summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c346
1 files changed, 132 insertions, 214 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5f940d2a136b..2c61c6b8ae09 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -159,6 +159,25 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
*/
unsigned int avail = (char *)argp->end - (char *)argp->p;
__be32 *p;
+
+ if (argp->pagelen == 0) {
+ struct kvec *vec = &argp->rqstp->rq_arg.tail[0];
+
+ if (!argp->tail) {
+ argp->tail = true;
+ avail = vec->iov_len;
+ argp->p = vec->iov_base;
+ argp->end = vec->iov_base + avail;
+ }
+
+ if (avail < nbytes)
+ return NULL;
+
+ p = argp->p;
+ argp->p += XDR_QUADLEN(nbytes);
+ return p;
+ }
+
if (avail + argp->pagelen < nbytes)
return NULL;
if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
@@ -1778,7 +1797,7 @@ nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
-static nfsd4_dec nfsd4_dec_ops[] = {
+static const nfsd4_dec nfsd4_dec_ops[] = {
[OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
[OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
[OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
@@ -1927,6 +1946,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
op->opnum = OP_ILLEGAL;
op->status = nfserr_op_illegal;
}
+ op->opdesc = OPDESC(op);
/*
* We'll try to cache the result in the DRC if any one
* op in the compound wants to be cached:
@@ -3102,14 +3122,12 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, 8);
- if (!p)
- return nfserr_resource;
- *p++ = cpu_to_be32(access->ac_supported);
- *p++ = cpu_to_be32(access->ac_resp_access);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, 8);
+ if (!p)
+ return nfserr_resource;
+ *p++ = cpu_to_be32(access->ac_supported);
+ *p++ = cpu_to_be32(access->ac_resp_access);
+ return 0;
}
static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
@@ -3117,17 +3135,15 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp,
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 8);
- if (!p)
- return nfserr_resource;
- p = xdr_encode_opaque_fixed(p, bcts->sessionid.data,
- NFS4_MAX_SESSIONID_LEN);
- *p++ = cpu_to_be32(bcts->dir);
- /* Upshifting from TCP to RDMA is not supported */
- *p++ = cpu_to_be32(0);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 8);
+ if (!p)
+ return nfserr_resource;
+ p = xdr_encode_opaque_fixed(p, bcts->sessionid.data,
+ NFS4_MAX_SESSIONID_LEN);
+ *p++ = cpu_to_be32(bcts->dir);
+ /* Upshifting from TCP to RDMA is not supported */
+ *p++ = cpu_to_be32(0);
+ return 0;
}
static __be32
@@ -3135,10 +3151,7 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
{
struct xdr_stream *xdr = &resp->xdr;
- if (!nfserr)
- nfserr = nfsd4_encode_stateid(xdr, &close->cl_stateid);
-
- return nfserr;
+ return nfsd4_encode_stateid(xdr, &close->cl_stateid);
}
@@ -3148,14 +3161,12 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
- if (!p)
- return nfserr_resource;
- p = xdr_encode_opaque_fixed(p, commit->co_verf.data,
+ p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
+ if (!p)
+ return nfserr_resource;
+ p = xdr_encode_opaque_fixed(p, commit->co_verf.data,
NFS4_VERIFIER_SIZE);
- }
- return nfserr;
+ return 0;
}
static __be32
@@ -3164,15 +3175,13 @@ nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, 20);
- if (!p)
- return nfserr_resource;
- encode_cinfo(p, &create->cr_cinfo);
- nfserr = nfsd4_encode_bitmap(xdr, create->cr_bmval[0],
- create->cr_bmval[1], create->cr_bmval[2]);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, 20);
+ if (!p)
+ return nfserr_resource;
+ encode_cinfo(p, &create->cr_cinfo);
+ nfserr = nfsd4_encode_bitmap(xdr, create->cr_bmval[0],
+ create->cr_bmval[1], create->cr_bmval[2]);
+ return 0;
}
static __be32
@@ -3181,13 +3190,8 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
struct svc_fh *fhp = getattr->ga_fhp;
struct xdr_stream *xdr = &resp->xdr;
- if (nfserr)
- return nfserr;
-
- nfserr = nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry,
- getattr->ga_bmval,
- resp->rqstp, 0);
- return nfserr;
+ return nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry,
+ getattr->ga_bmval, resp->rqstp, 0);
}
static __be32
@@ -3198,14 +3202,12 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
unsigned int len;
__be32 *p;
- if (!nfserr) {
- len = fhp->fh_handle.fh_size;
- p = xdr_reserve_space(xdr, len + 4);
- if (!p)
- return nfserr_resource;
- p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len);
- }
- return nfserr;
+ len = fhp->fh_handle.fh_size;
+ p = xdr_reserve_space(xdr, len + 4);
+ if (!p)
+ return nfserr_resource;
+ p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len);
+ return 0;
}
/*
@@ -3275,10 +3277,7 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
{
struct xdr_stream *xdr = &resp->xdr;
- if (!nfserr)
- nfserr = nfsd4_encode_stateid(xdr, &locku->lu_stateid);
-
- return nfserr;
+ return nfsd4_encode_stateid(xdr, &locku->lu_stateid);
}
@@ -3288,13 +3287,11 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, 20);
- if (!p)
- return nfserr_resource;
- p = encode_cinfo(p, &link->li_cinfo);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, 20);
+ if (!p)
+ return nfserr_resource;
+ p = encode_cinfo(p, &link->li_cinfo);
+ return 0;
}
@@ -3304,12 +3301,9 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (nfserr)
- goto out;
-
nfserr = nfsd4_encode_stateid(xdr, &open->op_stateid);
if (nfserr)
- goto out;
+ return nfserr;
p = xdr_reserve_space(xdr, 24);
if (!p)
return nfserr_resource;
@@ -3319,7 +3313,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
nfserr = nfsd4_encode_bitmap(xdr, open->op_bmval[0], open->op_bmval[1],
open->op_bmval[2]);
if (nfserr)
- goto out;
+ return nfserr;
p = xdr_reserve_space(xdr, 4);
if (!p)
@@ -3392,8 +3386,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
BUG();
}
/* XXX save filehandle here */
-out:
- return nfserr;
+ return 0;
}
static __be32
@@ -3401,10 +3394,7 @@ nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct
{
struct xdr_stream *xdr = &resp->xdr;
- if (!nfserr)
- nfserr = nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid);
-
- return nfserr;
+ return nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid);
}
static __be32
@@ -3412,10 +3402,7 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struc
{
struct xdr_stream *xdr = &resp->xdr;
- if (!nfserr)
- nfserr = nfsd4_encode_stateid(xdr, &od->od_stateid);
-
- return nfserr;
+ return nfsd4_encode_stateid(xdr, &od->od_stateid);
}
static __be32 nfsd4_encode_splice_read(
@@ -3552,20 +3539,15 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
struct raparms *ra = NULL;
__be32 *p;
- if (nfserr)
- goto out;
-
p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */
if (!p) {
WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags));
- nfserr = nfserr_resource;
- goto out;
+ return nfserr_resource;
}
if (resp->xdr.buf->page_len &&
test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) {
WARN_ON_ONCE(1);
- nfserr = nfserr_resource;
- goto out;
+ return nfserr_resource;
}
xdr_commit_encode(xdr);
@@ -3589,9 +3571,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
if (nfserr)
xdr_truncate_encode(xdr, starting_len);
-out:
- if (file)
- fput(file);
return nfserr;
}
@@ -3605,9 +3584,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
int length_offset = xdr->buf->len;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, 4);
if (!p)
return nfserr_resource;
@@ -3651,9 +3627,6 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
int starting_len = xdr->buf->len;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
if (!p)
return nfserr_resource;
@@ -3739,13 +3712,11 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, 20);
- if (!p)
- return nfserr_resource;
- p = encode_cinfo(p, &remove->rm_cinfo);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, 20);
+ if (!p)
+ return nfserr_resource;
+ p = encode_cinfo(p, &remove->rm_cinfo);
+ return 0;
}
static __be32
@@ -3754,19 +3725,16 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, 40);
- if (!p)
- return nfserr_resource;
- p = encode_cinfo(p, &rename->rn_sinfo);
- p = encode_cinfo(p, &rename->rn_tinfo);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, 40);
+ if (!p)
+ return nfserr_resource;
+ p = encode_cinfo(p, &rename->rn_sinfo);
+ p = encode_cinfo(p, &rename->rn_tinfo);
+ return 0;
}
static __be32
-nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
- __be32 nfserr, struct svc_export *exp)
+nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp)
{
u32 i, nflavs, supported;
struct exp_flavor_info *flavs;
@@ -3774,9 +3742,6 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
__be32 *p, *flavorsp;
static bool report = true;
- if (nfserr)
- goto out;
- nfserr = nfserr_resource;
if (exp->ex_nflavors) {
flavs = exp->ex_flavors;
nflavs = exp->ex_nflavors;
@@ -3800,7 +3765,7 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
supported = 0;
p = xdr_reserve_space(xdr, 4);
if (!p)
- goto out;
+ return nfserr_resource;
flavorsp = p++; /* to be backfilled later */
for (i = 0; i < nflavs; i++) {
@@ -3812,7 +3777,7 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
p = xdr_reserve_space(xdr, 4 + 4 +
XDR_LEN(info.oid.len) + 4 + 4);
if (!p)
- goto out;
+ return nfserr_resource;
*p++ = cpu_to_be32(RPC_AUTH_GSS);
p = xdr_encode_opaque(p, info.oid.data, info.oid.len);
*p++ = cpu_to_be32(info.qop);
@@ -3821,7 +3786,7 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
supported++;
p = xdr_reserve_space(xdr, 4);
if (!p)
- goto out;
+ return nfserr_resource;
*p++ = cpu_to_be32(pf);
} else {
if (report)
@@ -3833,11 +3798,7 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
if (nflavs != supported)
report = false;
*flavorsp = htonl(supported);
- nfserr = 0;
-out:
- if (exp)
- exp_put(exp);
- return nfserr;
+ return 0;
}
static __be32
@@ -3846,7 +3807,7 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
{
struct xdr_stream *xdr = &resp->xdr;
- return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->si_exp);
+ return nfsd4_do_encode_secinfo(xdr, secinfo->si_exp);
}
static __be32
@@ -3855,7 +3816,7 @@ nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr,
{
struct xdr_stream *xdr = &resp->xdr;
- return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->sin_exp);
+ return nfsd4_do_encode_secinfo(xdr, secinfo->sin_exp);
}
/*
@@ -3916,16 +3877,14 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (!nfserr) {
- p = xdr_reserve_space(xdr, 16);
- if (!p)
- return nfserr_resource;
- *p++ = cpu_to_be32(write->wr_bytes_written);
- *p++ = cpu_to_be32(write->wr_how_written);
- p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
- NFS4_VERIFIER_SIZE);
- }
- return nfserr;
+ p = xdr_reserve_space(xdr, 16);
+ if (!p)
+ return nfserr_resource;
+ *p++ = cpu_to_be32(write->wr_bytes_written);
+ *p++ = cpu_to_be32(write->wr_how_written);
+ p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
+ NFS4_VERIFIER_SIZE);
+ return 0;
}
static __be32
@@ -3938,12 +3897,8 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
char *server_scope;
int major_id_sz;
int server_scope_sz;
- int status = 0;
uint64_t minor_id = 0;
- if (nfserr)
- return nfserr;
-
major_id = utsname()->nodename;
major_id_sz = strlen(major_id);
server_scope = utsname()->nodename;
@@ -3968,19 +3923,19 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
break;
case SP4_MACH_CRED:
/* spo_must_enforce bitmap: */
- status = nfsd4_encode_bitmap(xdr,
+ nfserr = nfsd4_encode_bitmap(xdr,
exid->spo_must_enforce[0],
exid->spo_must_enforce[1],
exid->spo_must_enforce[2]);
- if (status)
- goto out;
+ if (nfserr)
+ return nfserr;
/* spo_must_allow bitmap: */
- status = nfsd4_encode_bitmap(xdr,
+ nfserr = nfsd4_encode_bitmap(xdr,
exid->spo_must_allow[0],
exid->spo_must_allow[1],
exid->spo_must_allow[2]);
- if (status)
- goto out;
+ if (nfserr)
+ return nfserr;
break;
default:
WARN_ON_ONCE(1);
@@ -4007,8 +3962,6 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
/* Implementation id */
*p++ = cpu_to_be32(0); /* zero length nfs_impl_id4 array */
return 0;
-out:
- return status;
}
static __be32
@@ -4018,9 +3971,6 @@ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr,
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, 24);
if (!p)
return nfserr_resource;
@@ -4074,9 +4024,6 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 20);
if (!p)
return nfserr_resource;
@@ -4101,9 +4048,6 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
struct nfsd4_test_stateid_id *stateid, *next;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, 4 + (4 * test_stateid->ts_num_ids));
if (!p)
return nfserr_resource;
@@ -4113,7 +4057,7 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
*p++ = stateid->ts_id_status;
}
- return nfserr;
+ return 0;
}
#ifdef CONFIG_NFSD_PNFS
@@ -4126,14 +4070,9 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
u32 starting_len = xdr->buf->len, needed_len;
__be32 *p;
- dprintk("%s: err %d\n", __func__, be32_to_cpu(nfserr));
- if (nfserr)
- goto out;
-
- nfserr = nfserr_resource;
p = xdr_reserve_space(xdr, 4);
if (!p)
- goto out;
+ return nfserr_resource;
*p++ = cpu_to_be32(gdev->gd_layout_type);
@@ -4149,42 +4088,33 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
*/
if (xdr->buf->len + 4 > gdev->gd_maxcount)
goto toosmall;
- goto out;
+ return nfserr;
}
}
- nfserr = nfserr_resource;
if (gdev->gd_notify_types) {
p = xdr_reserve_space(xdr, 4 + 4);
if (!p)
- goto out;
+ return nfserr_resource;
*p++ = cpu_to_be32(1); /* bitmap length */
*p++ = cpu_to_be32(gdev->gd_notify_types);
} else {
p = xdr_reserve_space(xdr, 4);
if (!p)
- goto out;
+ return nfserr_resource;
*p++ = 0;
}
- nfserr = 0;
-out:
- kfree(gdev->gd_device);
- dprintk("%s: done: %d\n", __func__, be32_to_cpu(nfserr));
- return nfserr;
-
+ return 0;
toosmall:
dprintk("%s: maxcount too small\n", __func__);
needed_len = xdr->buf->len + 4 /* notifications */;
xdr_truncate_encode(xdr, starting_len);
p = xdr_reserve_space(xdr, 4);
- if (!p) {
- nfserr = nfserr_resource;
- } else {
- *p++ = cpu_to_be32(needed_len);
- nfserr = nfserr_toosmall;
- }
- goto out;
+ if (!p)
+ return nfserr_resource;
+ *p++ = cpu_to_be32(needed_len);
+ return nfserr_toosmall;
}
static __be32
@@ -4195,14 +4125,9 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
const struct nfsd4_layout_ops *ops;
__be32 *p;
- dprintk("%s: err %d\n", __func__, nfserr);
- if (nfserr)
- goto out;
-
- nfserr = nfserr_resource;
p = xdr_reserve_space(xdr, 36 + sizeof(stateid_opaque_t));
if (!p)
- goto out;
+ return nfserr_resource;
*p++ = cpu_to_be32(1); /* we always set return-on-close */
*p++ = cpu_to_be32(lgp->lg_sid.si_generation);
@@ -4216,10 +4141,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
*p++ = cpu_to_be32(lgp->lg_layout_type);
ops = nfsd4_layout_ops[lgp->lg_layout_type];
- nfserr = ops->encode_layoutget(xdr, lgp);
-out:
- kfree(lgp->lg_content);
- return nfserr;
+ return ops->encode_layoutget(xdr, lgp);
}
static __be32
@@ -4229,9 +4151,6 @@ nfsd4_encode_layoutcommit(struct nfsd4_compoundres *resp, __be32 nfserr,
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, 4);
if (!p)
return nfserr_resource;
@@ -4243,7 +4162,7 @@ nfsd4_encode_layoutcommit(struct nfsd4_compoundres *resp, __be32 nfserr,
p = xdr_encode_hyper(p, lcp->lc_newsize);
}
- return nfs_ok;
+ return 0;
}
static __be32
@@ -4253,16 +4172,13 @@ nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr,
struct xdr_stream *xdr = &resp->xdr;
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(xdr, 4);
if (!p)
return nfserr_resource;
*p++ = cpu_to_be32(lrp->lrs_present);
if (lrp->lrs_present)
return nfsd4_encode_stateid(xdr, &lrp->lr_sid);
- return nfs_ok;
+ return 0;
}
#endif /* CONFIG_NFSD_PNFS */
@@ -4289,16 +4205,14 @@ nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
{
__be32 *p;
- if (!nfserr) {
- nfserr = nfsd42_encode_write_res(resp, &copy->cp_res);
- if (nfserr)
- return nfserr;
+ nfserr = nfsd42_encode_write_res(resp, &copy->cp_res);
+ if (nfserr)
+ return nfserr;
- p = xdr_reserve_space(&resp->xdr, 4 + 4);
- *p++ = cpu_to_be32(copy->cp_consecutive);
- *p++ = cpu_to_be32(copy->cp_synchronous);
- }
- return nfserr;
+ p = xdr_reserve_space(&resp->xdr, 4 + 4);
+ *p++ = cpu_to_be32(copy->cp_consecutive);
+ *p++ = cpu_to_be32(copy->cp_synchronous);
+ return 0;
}
static __be32
@@ -4307,14 +4221,11 @@ nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr,
{
__be32 *p;
- if (nfserr)
- return nfserr;
-
p = xdr_reserve_space(&resp->xdr, 4 + 8);
*p++ = cpu_to_be32(seek->seek_eof);
p = xdr_encode_hyper(p, seek->seek_pos);
- return nfserr;
+ return 0;
}
static __be32
@@ -4330,7 +4241,7 @@ typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
* since we don't need to filter out obsolete ops as this is
* done in the decoding phase.
*/
-static nfsd4_enc nfsd4_enc_ops[] = {
+static const nfsd4_enc nfsd4_enc_ops[] = {
[OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access,
[OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close,
[OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit,
@@ -4449,6 +4360,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
struct xdr_stream *xdr = &resp->xdr;
struct nfs4_stateowner *so = resp->cstate.replay_owner;
struct svc_rqst *rqstp = resp->rqstp;
+ const struct nfsd4_operation *opdesc = op->opdesc;
int post_err_offset;
nfsd4_enc encoder;
__be32 *p;
@@ -4463,10 +4375,15 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
if (op->opnum == OP_ILLEGAL)
goto status;
+ if (op->status && opdesc &&
+ !(opdesc->op_flags & OP_NONTRIVIAL_ERROR_ENCODE))
+ goto status;
BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
!nfsd4_enc_ops[op->opnum]);
encoder = nfsd4_enc_ops[op->opnum];
op->status = encoder(resp, op->status, &op->u);
+ if (opdesc && opdesc->op_release)
+ opdesc->op_release(&op->u);
xdr_commit_encode(xdr);
/* nfsd4_check_resp_size guarantees enough room for error status */
@@ -4573,6 +4490,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
args->pagelist = rqstp->rq_arg.pages;
args->pagelen = rqstp->rq_arg.page_len;
+ args->tail = false;
args->tmpp = NULL;
args->to_free = NULL;
args->ops = args->iops;