aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-12-23 15:21:38 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-12-23 15:21:38 -0500
commit343104308a33c4f1e23c8e841ede95e97b870842 (patch)
treee7772538627a0a2176bd23cd3b2f1acbacd24592 /fs/nfs/delegation.c
parent0cb2659b818eca99235e17c04291cfa9985c14f7 (diff)
NFSv4: Fix up another delegation related race
When we can update_open_stateid(), we need to be certain that we don't race with a delegation return. While we could do this by grabbing the nfs_client->cl_lock, a dedicated spin lock in the delegation structure will scale better. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index cc563cfa6940..e0cb4ee3b23e 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -140,13 +140,17 @@ static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfs
140 140
141 if (delegation == NULL) 141 if (delegation == NULL)
142 goto nomatch; 142 goto nomatch;
143 spin_lock(&delegation->lock);
143 if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, 144 if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
144 sizeof(delegation->stateid.data)) != 0) 145 sizeof(delegation->stateid.data)) != 0)
145 goto nomatch; 146 goto nomatch_unlock;
146 list_del_rcu(&delegation->super_list); 147 list_del_rcu(&delegation->super_list);
147 nfsi->delegation_state = 0; 148 nfsi->delegation_state = 0;
148 rcu_assign_pointer(nfsi->delegation, NULL); 149 rcu_assign_pointer(nfsi->delegation, NULL);
150 spin_unlock(&delegation->lock);
149 return delegation; 151 return delegation;
152nomatch_unlock:
153 spin_unlock(&delegation->lock);
150nomatch: 154nomatch:
151 return NULL; 155 return NULL;
152} 156}
@@ -172,6 +176,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
172 delegation->change_attr = nfsi->change_attr; 176 delegation->change_attr = nfsi->change_attr;
173 delegation->cred = get_rpccred(cred); 177 delegation->cred = get_rpccred(cred);
174 delegation->inode = inode; 178 delegation->inode = inode;
179 spin_lock_init(&delegation->lock);
175 180
176 spin_lock(&clp->cl_lock); 181 spin_lock(&clp->cl_lock);
177 if (rcu_dereference(nfsi->delegation) != NULL) { 182 if (rcu_dereference(nfsi->delegation) != NULL) {