nfsd4: disable zero-copy on non-final read ops
Subsystems (2)
PATCH 1/2 nfsd4: disable zero-copy on non-final read ops
From: "J. Bruce Fields" <[email protected]>
To ensure ordering of read data with any following operations, turn off zero copy if the read is not the final operation in the compound.
Signed-off-by J. Bruce Fields <[email protected]>
--- fs/nfsd/nfs4proc.c | 11 +++++++++++ fs/nfsd/nfs4state.c | 8 -------- fs/nfsd/xdr4.h | 8 ++++++++ 3 files changed, 19 insertions(+), 8 deletions(-)
fs/nfsd/nfs4proc.c +11 -0
@@ -692,6 +692,17 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (read->rd_offset >=OFFSET_MAX )return nfserr_inval; +/* +* If we do a zero copy read, then a client will see read data +* that reflects the state of the file *after* performing the +* following compound. +* +* To ensure proper ordering, we therefore turn off zero copy if +* the client wants us to do more in this compound: +*/ +if (!nfsd4_last_compound_op (rqstp)) + rqstp->rq_splice_ok = false; +nfs4_lock_state ();/* check stateid */ if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
fs/nfsd/nfs4state.c +0 -8
@@ -1855,14 +1855,6 @@ out_free_session: goto out; } -static bool nfsd4_last_compound_op (struct svc_rqst *rqstp) -{ -struct nfsd4_compoundres *resp = rqstp->rq_resp; -struct nfsd4_compoundargs *argp = rqstp->rq_argp; - -return argp->opcnt == resp->opcnt; -} -static __be32 nfsd4_map_bcts_dir (u32 *dir) {switch (*dir) {
fs/nfsd/xdr4.h +8 -0
@@ -528,6 +528,14 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) || nfsd4_is_solo_sequence(resp); } +static inline bool nfsd4_last_compound_op (struct svc_rqst *rqstp) +{ +struct nfsd4_compoundres *resp = rqstp->rq_resp; +struct nfsd4_compoundargs *argp = rqstp->rq_argp; + +return argp->opcnt == resp->opcnt; +} +#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) static inline void
Signature · 1 line
1.7.9.5
PATCH 2/2 nfsd4: fix oops on unusual readlike compound
From: "J. Bruce Fields" <[email protected]>
If the argument and reply together exceed the maximum payload size, then a reply with a read-like operation can overlow the rq_pages array.
Signed-off-by J. Bruce Fields <[email protected]>
--- fs/nfsd/nfs4xdr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c +10 -1
@@ -2925,11 +2925,16 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, len = maxcount; v =0 ;while (len >0 ) { - pn = resp->rqstp->rq_resused++; + pn = resp->rqstp->rq_resused; +if (!resp->rqstp->rq_respages[pn]) {/* ran out of pages */ + maxcount -= len; +break ; + } resp->rqstp->rq_vec[v].iov_base =page_address (resp->rqstp->rq_respages[pn]); resp->rqstp->rq_vec[v].iov_len = len <PAGE_SIZE ? len :PAGE_SIZE ; + resp->rqstp->rq_resused++; v++; len -=PAGE_SIZE ; }
@@ -2975,6 +2980,8 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsdreturn nfserr;if (resp->xbuf->page_len)return nfserr_resource; +if (!*resp->rqstp->rq_next_page) +return nfserr_resource; page =page_address (resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
@@ -3024,6 +3031,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4return nfserr;if (resp->xbuf->page_len)return nfserr_resource; +if (!*resp->rqstp->rq_next_page) +return nfserr_resource;RESERVE_SPACE (NFS4_VERIFIER_SIZE ); savep = p;
Signature · 1 line
1.7.9.5