aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c80
1 files changed, 50 insertions, 30 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 9f17b91205cf..cee2ba42b68d 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -57,7 +57,7 @@ out_err:
57 return status; 57 return status;
58} 58}
59 59
60static void nfs_delegation_claim_opens(struct inode *inode) 60static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
61{ 61{
62 struct nfs_inode *nfsi = NFS_I(inode); 62 struct nfs_inode *nfsi = NFS_I(inode);
63 struct nfs_open_context *ctx; 63 struct nfs_open_context *ctx;
@@ -72,6 +72,8 @@ again:
72 continue; 72 continue;
73 if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) 73 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
74 continue; 74 continue;
75 if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
76 continue;
75 get_nfs_open_context(ctx); 77 get_nfs_open_context(ctx);
76 spin_unlock(&inode->i_lock); 78 spin_unlock(&inode->i_lock);
77 err = nfs4_open_delegation_recall(ctx, state); 79 err = nfs4_open_delegation_recall(ctx, state);
@@ -170,33 +172,55 @@ static void nfs_msync_inode(struct inode *inode)
170/* 172/*
171 * Basic procedure for returning a delegation to the server 173 * Basic procedure for returning a delegation to the server
172 */ 174 */
173int __nfs_inode_return_delegation(struct inode *inode) 175static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
174{ 176{
175 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 177 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
176 struct nfs_inode *nfsi = NFS_I(inode); 178 struct nfs_inode *nfsi = NFS_I(inode);
177 struct nfs_delegation *delegation;
178 int res = 0;
179 179
180 nfs_msync_inode(inode); 180 nfs_msync_inode(inode);
181 down_read(&clp->cl_sem); 181 down_read(&clp->cl_sem);
182 /* Guard against new delegated open calls */ 182 /* Guard against new delegated open calls */
183 down_write(&nfsi->rwsem); 183 down_write(&nfsi->rwsem);
184 spin_lock(&clp->cl_lock); 184 nfs_delegation_claim_opens(inode, &delegation->stateid);
185 delegation = nfsi->delegation;
186 if (delegation != NULL) {
187 list_del_init(&delegation->super_list);
188 nfsi->delegation = NULL;
189 nfsi->delegation_state = 0;
190 }
191 spin_unlock(&clp->cl_lock);
192 nfs_delegation_claim_opens(inode);
193 up_write(&nfsi->rwsem); 185 up_write(&nfsi->rwsem);
194 up_read(&clp->cl_sem); 186 up_read(&clp->cl_sem);
195 nfs_msync_inode(inode); 187 nfs_msync_inode(inode);
196 188
197 if (delegation != NULL) 189 return nfs_do_return_delegation(inode, delegation);
198 res = nfs_do_return_delegation(inode, delegation); 190}
199 return res; 191
192static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
193{
194 struct nfs_delegation *delegation = nfsi->delegation;
195
196 if (delegation == NULL)
197 goto nomatch;
198 if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
199 sizeof(delegation->stateid.data)) != 0)
200 goto nomatch;
201 list_del_init(&delegation->super_list);
202 nfsi->delegation = NULL;
203 nfsi->delegation_state = 0;
204 return delegation;
205nomatch:
206 return NULL;
207}
208
209int nfs_inode_return_delegation(struct inode *inode)
210{
211 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
212 struct nfs_inode *nfsi = NFS_I(inode);
213 struct nfs_delegation *delegation;
214 int err = 0;
215
216 if (nfsi->delegation_state != 0) {
217 spin_lock(&clp->cl_lock);
218 delegation = nfs_detach_delegation_locked(nfsi, NULL);
219 spin_unlock(&clp->cl_lock);
220 if (delegation != NULL)
221 err = __nfs_inode_return_delegation(inode, delegation);
222 }
223 return err;
200} 224}
201 225
202/* 226/*
@@ -218,8 +242,9 @@ restart:
218 inode = igrab(delegation->inode); 242 inode = igrab(delegation->inode);
219 if (inode == NULL) 243 if (inode == NULL)
220 continue; 244 continue;
245 nfs_detach_delegation_locked(NFS_I(inode), NULL);
221 spin_unlock(&clp->cl_lock); 246 spin_unlock(&clp->cl_lock);
222 nfs_inode_return_delegation(inode); 247 __nfs_inode_return_delegation(inode, delegation);
223 iput(inode); 248 iput(inode);
224 goto restart; 249 goto restart;
225 } 250 }
@@ -243,8 +268,9 @@ restart:
243 inode = igrab(delegation->inode); 268 inode = igrab(delegation->inode);
244 if (inode == NULL) 269 if (inode == NULL)
245 continue; 270 continue;
271 nfs_detach_delegation_locked(NFS_I(inode), NULL);
246 spin_unlock(&clp->cl_lock); 272 spin_unlock(&clp->cl_lock);
247 nfs_inode_return_delegation(inode); 273 __nfs_inode_return_delegation(inode, delegation);
248 iput(inode); 274 iput(inode);
249 goto restart; 275 goto restart;
250 } 276 }
@@ -285,8 +311,9 @@ restart:
285 inode = igrab(delegation->inode); 311 inode = igrab(delegation->inode);
286 if (inode == NULL) 312 if (inode == NULL)
287 continue; 313 continue;
314 nfs_detach_delegation_locked(NFS_I(inode), NULL);
288 spin_unlock(&clp->cl_lock); 315 spin_unlock(&clp->cl_lock);
289 nfs_inode_return_delegation(inode); 316 __nfs_inode_return_delegation(inode, delegation);
290 iput(inode); 317 iput(inode);
291 goto restart; 318 goto restart;
292 } 319 }
@@ -316,21 +343,14 @@ static int recall_thread(void *data)
316 down_read(&clp->cl_sem); 343 down_read(&clp->cl_sem);
317 down_write(&nfsi->rwsem); 344 down_write(&nfsi->rwsem);
318 spin_lock(&clp->cl_lock); 345 spin_lock(&clp->cl_lock);
319 delegation = nfsi->delegation; 346 delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
320 if (delegation != NULL && memcmp(delegation->stateid.data, 347 if (delegation != NULL)
321 args->stateid->data,
322 sizeof(delegation->stateid.data)) == 0) {
323 list_del_init(&delegation->super_list);
324 nfsi->delegation = NULL;
325 nfsi->delegation_state = 0;
326 args->result = 0; 348 args->result = 0;
327 } else { 349 else
328 delegation = NULL;
329 args->result = -ENOENT; 350 args->result = -ENOENT;
330 }
331 spin_unlock(&clp->cl_lock); 351 spin_unlock(&clp->cl_lock);
332 complete(&args->started); 352 complete(&args->started);
333 nfs_delegation_claim_opens(inode); 353 nfs_delegation_claim_opens(inode, args->stateid);
334 up_write(&nfsi->rwsem); 354 up_write(&nfsi->rwsem);
335 up_read(&clp->cl_sem); 355 up_read(&clp->cl_sem);
336 nfs_msync_inode(inode); 356 nfs_msync_inode(inode);