aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2009-02-22 17:51:34 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-03-18 17:38:38 -0400
commit8b671b80707e4fc76adfe4387df07b3be1007c1e (patch)
treed9dafb3a1174dfeb84f72ba56a04625204aab415
parentd7fdcfe0aaaf6dffca6fa857bab374182fe7ca8b (diff)
nfsd4: remove use of mutex for file_hashtable
As part of reducing the scope of the client_mutex, and in order to remove the need for mutexes from the callback code (so that callbacks can be done as asynchronous rpc calls), move manipulations of the file_hashtable under the recall_lock. Update the relevant comments while we're here. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Cc: Alexandros Batsakis <batsakis@netapp.com> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
-rw-r--r--fs/nfsd/nfs4callback.c2
-rw-r--r--fs/nfsd/nfs4state.c47
-rw-r--r--include/linux/nfsd/state.h2
3 files changed, 24 insertions, 27 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 3fd7136321ca..5dcd38e5f138 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -491,8 +491,6 @@ out_put_cred:
491 * or deleg_return. 491 * or deleg_return.
492 */ 492 */
493 put_nfs4_client(clp); 493 put_nfs4_client(clp);
494 nfs4_lock_state();
495 nfs4_put_delegation(dp); 494 nfs4_put_delegation(dp);
496 nfs4_unlock_state();
497 return; 495 return;
498} 496}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 89e575e7daea..54651aa45790 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -78,14 +78,18 @@ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, state
78static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 78static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
79static void nfs4_set_recdir(char *recdir); 79static void nfs4_set_recdir(char *recdir);
80 80
81/* Locking: 81/* Locking: */
82 * 82
83 * client_mutex: 83/* Currently used for almost all code touching nfsv4 state: */
84 * protects clientid_hashtbl[], clientstr_hashtbl[],
85 * unconfstr_hashtbl[], uncofid_hashtbl[].
86 */
87static DEFINE_MUTEX(client_mutex); 84static DEFINE_MUTEX(client_mutex);
88 85
86/*
87 * Currently used for the del_recall_lru and file hash table. In an
88 * effort to decrease the scope of the client_mutex, this spinlock may
89 * eventually cover more:
90 */
91static DEFINE_SPINLOCK(recall_lock);
92
89static struct kmem_cache *stateowner_slab = NULL; 93static struct kmem_cache *stateowner_slab = NULL;
90static struct kmem_cache *file_slab = NULL; 94static struct kmem_cache *file_slab = NULL;
91static struct kmem_cache *stateid_slab = NULL; 95static struct kmem_cache *stateid_slab = NULL;
@@ -116,33 +120,23 @@ opaque_hashval(const void *ptr, int nbytes)
116 return x; 120 return x;
117} 121}
118 122
119/*
120 * Delegation state
121 */
122
123/* recall_lock protects the del_recall_lru */
124static DEFINE_SPINLOCK(recall_lock);
125static struct list_head del_recall_lru; 123static struct list_head del_recall_lru;
126 124
127static void
128free_nfs4_file(struct kref *kref)
129{
130 struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
131 list_del(&fp->fi_hash);
132 iput(fp->fi_inode);
133 kmem_cache_free(file_slab, fp);
134}
135
136static inline void 125static inline void
137put_nfs4_file(struct nfs4_file *fi) 126put_nfs4_file(struct nfs4_file *fi)
138{ 127{
139 kref_put(&fi->fi_ref, free_nfs4_file); 128 if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) {
129 list_del(&fi->fi_hash);
130 spin_unlock(&recall_lock);
131 iput(fi->fi_inode);
132 kmem_cache_free(file_slab, fi);
133 }
140} 134}
141 135
142static inline void 136static inline void
143get_nfs4_file(struct nfs4_file *fi) 137get_nfs4_file(struct nfs4_file *fi)
144{ 138{
145 kref_get(&fi->fi_ref); 139 atomic_inc(&fi->fi_ref);
146} 140}
147 141
148static int num_delegations; 142static int num_delegations;
@@ -1000,11 +994,13 @@ alloc_init_file(struct inode *ino)
1000 994
1001 fp = kmem_cache_alloc(file_slab, GFP_KERNEL); 995 fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
1002 if (fp) { 996 if (fp) {
1003 kref_init(&fp->fi_ref); 997 atomic_set(&fp->fi_ref, 1);
1004 INIT_LIST_HEAD(&fp->fi_hash); 998 INIT_LIST_HEAD(&fp->fi_hash);
1005 INIT_LIST_HEAD(&fp->fi_stateids); 999 INIT_LIST_HEAD(&fp->fi_stateids);
1006 INIT_LIST_HEAD(&fp->fi_delegations); 1000 INIT_LIST_HEAD(&fp->fi_delegations);
1001 spin_lock(&recall_lock);
1007 list_add(&fp->fi_hash, &file_hashtbl[hashval]); 1002 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
1003 spin_unlock(&recall_lock);
1008 fp->fi_inode = igrab(ino); 1004 fp->fi_inode = igrab(ino);
1009 fp->fi_id = current_fileid++; 1005 fp->fi_id = current_fileid++;
1010 fp->fi_had_conflict = false; 1006 fp->fi_had_conflict = false;
@@ -1177,12 +1173,15 @@ find_file(struct inode *ino)
1177 unsigned int hashval = file_hashval(ino); 1173 unsigned int hashval = file_hashval(ino);
1178 struct nfs4_file *fp; 1174 struct nfs4_file *fp;
1179 1175
1176 spin_lock(&recall_lock);
1180 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { 1177 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
1181 if (fp->fi_inode == ino) { 1178 if (fp->fi_inode == ino) {
1182 get_nfs4_file(fp); 1179 get_nfs4_file(fp);
1180 spin_unlock(&recall_lock);
1183 return fp; 1181 return fp;
1184 } 1182 }
1185 } 1183 }
1184 spin_unlock(&recall_lock);
1186 return NULL; 1185 return NULL;
1187} 1186}
1188 1187
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 503b6bb53a56..a6e4a00fa392 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -214,7 +214,7 @@ struct nfs4_stateowner {
214* share_acces, share_deny on the file. 214* share_acces, share_deny on the file.
215*/ 215*/
216struct nfs4_file { 216struct nfs4_file {
217 struct kref fi_ref; 217 atomic_t fi_ref;
218 struct list_head fi_hash; /* hash by "struct inode *" */ 218 struct list_head fi_hash; /* hash by "struct inode *" */
219 struct list_head fi_stateids; 219 struct list_head fi_stateids;
220 struct list_head fi_delegations; 220 struct list_head fi_delegations;