diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2009-02-22 17:51:34 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-03-18 17:38:38 -0400 |
commit | 8b671b80707e4fc76adfe4387df07b3be1007c1e (patch) | |
tree | d9dafb3a1174dfeb84f72ba56a04625204aab415 | |
parent | d7fdcfe0aaaf6dffca6fa857bab374182fe7ca8b (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.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 47 | ||||
-rw-r--r-- | include/linux/nfsd/state.h | 2 |
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 | |||
78 | static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; | 78 | static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; |
79 | static void nfs4_set_recdir(char *recdir); | 79 | static 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 | */ | ||
87 | static DEFINE_MUTEX(client_mutex); | 84 | static 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 | */ | ||
91 | static DEFINE_SPINLOCK(recall_lock); | ||
92 | |||
89 | static struct kmem_cache *stateowner_slab = NULL; | 93 | static struct kmem_cache *stateowner_slab = NULL; |
90 | static struct kmem_cache *file_slab = NULL; | 94 | static struct kmem_cache *file_slab = NULL; |
91 | static struct kmem_cache *stateid_slab = NULL; | 95 | static 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 */ | ||
124 | static DEFINE_SPINLOCK(recall_lock); | ||
125 | static struct list_head del_recall_lru; | 123 | static struct list_head del_recall_lru; |
126 | 124 | ||
127 | static void | ||
128 | free_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 | |||
136 | static inline void | 125 | static inline void |
137 | put_nfs4_file(struct nfs4_file *fi) | 126 | put_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 | ||
142 | static inline void | 136 | static inline void |
143 | get_nfs4_file(struct nfs4_file *fi) | 137 | get_nfs4_file(struct nfs4_file *fi) |
144 | { | 138 | { |
145 | kref_get(&fi->fi_ref); | 139 | atomic_inc(&fi->fi_ref); |
146 | } | 140 | } |
147 | 141 | ||
148 | static int num_delegations; | 142 | static 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 | */ |
216 | struct nfs4_file { | 216 | struct 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; |