Skip to content

Commit

Permalink
NFSv4.2: Clean up: move decode_*xattr() functions
Browse files Browse the repository at this point in the history
Move them out of the encode_*() section and into the decode_*() section
where it belongs.

Signed-off-by: Anna Schumaker <[email protected]>
Signed-off-by: Trond Myklebust <[email protected]>
  • Loading branch information
amschuma-ntap authored and Trond Myklebust committed Jun 19, 2023
1 parent fd42ba8 commit 04b4c9f
Showing 1 changed file with 162 additions and 164 deletions.
326 changes: 162 additions & 164 deletions fs/nfs/nfs42xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,86 +464,20 @@ static void encode_setxattr(struct xdr_stream *xdr,
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);

/*
* Only check against the page length here. The actual
* requested length may be smaller, but that is only
* checked against after possibly caching a valid reply.
*/
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)
Expand All @@ -565,104 +499,6 @@ static void encode_listxattrs(struct xdr_stream *xdr,
*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;
/*
* Special case: for LISTXATTRS, NFS4ERR_NOXATTR
* should be translated to success with zero-length reply.
*/
if (status == -ENODATA) {
res->eof = true;
status = 0;
}
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;
}

/*
* Encode ALLOCATE request
*/
Expand Down Expand Up @@ -1192,6 +1028,168 @@ static int decode_layouterror(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_LAYOUTERROR);
}

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 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);

/*
* Only check against the page length here. The actual
* requested length may be smaller, but that is only
* checked against after possibly caching a valid reply.
*/
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 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 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;
/*
* Special case: for LISTXATTRS, NFS4ERR_NOXATTR
* should be translated to success with zero-length reply.
*/
if (status == -ENODATA) {
res->eof = true;
status = 0;
}
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;
}

/*
* Decode ALLOCATE request
*/
Expand Down

0 comments on commit 04b4c9f

Please sign in to comment.