From: "Schumaker, Anna" <Anna.Schumaker@netapp.com>
To: "fllinden@amazon.com" <fllinden@amazon.com>,
"linux-nfs@vger.kernel.org" <linux-nfs@vger.kernel.org>,
"trond.myklebust@hammerspace.com"
<trond.myklebust@hammerspace.com>
Subject: Re: [PATCH 05/13] NFSv4.2: add client side XDR handling for extended attributes
Date: Thu, 12 Mar 2020 20:49:41 +0000 [thread overview]
Message-ID: <a9eee7c7a57fecb85a273d339b8112bf360fba8f.camel@netapp.com> (raw)
In-Reply-To: <20200311195613.26108-6-fllinden@amazon.com>
Hi Frank,
On Wed, 2020-03-11 at 19:56 +0000, Frank van der Linden wrote:
> Define the argument and response structures that will be used for
> RFC 8276 extended attribute RPC calls, and implement the necessary
> functions to encode/decode the extended attribute operations.
>
> Signed-off-by: Frank van der Linden <fllinden@amazon.com>
> ---
> fs/nfs/nfs42xdr.c | 368
> ++++++++++++++++++++++++++++++++++++++++++++++++
> fs/nfs/nfs4xdr.c | 6 +
> include/linux/nfs_xdr.h | 59 +++++++-
> 3 files changed, 432 insertions(+), 1 deletion(-)
>
> diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c
> index 6712daa9d85b..ac45a1027523 100644
> --- a/fs/nfs/nfs42xdr.c
> +++ b/fs/nfs/nfs42xdr.c
> @@ -407,6 +407,212 @@ static void encode_layouterror(struct xdr_stream *xdr,
> encode_device_error(xdr, &args->errors[0]);
> }
>
> +#ifdef CONFIG_NFS_V4_2
This file is only compiled when CONFIG_NFS_V4_2=y, so there is no need for the
#ifdef here.
Anna
> +static void encode_setxattr(struct xdr_stream *xdr,
> + const struct nfs42_setxattrargs *arg,
> + struct compound_hdr *hdr)
> +{
> + __be32 *p;
> +
> + BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
> + BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
> +
> + encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
> + p = reserve_space(xdr, 4);
> + *p = cpu_to_be32(arg->xattr_flags);
> + encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
> + p = reserve_space(xdr, 4);
> + *p = cpu_to_be32(arg->xattr_len);
> + if (arg->xattr_len)
> + xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
> +}
> +
> +static int decode_setxattr(struct xdr_stream *xdr,
> + struct nfs4_change_info *cinfo)
> +{
> + int status;
> +
> + status = decode_op_hdr(xdr, OP_SETXATTR);
> + if (status)
> + goto out;
> + status = decode_change_info(xdr, cinfo);
> +out:
> + return status;
> +}
> +
> +
> +static void encode_getxattr(struct xdr_stream *xdr, const char *name,
> + struct compound_hdr *hdr)
> +{
> + encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
> + encode_string(xdr, strlen(name), name);
> +}
> +
> +static int decode_getxattr(struct xdr_stream *xdr,
> + struct nfs42_getxattrres *res,
> + struct rpc_rqst *req)
> +{
> + int status;
> + __be32 *p;
> + u32 len, rdlen;
> +
> + status = decode_op_hdr(xdr, OP_GETXATTR);
> + if (status)
> + return status;
> +
> + p = xdr_inline_decode(xdr, 4);
> + if (unlikely(!p))
> + return -EIO;
> +
> + len = be32_to_cpup(p);
> + if (len > req->rq_rcv_buf.page_len)
> + return -ERANGE;
> +
> + res->xattr_len = len;
> +
> + if (len > 0) {
> + rdlen = xdr_read_pages(xdr, len);
> + if (rdlen < len)
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +static void encode_removexattr(struct xdr_stream *xdr, const char *name,
> + struct compound_hdr *hdr)
> +{
> + encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
> + encode_string(xdr, strlen(name), name);
> +}
> +
> +
> +static int decode_removexattr(struct xdr_stream *xdr,
> + struct nfs4_change_info *cinfo)
> +{
> + int status;
> +
> + status = decode_op_hdr(xdr, OP_REMOVEXATTR);
> + if (status)
> + goto out;
> +
> + status = decode_change_info(xdr, cinfo);
> +out:
> + return status;
> +}
> +
> +static void encode_listxattrs(struct xdr_stream *xdr,
> + const struct nfs42_listxattrsargs *arg,
> + struct compound_hdr *hdr)
> +{
> + __be32 *p;
> +
> + encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz + 1, hdr);
> +
> + p = reserve_space(xdr, 12);
> + if (unlikely(!p))
> + return;
> +
> + p = xdr_encode_hyper(p, arg->cookie);
> + /*
> + * RFC 8276 says to specify the full max length of the LISTXATTRS
> + * XDR reply. Count is set to the XDR length of the names array
> + * plus the EOF marker. So, add the cookie and the names count.
> + */
> + *p = cpu_to_be32(arg->count + 8 + 4);
> +}
> +
> +static int decode_listxattrs(struct xdr_stream *xdr,
> + struct nfs42_listxattrsres *res)
> +{
> + int status;
> + __be32 *p;
> + u32 count, len, ulen;
> + size_t left, copied;
> + char *buf;
> +
> + status = decode_op_hdr(xdr, OP_LISTXATTRS);
> + if (status) {
> + /*
> + * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
> + * should be translated to ERANGE.
> + */
> + if (status == -ETOOSMALL)
> + status = -ERANGE;
> + goto out;
> + }
> +
> + p = xdr_inline_decode(xdr, 8);
> + if (unlikely(!p))
> + return -EIO;
> +
> + xdr_decode_hyper(p, &res->cookie);
> +
> + p = xdr_inline_decode(xdr, 4);
> + if (unlikely(!p))
> + return -EIO;
> +
> + left = res->xattr_len;
> + buf = res->xattr_buf;
> +
> + count = be32_to_cpup(p);
> + copied = 0;
> +
> + /*
> + * We have asked for enough room to encode the maximum number
> + * of possible attribute names, so everything should fit.
> + *
> + * But, don't rely on that assumption. Just decode entries
> + * until they don't fit anymore, just in case the server did
> + * something odd.
> + */
> + while (count--) {
> + p = xdr_inline_decode(xdr, 4);
> + if (unlikely(!p))
> + return -EIO;
> +
> + len = be32_to_cpup(p);
> + if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
> + status = -ERANGE;
> + goto out;
> + }
> +
> + p = xdr_inline_decode(xdr, len);
> + if (unlikely(!p))
> + return -EIO;
> +
> + ulen = len + XATTR_USER_PREFIX_LEN + 1;
> + if (buf) {
> + if (ulen > left) {
> + status = -ERANGE;
> + goto out;
> + }
> +
> + memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
> + memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
> +
> + buf[ulen - 1] = 0;
> + buf += ulen;
> + left -= ulen;
> + }
> + copied += ulen;
> + }
> +
> + p = xdr_inline_decode(xdr, 4);
> + if (unlikely(!p))
> + return -EIO;
> +
> + res->eof = be32_to_cpup(p);
> + res->copied = copied;
> +
> +out:
> + if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
> + status = -E2BIG;
> +
> + return status;
> +}
> +#endif
> +
> /*
> * Encode ALLOCATE request
> */
> @@ -1062,4 +1268,166 @@ static int nfs4_xdr_dec_layouterror(struct rpc_rqst
> *rqstp,
> return status;
> }
>
> +#ifdef CONFIG_NFS_V4_2
> +static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream
> *xdr,
> + const void *data)
> +{
> + const struct nfs42_setxattrargs *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_setxattr(xdr, args, &hdr);
> + encode_nops(&hdr);
> +}
> +
> +static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream
> *xdr,
> + void *data)
> +{
> + struct nfs42_setxattrres *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, req);
> + if (status)
> + goto out;
> + status = decode_putfh(xdr);
> + if (status)
> + goto out;
> +
> + status = decode_setxattr(xdr, &res->cinfo);
> +out:
> + return status;
> +}
> +
> +static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream
> *xdr,
> + const void *data)
> +{
> + const struct nfs42_getxattrargs *args = data;
> + struct compound_hdr hdr = {
> + .minorversion = nfs4_xdr_minorversion(&args->seq_args),
> + };
> + size_t plen;
> +
> + encode_compound_hdr(xdr, req, &hdr);
> + encode_sequence(xdr, &args->seq_args, &hdr);
> + encode_putfh(xdr, args->fh, &hdr);
> + encode_getxattr(xdr, args->xattr_name, &hdr);
> +
> + plen = args->xattr_len ? args->xattr_len : XATTR_SIZE_MAX;
> +
> + rpc_prepare_reply_pages(req, args->xattr_pages, 0, plen,
> + hdr.replen);
> + req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
> +
> + encode_nops(&hdr);
> +}
> +
> +static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
> + struct xdr_stream *xdr, void *data)
> +{
> + struct nfs42_getxattrres *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_getxattr(xdr, res, rqstp);
> +out:
> + return status;
> +}
> +
> +static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
> + struct xdr_stream *xdr, const void *data)
> +{
> + const struct nfs42_listxattrsargs *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_listxattrs(xdr, args, &hdr);
> +
> + rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count,
> + hdr.replen);
> + req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
> +
> + encode_nops(&hdr);
> +}
> +
> +static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
> + struct xdr_stream *xdr, void *data)
> +{
> + struct nfs42_listxattrsres *res = data;
> + struct compound_hdr hdr;
> + int status;
> +
> + xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE);
> +
> + 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_listxattrs(xdr, res);
> +out:
> + return status;
> +}
> +
> +static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
> + struct xdr_stream *xdr, const void *data)
> +{
> + const struct nfs42_removexattrargs *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_removexattr(xdr, args->xattr_name, &hdr);
> + encode_nops(&hdr);
> +}
> +
> +static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
> + struct xdr_stream *xdr, void *data)
> +{
> + struct nfs42_removexattrres *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, req);
> + if (status)
> + goto out;
> + status = decode_putfh(xdr);
> + if (status)
> + goto out;
> +
> + status = decode_removexattr(xdr, &res->cinfo);
> +out:
> + return status;
> +}
> +#endif
> #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index bebc087a1433..9e1ced791789 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -7479,6 +7479,8 @@ static struct {
> { NFS4ERR_SYMLINK, -ELOOP },
> { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
> { NFS4ERR_DEADLOCK, -EDEADLK },
> + { NFS4ERR_NOXATTR, -ENODATA },
> + { NFS4ERR_XATTR2BIG, -E2BIG },
> { -1, -EIO }
> };
>
> @@ -7607,6 +7609,10 @@ const struct rpc_procinfo nfs4_procedures[] = {
> PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify),
> PROC(LOOKUPP, enc_lookupp, dec_lookupp),
> PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror),
> + PROC42(GETXATTR, enc_getxattr, dec_getxattr),
> + PROC42(SETXATTR, enc_setxattr, dec_setxattr),
> + PROC42(LISTXATTRS, enc_listxattrs, dec_listxattrs),
> + PROC42(REMOVEXATTR, enc_removexattr, dec_removexattr),
> };
>
> static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)];
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 5076fe42c693..685deed805e8 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -1497,7 +1497,64 @@ struct nfs42_seek_res {
> u32 sr_eof;
> u64 sr_offset;
> };
> -#endif
> +
> +struct nfs42_setxattrargs {
> + struct nfs4_sequence_args seq_args;
> + struct nfs_fh *fh;
> + const char *xattr_name;
> + u32 xattr_flags;
> + size_t xattr_len;
> + struct page **xattr_pages;
> +};
> +
> +struct nfs42_setxattrres {
> + struct nfs4_sequence_res seq_res;
> + struct nfs4_change_info cinfo;
> +};
> +
> +struct nfs42_getxattrargs {
> + struct nfs4_sequence_args seq_args;
> + struct nfs_fh *fh;
> + const char *xattr_name;
> + size_t xattr_len;
> + struct page **xattr_pages;
> +};
> +
> +struct nfs42_getxattrres {
> + struct nfs4_sequence_res seq_res;
> + size_t xattr_len;
> +};
> +
> +struct nfs42_listxattrsargs {
> + struct nfs4_sequence_args seq_args;
> + struct nfs_fh *fh;
> + u32 count;
> + u64 cookie;
> + struct page **xattr_pages;
> +};
> +
> +struct nfs42_listxattrsres {
> + struct nfs4_sequence_res seq_res;
> + struct page *scratch;
> + void *xattr_buf;
> + size_t xattr_len;
> + u64 cookie;
> + bool eof;
> + size_t copied;
> +};
> +
> +struct nfs42_removexattrargs {
> + struct nfs4_sequence_args seq_args;
> + struct nfs_fh *fh;
> + const char *xattr_name;
> +};
> +
> +struct nfs42_removexattrres {
> + struct nfs4_sequence_res seq_res;
> + struct nfs4_change_info cinfo;
> +};
> +
> +#endif /* CONFIG_NFS_V4_2 */
>
> struct nfs_page;
>
next prev parent reply other threads:[~2020-03-12 20:49 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-11 19:56 [PATCH 00/13] client side user xattr (RFC8276) support Frank van der Linden
2020-03-11 19:56 ` [PATCH 01/13] nfs,nfsd: NFSv4.2 extended attribute protocol definitions Frank van der Linden
2020-03-11 19:56 ` [PATCH 02/13] nfs: add client side only definitions for user xattrs Frank van der Linden
2020-03-11 19:56 ` [PATCH 03/13] NFSv4.2: query the server for extended attribute support Frank van der Linden
2020-03-12 16:15 ` Mkrtchyan, Tigran
2020-03-12 20:51 ` Frank van der Linden
2020-03-12 21:15 ` Frank van der Linden
2020-03-13 11:11 ` Mkrtchyan, Tigran
2020-03-13 13:50 ` Trond Myklebust
2020-03-13 14:19 ` Mkrtchyan, Tigran
2020-03-13 17:10 ` Trond Myklebust
2020-03-13 17:55 ` Frank van der Linden
2020-03-11 19:56 ` [PATCH 04/13] NFSv4.2: define limits and sizes for user xattr handling Frank van der Linden
2020-03-12 20:35 ` Schumaker, Anna
2020-03-11 19:56 ` [PATCH 05/13] NFSv4.2: add client side XDR handling for extended attributes Frank van der Linden
2020-03-12 20:49 ` Schumaker, Anna [this message]
2020-03-11 19:56 ` [PATCH 06/13] nfs: define nfs_access_get_cached function Frank van der Linden
2020-03-11 19:56 ` [PATCH 07/13] NFSv4.2: query the extended attribute access bits Frank van der Linden
2020-03-11 19:56 ` [PATCH 08/13] nfs: modify update_changeattr to deal with regular files Frank van der Linden
2020-03-11 19:56 ` [PATCH 09/13] nfs: define and use the NFS_INO_INVALID_XATTR flag Frank van der Linden
[not found] ` <20200324060215.GD11705@shao2-debian>
2020-03-24 16:21 ` [nfs] c5654df66d: stress-ng.msg.ops_per_sec 15.5% improvement Frank van der Linden
2020-03-11 19:56 ` [PATCH 10/13] nfs: make the buf_to_pages_noslab function available to the nfs code Frank van der Linden
2020-03-12 20:36 ` Schumaker, Anna
2020-03-11 19:56 ` [PATCH 11/13] NFSv4.2: add the extended attribute proc functions Frank van der Linden
2020-03-11 19:56 ` [PATCH 12/13] NFSv4.2: hook in the user extended attribute handlers Frank van der Linden
2020-03-11 19:56 ` [PATCH 13/13] NFSv4.2: add client side xattr caching Frank van der Linden
2020-03-12 20:39 ` Schumaker, Anna
2020-03-12 20:48 ` Schumaker, Anna
2020-03-12 19:06 ` [PATCH 00/13] client side user xattr (RFC8276) support Mkrtchyan, Tigran
2020-03-12 20:09 ` Anna Schumaker
2020-03-16 15:50 ` Frank van der Linden
2020-03-17 23:03 ` Frank van der Linden
2020-03-19 14:39 ` J. Bruce Fields
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a9eee7c7a57fecb85a273d339b8112bf360fba8f.camel@netapp.com \
--to=anna.schumaker@netapp.com \
--cc=fllinden@amazon.com \
--cc=linux-nfs@vger.kernel.org \
--cc=trond.myklebust@hammerspace.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox