diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-12-23 15:21:51 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-12-23 15:21:51 -0500 |
| commit | 6411bd4a471893ab2af103d96253ba97c92d4777 (patch) | |
| tree | 573c6a571d1dd500a98f51f3341d031354a17013 | |
| parent | b0d3ded1a21dc3057daff5a488469d9e6aa1b567 (diff) | |
NFSv4: Clean up the asynchronous delegation return
Reuse the state management thread in order to return delegations when we
get a callback.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -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 | /* |
