[pnfs] [PATCH 1/5] rpc_clnt ref count for nfs4_cb_recall
Benny Halevy
bhalevy at panasas.com
Thu May 17 09:44:18 EDT 2007
This patch adds a refcount to rpc_clnt.cl_users around the call
to nfs4_cb_recall to keep the rpc_clnt around throughout the recall.
Otherwise, it could be used after free if expire_client is called
before the callback rpc starts.
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
fs/nfsd/nfs4callback.c | 3 +++
fs/nfsd/nfs4state.c | 13 +++++++++++++
net/sunrpc/sunrpc_syms.c | 1 +
3 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 54b37b1..63aafd2 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -543,6 +543,9 @@ out:
/* Success or failure, now we're either waiting for lease expiration
* or deleg_return. */
dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
+ rpc_release_client(clnt);
+ nfs4_lock_state();
nfs4_put_delegation(dp);
+ nfs4_unlock_state();
return;
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 2d2c85d..e2e924e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1679,12 +1679,22 @@ static
void nfsd_break_deleg_cb(struct file_lock *fl)
{
struct nfs4_delegation *dp= (struct nfs4_delegation *)fl->fl_owner;
+ struct rpc_clnt *clnt;
struct task_struct *t;
dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
if (!dp)
return;
+ nfs4_lock_state();
+ clnt = dp->dl_client->cl_callback.cb_client;
+ if (!atomic_read(&dp->dl_client->cl_callback.cb_set) || !clnt) {
+ nfs4_unlock_state();
+ return;
+ }
+ atomic_inc(&clnt->cl_users);
+ nfs4_unlock_state();
+
/* We're assuming the state code never drops its reference
* without first removing the lease. Since we're in this lease
* callback (and since the lease code is serialized by the kernel
@@ -1709,7 +1719,10 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
printk(KERN_INFO "NFSD: Callback thread failed for "
"for client (clientid %08x/%08x)\n",
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+ rpc_release_client(clnt);
+ nfs4_lock_state();
nfs4_put_delegation(dp);
+ nfs4_unlock_state();
}
}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index f38f939..b329983 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -40,6 +40,7 @@ EXPORT_SYMBOL(rpc_create_client);
EXPORT_SYMBOL(rpc_new_client);
EXPORT_SYMBOL(rpc_clone_client);
EXPORT_SYMBOL(rpc_bind_new_program);
+EXPORT_SYMBOL(rpc_release_client);
EXPORT_SYMBOL(rpc_destroy_client);
EXPORT_SYMBOL(rpc_shutdown_client);
EXPORT_SYMBOL(rpc_killall_tasks);
More information about the pNFS
mailing list