diff options
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r-- | fs/nfs/delegation.c | 73 |
1 files changed, 19 insertions, 54 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 21eda6c083d0..00c350c031b4 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -321,6 +321,12 @@ int nfs_inode_return_delegation(struct inode *inode) | |||
321 | return err; | 321 | return err; |
322 | } | 322 | } |
323 | 323 | ||
324 | static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation) | ||
325 | { | ||
326 | set_bit(NFS_DELEGATION_RETURN, &delegation->flags); | ||
327 | set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); | ||
328 | } | ||
329 | |||
324 | /* | 330 | /* |
325 | * Return all delegations associated to a super block | 331 | * Return all delegations associated to a super block |
326 | */ | 332 | */ |
@@ -376,66 +382,25 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp) | |||
376 | nfs_client_mark_return_all_delegations(clp); | 382 | nfs_client_mark_return_all_delegations(clp); |
377 | } | 383 | } |
378 | 384 | ||
379 | struct recall_threadargs { | ||
380 | struct inode *inode; | ||
381 | struct nfs_client *clp; | ||
382 | const nfs4_stateid *stateid; | ||
383 | |||
384 | struct completion started; | ||
385 | int result; | ||
386 | }; | ||
387 | |||
388 | static int recall_thread(void *data) | ||
389 | { | ||
390 | struct recall_threadargs *args = (struct recall_threadargs *)data; | ||
391 | struct inode *inode = igrab(args->inode); | ||
392 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | ||
393 | struct nfs_inode *nfsi = NFS_I(inode); | ||
394 | struct nfs_delegation *delegation; | ||
395 | |||
396 | daemonize("nfsv4-delegreturn"); | ||
397 | |||
398 | nfs_msync_inode(inode); | ||
399 | down_write(&nfsi->rwsem); | ||
400 | spin_lock(&clp->cl_lock); | ||
401 | delegation = nfs_detach_delegation_locked(nfsi, args->stateid); | ||
402 | if (delegation != NULL) | ||
403 | args->result = 0; | ||
404 | else | ||
405 | args->result = -ENOENT; | ||
406 | spin_unlock(&clp->cl_lock); | ||
407 | complete(&args->started); | ||
408 | nfs_delegation_claim_opens(inode, args->stateid); | ||
409 | up_write(&nfsi->rwsem); | ||
410 | nfs_msync_inode(inode); | ||
411 | |||
412 | if (delegation != NULL) | ||
413 | nfs_do_return_delegation(inode, delegation, 1); | ||
414 | iput(inode); | ||
415 | module_put_and_exit(0); | ||
416 | } | ||
417 | |||
418 | /* | 385 | /* |
419 | * Asynchronous delegation recall! | 386 | * Asynchronous delegation recall! |
420 | */ | 387 | */ |
421 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) | 388 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) |
422 | { | 389 | { |
423 | struct recall_threadargs data = { | 390 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
424 | .inode = inode, | 391 | struct nfs_delegation *delegation; |
425 | .stateid = stateid, | ||
426 | }; | ||
427 | int status; | ||
428 | 392 | ||
429 | init_completion(&data.started); | 393 | rcu_read_lock(); |
430 | __module_get(THIS_MODULE); | 394 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
431 | status = kernel_thread(recall_thread, &data, CLONE_KERNEL); | 395 | if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, |
432 | if (status < 0) | 396 | sizeof(delegation->stateid.data)) != 0) { |
433 | goto out_module_put; | 397 | rcu_read_unlock(); |
434 | wait_for_completion(&data.started); | 398 | return -ENOENT; |
435 | return data.result; | 399 | } |
436 | out_module_put: | 400 | nfs_mark_return_delegation(clp, delegation); |
437 | module_put(THIS_MODULE); | 401 | rcu_read_unlock(); |
438 | return status; | 402 | nfs_delegation_run_state_manager(clp); |
403 | return 0; | ||
439 | } | 404 | } |
440 | 405 | ||
441 | /* | 406 | /* |