Skip to content

Commit

Permalink
Merge tag 'nfs-for-5.10-1' of git://git.linux-nfs.org/projects/anna/l…
Browse files Browse the repository at this point in the history
…inux-nfs

Pull NFS client updates from Anna Schumaker:
 "Stable Fixes:
   - Wait for stateid updates after CLOSE/OPEN_DOWNGRADE # v5.4+
   - Fix nfs_path in case of a rename retry
   - Support EXCHID4_FLAG_SUPP_FENCE_OPS v4.2 EXCHANGE_ID flag

  New features and improvements:
   - Replace dprintk() calls with tracepoints
   - Make cache consistency bitmap dynamic
   - Added support for the NFS v4.2 READ_PLUS operation
   - Improvements to net namespace uniquifier

  Other bugfixes and cleanups:
   - Remove redundant clnt pointer
   - Don't update timeout values on connection resets
   - Remove redundant tracepoints
   - Various cleanups to comments
   - Fix oops when trying to use copy_file_range with v4.0 source server
   - Improvements to flexfiles mirrors
   - Add missing 'local_lock=posix' mount option"

* tag 'nfs-for-5.10-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (55 commits)
  NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
  NFSv4: Fix up RCU annotations for struct nfs_netns_client
  NFS: Only reference user namespace from nfs4idmap struct instead of cred
  nfs: add missing "posix" local_lock constant table definition
  NFSv4: Use the net namespace uniquifier if it is set
  NFSv4: Clean up initialisation of uniquified client id strings
  NFS: Decode a full READ_PLUS reply
  SUNRPC: Add an xdr_align_data() function
  NFS: Add READ_PLUS hole segment decoding
  SUNRPC: Add the ability to expand holes in data pages
  SUNRPC: Split out _shift_data_right_tail()
  SUNRPC: Split out xdr_realign_pages() from xdr_align_pages()
  NFS: Add READ_PLUS data segment support
  NFS: Use xdr_page_pos() in NFSv4 decode_getacl()
  SUNRPC: Implement a xdr_page_pos() function
  SUNRPC: Split out a function for setting current page
  NFS: fix nfs_path in case of a rename retry
  fs: nfs: return per memcg count for xattr shrinkers
  NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE
  nfs: remove incorrect fallthrough label
  ...
  • Loading branch information
torvalds committed Oct 20, 2020
2 parents 4962a85 + 8c39076 commit 59f0e7e
Show file tree
Hide file tree
Showing 36 changed files with 989 additions and 502 deletions.
2 changes: 1 addition & 1 deletion fs/lockd/mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ void nsm_release(struct nsm_handle *nsm)
/*
* XDR functions for NSM.
*
* See http://www.opengroup.org/ for details on the Network
* See https://www.opengroup.org/ for details on the Network
* Status Monitor wire protocol.
*/

Expand Down
1 change: 1 addition & 0 deletions fs/nfs/fs_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ enum {
static const struct constant_table nfs_param_enums_local_lock[] = {
{ "all", Opt_local_lock_all },
{ "flock", Opt_local_lock_flock },
{ "posix", Opt_local_lock_posix },
{ "none", Opt_local_lock_none },
{}
};
Expand Down
12 changes: 8 additions & 4 deletions fs/nfs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
/*
* nfs_path - reconstruct the path given an arbitrary dentry
* @base - used to return pointer to the end of devname part of path
* @dentry - pointer to dentry
* @dentry_in - pointer to dentry
* @buffer - result buffer
* @buflen - length of buffer
* @buflen_in - length of buffer
* @flags - options (see below)
*
* Helper function for constructing the server pathname
Expand All @@ -49,15 +49,19 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
* the original device (export) name
* (if unset, the original name is returned verbatim)
*/
char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
unsigned flags)
char *nfs_path(char **p, struct dentry *dentry_in, char *buffer,
ssize_t buflen_in, unsigned flags)
{
char *end;
int namelen;
unsigned seq;
const char *base;
struct dentry *dentry;
ssize_t buflen;

rename_retry:
buflen = buflen_in;
dentry = dentry_in;
end = buffer+buflen;
*--end = '\0';
buflen--;
Expand Down
5 changes: 2 additions & 3 deletions fs/nfs/nfs42xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ struct nfs4_xattr_bucket {

struct nfs4_xattr_cache {
struct kref ref;
spinlock_t hash_lock; /* protects hashtable and lru */
struct nfs4_xattr_bucket buckets[NFS4_XATTR_HASH_SIZE];
struct list_head lru;
struct list_head dispose;
Expand Down Expand Up @@ -882,7 +881,7 @@ nfs4_xattr_cache_count(struct shrinker *shrink, struct shrink_control *sc)
{
unsigned long count;

count = list_lru_count(&nfs4_xattr_cache_lru);
count = list_lru_shrink_count(&nfs4_xattr_cache_lru, sc);
return vfs_pressure_ratio(count);
}

Expand Down Expand Up @@ -976,7 +975,7 @@ nfs4_xattr_entry_count(struct shrinker *shrink, struct shrink_control *sc)
lru = (shrink == &nfs4_xattr_large_entry_shrinker) ?
&nfs4_xattr_large_entry_lru : &nfs4_xattr_entry_lru;

count = list_lru_count(lru);
count = list_lru_shrink_count(lru, sc);
return vfs_pressure_ratio(count);
}

Expand Down
167 changes: 167 additions & 0 deletions fs/nfs/nfs42xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
encode_fallocate_maxsz)
#define decode_deallocate_maxsz (op_decode_hdr_maxsz)
#define encode_read_plus_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + 3)
#define NFS42_READ_PLUS_SEGMENT_SIZE (1 /* data_content4 */ + \
2 /* data_info4.di_offset */ + \
2 /* data_info4.di_length */)
#define decode_read_plus_maxsz (op_decode_hdr_maxsz + \
1 /* rpr_eof */ + \
1 /* rpr_contents count */ + \
2 * NFS42_READ_PLUS_SEGMENT_SIZE)
#define encode_seek_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + \
2 /* offset */ + \
Expand Down Expand Up @@ -128,6 +137,14 @@
decode_putfh_maxsz + \
decode_deallocate_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_read_plus_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_read_plus_maxsz)
#define NFS4_dec_read_plus_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_read_plus_maxsz)
#define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
Expand Down Expand Up @@ -324,6 +341,16 @@ static void encode_deallocate(struct xdr_stream *xdr,
encode_fallocate(xdr, args);
}

static void encode_read_plus(struct xdr_stream *xdr,
const struct nfs_pgio_args *args,
struct compound_hdr *hdr)
{
encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
encode_nfs4_stateid(xdr, &args->stateid);
encode_uint64(xdr, args->offset);
encode_uint32(xdr, args->count);
}

static void encode_seek(struct xdr_stream *xdr,
const struct nfs42_seek_args *args,
struct compound_hdr *hdr)
Expand Down Expand Up @@ -722,6 +749,28 @@ static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
encode_nops(&hdr);
}

/*
* Encode READ_PLUS request
*/
static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
const struct nfs_pgio_args *args = data;
struct compound_hdr hdr = {
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
};

encode_compound_hdr(xdr, req, &hdr);
encode_sequence(xdr, &args->seq_args, &hdr);
encode_putfh(xdr, args->fh, &hdr);
encode_read_plus(xdr, args, &hdr);

rpc_prepare_reply_pages(req, args->pages, args->pgbase,
args->count, hdr.replen);
encode_nops(&hdr);
}

/*
* Encode SEEK request
*/
Expand Down Expand Up @@ -970,6 +1019,97 @@ static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *re
return decode_op_hdr(xdr, OP_DEALLOCATE);
}

static int decode_read_plus_data(struct xdr_stream *xdr, struct nfs_pgio_res *res,
uint32_t *eof)
{
uint32_t count, recvd;
uint64_t offset;
__be32 *p;

p = xdr_inline_decode(xdr, 8 + 4);
if (unlikely(!p))
return -EIO;

p = xdr_decode_hyper(p, &offset);
count = be32_to_cpup(p);
recvd = xdr_align_data(xdr, res->count, count);
res->count += recvd;

if (count > recvd) {
dprintk("NFS: server cheating in read reply: "
"count %u > recvd %u\n", count, recvd);
*eof = 0;
return 1;
}

return 0;
}

static int decode_read_plus_hole(struct xdr_stream *xdr, struct nfs_pgio_res *res,
uint32_t *eof)
{
uint64_t offset, length, recvd;
__be32 *p;

p = xdr_inline_decode(xdr, 8 + 8);
if (unlikely(!p))
return -EIO;

p = xdr_decode_hyper(p, &offset);
p = xdr_decode_hyper(p, &length);
recvd = xdr_expand_hole(xdr, res->count, length);
res->count += recvd;

if (recvd < length) {
*eof = 0;
return 1;
}
return 0;
}

static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
{
uint32_t eof, segments, type;
int status, i;
__be32 *p;

status = decode_op_hdr(xdr, OP_READ_PLUS);
if (status)
return status;

p = xdr_inline_decode(xdr, 4 + 4);
if (unlikely(!p))
return -EIO;

eof = be32_to_cpup(p++);
segments = be32_to_cpup(p++);
if (segments == 0)
goto out;

for (i = 0; i < segments; i++) {
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
return -EIO;

type = be32_to_cpup(p++);
if (type == NFS4_CONTENT_DATA)
status = decode_read_plus_data(xdr, res, &eof);
else if (type == NFS4_CONTENT_HOLE)
status = decode_read_plus_hole(xdr, res, &eof);
else
return -EINVAL;

if (status < 0)
return status;
if (status > 0)
break;
}

out:
res->eof = eof;
return 0;
}

static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
{
int status;
Expand Down Expand Up @@ -1146,6 +1286,33 @@ static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
return status;
}

/*
* Decode READ_PLUS request
*/
static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
struct xdr_stream *xdr,
void *data)
{
struct nfs_pgio_res *res = data;
struct compound_hdr hdr;
int status;

status = decode_compound_hdr(xdr, &hdr);
if (status)
goto out;
status = decode_sequence(xdr, &res->seq_res, rqstp);
if (status)
goto out;
status = decode_putfh(xdr);
if (status)
goto out;
status = decode_read_plus(xdr, res);
if (!status)
status = res->count;
out:
return status;
}

/*
* Decode SEEK request
*/
Expand Down
8 changes: 8 additions & 0 deletions fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,14 @@ static inline bool nfs4_stateid_is_newer(const nfs4_stateid *s1, const nfs4_stat
return (s32)(be32_to_cpu(s1->seqid) - be32_to_cpu(s2->seqid)) > 0;
}

static inline bool nfs4_stateid_is_next(const nfs4_stateid *s1, const nfs4_stateid *s2)
{
u32 seq1 = be32_to_cpu(s1->seqid);
u32 seq2 = be32_to_cpu(s2->seqid);

return seq2 == seq1 + 1U || (seq2 == 1U && seq1 == 0xffffffffU);
}

static inline bool nfs4_stateid_match_or_older(const nfs4_stateid *dst, const nfs4_stateid *src)
{
return nfs4_stateid_match_other(dst, src) &&
Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/nfs4client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,8 @@ static int nfs4_server_common_setup(struct nfs_server *server,
server->caps |= server->nfs_client->cl_mvops->init_caps;
if (server->flags & NFS_MOUNT_NORDIRPLUS)
server->caps &= ~NFS_CAP_READDIRPLUS;
if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA)
server->caps &= ~NFS_CAP_READ_PLUS;
/*
* Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
* authentication.
Expand Down
3 changes: 2 additions & 1 deletion fs/nfs/nfs4file.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
/* Only offload copy if superblock is the same */
if (file_in->f_op != &nfs4_file_operations)
return -EXDEV;
if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY) ||
!nfs_server_capable(file_inode(file_in), NFS_CAP_COPY))
return -EOPNOTSUPP;
if (file_inode(file_in) == file_inode(file_out))
return -EOPNOTSUPP;
Expand Down
15 changes: 8 additions & 7 deletions fs/nfs/nfs4idmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <keys/user-type.h>
#include <keys/request_key_auth-type.h>
#include <linux/module.h>
#include <linux/user_namespace.h>

#include "internal.h"
#include "netns.h"
Expand All @@ -69,13 +70,13 @@ struct idmap {
struct rpc_pipe *idmap_pipe;
struct idmap_legacy_upcalldata *idmap_upcall_data;
struct mutex idmap_mutex;
const struct cred *cred;
struct user_namespace *user_ns;
};

static struct user_namespace *idmap_userns(const struct idmap *idmap)
{
if (idmap && idmap->cred)
return idmap->cred->user_ns;
if (idmap && idmap->user_ns)
return idmap->user_ns;
return &init_user_ns;
}

Expand Down Expand Up @@ -286,7 +287,7 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
if (ret < 0)
return ERR_PTR(ret);

if (!idmap->cred || idmap->cred->user_ns == &init_user_ns)
if (!idmap->user_ns || idmap->user_ns == &init_user_ns)
rkey = request_key(&key_type_id_resolver, desc, "");
if (IS_ERR(rkey)) {
mutex_lock(&idmap->idmap_mutex);
Expand Down Expand Up @@ -462,7 +463,7 @@ nfs_idmap_new(struct nfs_client *clp)
return -ENOMEM;

mutex_init(&idmap->idmap_mutex);
idmap->cred = get_cred(clp->cl_rpcclient->cl_cred);
idmap->user_ns = get_user_ns(clp->cl_rpcclient->cl_cred->user_ns);

rpc_init_pipe_dir_object(&idmap->idmap_pdo,
&nfs_idmap_pipe_dir_object_ops,
Expand All @@ -486,7 +487,7 @@ nfs_idmap_new(struct nfs_client *clp)
err_destroy_pipe:
rpc_destroy_pipe_data(idmap->idmap_pipe);
err:
put_cred(idmap->cred);
get_user_ns(idmap->user_ns);
kfree(idmap);
return error;
}
Expand All @@ -503,7 +504,7 @@ nfs_idmap_delete(struct nfs_client *clp)
&clp->cl_rpcclient->cl_pipedir_objects,
&idmap->idmap_pdo);
rpc_destroy_pipe_data(idmap->idmap_pipe);
put_cred(idmap->cred);
put_user_ns(idmap->user_ns);
kfree(idmap);
}

Expand Down
Loading

0 comments on commit 59f0e7e

Please sign in to comment.