aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/delegation.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 8d9ec494a944..ea61d26e7871 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -24,6 +24,8 @@
24 24
25static void nfs_do_free_delegation(struct nfs_delegation *delegation) 25static void nfs_do_free_delegation(struct nfs_delegation *delegation)
26{ 26{
27 if (delegation->cred)
28 put_rpccred(delegation->cred);
27 kfree(delegation); 29 kfree(delegation);
28} 30}
29 31
@@ -36,13 +38,7 @@ static void nfs_free_delegation_callback(struct rcu_head *head)
36 38
37static void nfs_free_delegation(struct nfs_delegation *delegation) 39static void nfs_free_delegation(struct nfs_delegation *delegation)
38{ 40{
39 struct rpc_cred *cred;
40
41 cred = rcu_dereference(delegation->cred);
42 rcu_assign_pointer(delegation->cred, NULL);
43 call_rcu(&delegation->rcu, nfs_free_delegation_callback); 41 call_rcu(&delegation->rcu, nfs_free_delegation_callback);
44 if (cred)
45 put_rpccred(cred);
46} 42}
47 43
48void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) 44void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
@@ -180,9 +176,13 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation
180 return inode; 176 return inode;
181} 177}
182 178
183static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) 179static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi,
180 const nfs4_stateid *stateid,
181 struct nfs_client *clp)
184{ 182{
185 struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); 183 struct nfs_delegation *delegation =
184 rcu_dereference_protected(nfsi->delegation,
185 lockdep_is_held(&clp->cl_lock));
186 186
187 if (delegation == NULL) 187 if (delegation == NULL)
188 goto nomatch; 188 goto nomatch;
@@ -209,7 +209,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
209{ 209{
210 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 210 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
211 struct nfs_inode *nfsi = NFS_I(inode); 211 struct nfs_inode *nfsi = NFS_I(inode);
212 struct nfs_delegation *delegation; 212 struct nfs_delegation *delegation, *old_delegation;
213 struct nfs_delegation *freeme = NULL; 213 struct nfs_delegation *freeme = NULL;
214 int status = 0; 214 int status = 0;
215 215
@@ -227,10 +227,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
227 spin_lock_init(&delegation->lock); 227 spin_lock_init(&delegation->lock);
228 228
229 spin_lock(&clp->cl_lock); 229 spin_lock(&clp->cl_lock);
230 if (rcu_dereference(nfsi->delegation) != NULL) { 230 old_delegation = rcu_dereference_protected(nfsi->delegation,
231 if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, 231 lockdep_is_held(&clp->cl_lock));
232 sizeof(delegation->stateid)) == 0 && 232 if (old_delegation != NULL) {
233 delegation->type == nfsi->delegation->type) { 233 if (memcmp(&delegation->stateid, &old_delegation->stateid,
234 sizeof(old_delegation->stateid)) == 0 &&
235 delegation->type == old_delegation->type) {
234 goto out; 236 goto out;
235 } 237 }
236 /* 238 /*
@@ -240,12 +242,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
240 dfprintk(FILE, "%s: server %s handed out " 242 dfprintk(FILE, "%s: server %s handed out "
241 "a duplicate delegation!\n", 243 "a duplicate delegation!\n",
242 __func__, clp->cl_hostname); 244 __func__, clp->cl_hostname);
243 if (delegation->type <= nfsi->delegation->type) { 245 if (delegation->type <= old_delegation->type) {
244 freeme = delegation; 246 freeme = delegation;
245 delegation = NULL; 247 delegation = NULL;
246 goto out; 248 goto out;
247 } 249 }
248 freeme = nfs_detach_delegation_locked(nfsi, NULL); 250 freeme = nfs_detach_delegation_locked(nfsi, NULL, clp);
249 } 251 }
250 list_add_rcu(&delegation->super_list, &clp->cl_delegations); 252 list_add_rcu(&delegation->super_list, &clp->cl_delegations);
251 nfsi->delegation_state = delegation->type; 253 nfsi->delegation_state = delegation->type;
@@ -315,7 +317,7 @@ restart:
315 if (inode == NULL) 317 if (inode == NULL)
316 continue; 318 continue;
317 spin_lock(&clp->cl_lock); 319 spin_lock(&clp->cl_lock);
318 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); 320 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp);
319 spin_unlock(&clp->cl_lock); 321 spin_unlock(&clp->cl_lock);
320 rcu_read_unlock(); 322 rcu_read_unlock();
321 if (delegation != NULL) { 323 if (delegation != NULL) {
@@ -344,9 +346,9 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode)
344 struct nfs_inode *nfsi = NFS_I(inode); 346 struct nfs_inode *nfsi = NFS_I(inode);
345 struct nfs_delegation *delegation; 347 struct nfs_delegation *delegation;
346 348
347 if (rcu_dereference(nfsi->delegation) != NULL) { 349 if (rcu_access_pointer(nfsi->delegation) != NULL) {
348 spin_lock(&clp->cl_lock); 350 spin_lock(&clp->cl_lock);
349 delegation = nfs_detach_delegation_locked(nfsi, NULL); 351 delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
350 spin_unlock(&clp->cl_lock); 352 spin_unlock(&clp->cl_lock);
351 if (delegation != NULL) 353 if (delegation != NULL)
352 nfs_do_return_delegation(inode, delegation, 0); 354 nfs_do_return_delegation(inode, delegation, 0);
@@ -360,9 +362,9 @@ int nfs_inode_return_delegation(struct inode *inode)
360 struct nfs_delegation *delegation; 362 struct nfs_delegation *delegation;
361 int err = 0; 363 int err = 0;
362 364
363 if (rcu_dereference(nfsi->delegation) != NULL) { 365 if (rcu_access_pointer(nfsi->delegation) != NULL) {
364 spin_lock(&clp->cl_lock); 366 spin_lock(&clp->cl_lock);
365 delegation = nfs_detach_delegation_locked(nfsi, NULL); 367 delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
366 spin_unlock(&clp->cl_lock); 368 spin_unlock(&clp->cl_lock);
367 if (delegation != NULL) { 369 if (delegation != NULL) {
368 nfs_msync_inode(inode); 370 nfs_msync_inode(inode);
@@ -540,7 +542,7 @@ restart:
540 if (inode == NULL) 542 if (inode == NULL)
541 continue; 543 continue;
542 spin_lock(&clp->cl_lock); 544 spin_lock(&clp->cl_lock);
543 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); 545 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp);
544 spin_unlock(&clp->cl_lock); 546 spin_unlock(&clp->cl_lock);
545 rcu_read_unlock(); 547 rcu_read_unlock();
546 if (delegation != NULL) 548 if (delegation != NULL)