[RFC 30/51] nfsd: lock state around nfs4_put_delegation in nfsd_break_deleg_cb err path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If kthread_run fails we put the client and delegation.  This requires
the state lock since the fi_hash is manipulated in the process.
Use nfs4_lock_state_nested as nfsd_break_deleg_cb may be called
back by the filesystem while under the state lock (e.g. in the close path)

Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx>
---
 fs/nfsd/nfs4state.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 7fe074a..0b45680 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -94,6 +94,7 @@ static void nfs4_set_recdir(char *recdir);
  * 	unconfstr_hashtbl[], uncofid_hashtbl[].
  */
 static DEFINE_MUTEX(client_mutex);
+static struct thread_info *client_mutex_owner;
 
 static struct kmem_cache *stateowner_slab = NULL;
 static struct kmem_cache *file_slab = NULL;
@@ -106,14 +107,26 @@ void
 nfs4_lock_state(void)
 {
 	mutex_lock(&client_mutex);
+	client_mutex_owner = current_thread_info();
 }
 
 void
 nfs4_unlock_state(void)
 {
+	BUG_ON(client_mutex_owner != current_thread_info());
+	client_mutex_owner = NULL;
 	mutex_unlock(&client_mutex);
 }
 
+static int
+nfs4_lock_state_nested(void)
+{
+	if (client_mutex_owner == current_thread_info())
+		return 0;
+	nfs4_lock_state();
+	return 1;
+}
+
 static inline u32
 opaque_hashval(const void *ptr, int nbytes)
 {
@@ -1798,6 +1811,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
 {
 	struct nfs4_delegation *dp=  (struct nfs4_delegation *)fl->fl_owner;
 	struct task_struct *t;
+	int did_lock;
 
 	dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
 	if (!dp)
@@ -1832,8 +1846,11 @@ 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);
+		did_lock = nfs4_lock_state_nested();
 		put_nfs4_client(dp->dl_client);
 		nfs4_put_delegation(dp);
+		if (did_lock)
+			nfs4_unlock_state();
 	}
 }
 
-- 
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux