[pnfs] [PATCH 22/23] 2.6-latest pnfs client nfs41_proc_async_sequence bug fix

andros at umich.edu andros at umich.edu
Thu Dec 13 15:51:48 EST 2007


From: Andy Adamson <andros at umich.edu>

Move the put_rpccred() call from nfs4_renew_state90 into the asyc state
renewal rpc_call_done routine so the rpc cred is not reaped before the call
is done.

The async rpc call requires kmalloc'ed arguments.

Replace the local nfs41_sequence_args and nfs41_sequence_res
nfs41_proc_async_sequence() variables with kmalloc versions. Free
in rpc_call_done routine.

Signed-off by: Andy Adamson<andros at umich.edu>
---
 fs/nfs/nfs4proc.c   |   32 +++++++++++++++++++++++++-------
 fs/nfs/nfs4renewd.c |    1 -
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f3aa86e..2c52819 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3130,6 +3130,9 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
 	if (time_before(clp->cl_last_renewal,timestamp))
 		clp->cl_last_renewal = timestamp;
 	spin_unlock(&clp->cl_lock);
+	dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__,
+				task->tk_msg.rpc_cred);
+	put_rpccred(task->tk_msg.rpc_cred);
 }
 
 static const struct rpc_call_ops nfs4_renew_ops = {
@@ -3235,6 +3238,13 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 				nfs41_recover_session(clp, session);
 		}
 	}
+	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
+
+	put_rpccred(task->tk_msg.rpc_cred);
+	kfree(task->tk_msg.rpc_argp);
+	kfree(task->tk_msg.rpc_resp);
+
+	dprintk("<-- %s\n", __func__);
 }
 
 static void nfs41_sequence_validate(struct rpc_task *task, void *data)
@@ -3261,17 +3271,25 @@ static const struct rpc_call_ops nfs41_sequence_ops = {
 
 int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred)
 {
-	struct nfs41_sequence_args args;
-	struct nfs41_sequence_res res;
+	struct nfs41_sequence_args *args;
+	struct nfs41_sequence_res *res;
 	struct nfs_server *server;
-	
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
-		.rpc_argp	= &args,
-		.rpc_resp	= &res,
 		.rpc_cred	= cred,
 	};
 
+	args = kzalloc(sizeof(*args), GFP_KERNEL);
+	if (!args)
+		return -ENOMEM;
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res) {
+		kfree(args);
+		return -ENOMEM;
+	} 
+	msg.rpc_argp = args;
+	msg.rpc_resp = res;
+
 	/*
 	 * We need to renew the lease on the server. For this, we use any
 	 * session we have on the server to send the SEQUENCE op
@@ -5169,13 +5187,13 @@ struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = {
 
 struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
 	.sched_state_renewal = nfs4_proc_async_renew,
-	.get_state_renewal_cred = nfs41_get_state_renewal_cred,
+	.get_state_renewal_cred = nfs4_get_renew_cred,
 };
 
 #if defined (CONFIG_NFS_V4_1)
 struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
 	.sched_state_renewal = nfs41_proc_async_sequence,
-	.get_state_renewal_cred = nfs4_get_renew_cred,
+	.get_state_renewal_cred = nfs41_get_state_renewal_cred,
 };
 #endif
 
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 20667d8..94f1d82 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -91,7 +91,6 @@ nfs4_renew_state(struct work_struct *work)
 		spin_unlock(&clp->cl_lock);
 		/* Queue an asynchronous RENEW. */
 		ops->sched_state_renewal(clp, cred);
-		put_rpccred(cred);
 		timeout = (2 * lease) / 3;
 		spin_lock(&clp->cl_lock);
 	} else
-- 
1.5.0.2



More information about the pNFS mailing list