[PATCH] cleanup nfsd state lock

Benny Halevy bhalevy at ns1.bhalevy.com
Mon May 7 09:58:42 EDT 2007


make sure nfs4 file and client are got and freed
under the state lock
get... code asserts that the lock is taken (with BUG_ON)
free... code just takes the lock if needed
---
 fs/nfsd/nfs4state.c |   19 ++++++++++++++++++-
 1 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d1355b2..71c9ec3 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -108,6 +108,12 @@ static kmem_cache_t *file_slab = NULL;
 static kmem_cache_t *stateid_slab = NULL;
 static kmem_cache_t *deleg_slab = NULL;
 
+static int
+nfs4_trylock_state(void)
+{
+	return mutex_trylock(&client_mutex);
+}
+
 void
 nfs4_lock_state(void)
 {
@@ -120,6 +126,8 @@ nfs4_unlock_state(void)
 	mutex_unlock(&client_mutex);
 }
 
+#define BUG_ON_UNLOCKED_STATE() BUG_ON(nfs4_trylock_state());
+
 static inline u32
 opaque_hashval(const void *ptr, int nbytes)
 {
@@ -148,8 +156,12 @@ static struct list_head del_recall_lru;
 static void
 free_nfs4_file(struct kref *kref)
 {
+	int did_lock;
 	struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
+	did_lock = nfs4_trylock_state();
 	list_del(&fp->fi_hash);
+	if (did_lock)
+		nfs4_unlock_state();
 	iput(fp->fi_inode);
 	kmem_cache_free(file_slab, fp);
 }
@@ -157,12 +169,15 @@ free_nfs4_file(struct kref *kref)
 static inline void
 put_nfs4_file(struct nfs4_file *fi)
 {
-	kref_put(&fi->fi_ref, free_nfs4_file);
+	BUG_ON_UNLOCKED_STATE();
+	if (fi)
+		kref_put(&fi->fi_ref, free_nfs4_file);
 }
 
 static inline void
 get_nfs4_file(struct nfs4_file *fi)
 {
+	BUG_ON_UNLOCKED_STATE();
 	kref_get(&fi->fi_ref);
 }
 
@@ -538,6 +553,7 @@ alloc_client(struct xdr_netobj name)
 static inline struct nfs4_client *
 get_nfs4_client(struct nfs4_client *clp)
 {
+	BUG_ON_UNLOCKED_STATE();
 	kref_get(&clp->cl_ref);
 	return clp;
 }
@@ -1661,6 +1677,7 @@ find_file(struct inode *ino)
 	unsigned int hashval = file_hashval(ino);
 	struct nfs4_file *fp;
 
+	BUG_ON_UNLOCKED_STATE();
 	list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
 		if (fp->fi_inode == ino) {
 			get_nfs4_file(fp);
-- 
1.5.1


--------------060903090305060208070700--


More information about the pNFS mailing list