[pnfs] [PATCH 1/2] NFS: Fix an illegal allocation...

Trond Myklebust Trond.Myklebust at netapp.com
Mon Jul 14 23:39:25 EDT 2008


Routines that may be run in the NFS writeback path may not allocate memory
using GFP_KERNEL, since that may initiate more I/O in order to free up
resources.

Signed-off-by: Trond Myklebust <Trond.Myklebust at netapp.com>
---

 fs/nfs/nfs4proc.c |    9 +++++++++
 fs/nfs/nfs4xdr.c  |    3 +--
 fs/nfs/pnfs.c     |    3 ---
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 7c3bc50..40f5eef 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5140,6 +5140,8 @@ static void nfs4_pnfs_layoutget_release(void *calldata)
 
 	dprintk("--> %s\n", __func__);
 	pnfs_layout_release(lo);
+	if (lgp->res.layout.buf != NULL)
+		free_page((unsigned long) lgp->res.layout.buf);
 	kfree(calldata);
 	dprintk("<-- %s\n", __func__);
 }
@@ -5171,6 +5173,13 @@ static int nfs4_proc_pnfs_layoutget(struct nfs4_pnfs_layoutget *lgp)
 
 	dprintk("--> %s\n", __func__);
 
+	lgp->res.layout.buf = (void *)__get_free_page(GFP_KERNEL);
+	if (lgp->res.layout.buf == NULL) {
+		nfs4_pnfs_layoutget_release(lgp);
+		status = -ENOMEM;
+		goto out;
+	}
+
 	task = rpc_run_task(&task_setup_data);
 	if (IS_ERR(task)) {
 		status = PTR_ERR(task);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 884c42d..50478b5 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -5562,8 +5562,7 @@ static int decode_pnfs_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 		res->type,
 		res->layout.len);
 
-	res->layout.buf = kmalloc(res->layout.len, GFP_KERNEL);
-	if (!res->layout.buf)
+	if (res->layout.len > PAGE_SIZE)
 		return -ENOMEM;
 	READ_BUF(res->layout.len);
 	COPYMEM(res->layout.buf, res->layout.len);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index afb3d71..79208e6 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1049,9 +1049,6 @@ get_out:
 	/* Done processing layoutget. Set the layout stateid */
 	pnfs_set_layout_stateid(lo, &res->stateid);
 
-	/* res->layout.buf kalloc'ed by the xdr decoder? */
-	kfree(res->layout.buf);
-
 	dprintk("%s end (err:%d) state 0x%lx lseg %p\n",
 		__func__, lgp->status, nfsi->pnfs_layout_state, lseg);
 	if (lgp->lsegpp)



More information about the pNFS mailing list