From: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> We might need this to better handle shifting around data in the reply buffer. Suggested-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> Signed-off-by: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> --- fs/nfs/nfs42xdr.c | 2 ++ fs/nfs/read.c | 13 +++++++++++-- include/linux/nfs_xdr.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index 8432bd6b95f0..ef095a5f86f7 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c @@ -1297,6 +1297,8 @@ static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp, 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; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index eb854f1f86e2..012deb5a136f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -37,15 +37,24 @@ static struct kmem_cache *nfs_rdata_cachep; static struct nfs_pgio_header *nfs_readhdr_alloc(void) { - struct nfs_pgio_header *p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); + struct nfs_pgio_header *p; + struct page *page; - if (p) + page = alloc_page(GFP_KERNEL); + if (!page) + return ERR_PTR(-ENOMEM); + + p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); + if (p) { p->rw_mode = FMODE_READ; + p->res.scratch = page; + } return p; } static void nfs_readhdr_free(struct nfs_pgio_header *rhdr) { + __free_page(rhdr->res.scratch); kmem_cache_free(nfs_rdata_cachep, rhdr); } diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index d63cb862d58e..e0a1c97f11a9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -659,6 +659,7 @@ struct nfs_pgio_res { struct nfs_fattr * fattr; __u64 count; __u32 op_status; + struct page * scratch; union { struct { unsigned int replen; /* used by read */ -- 2.29.2