diff options
Diffstat (limited to 'fs/lockd/clntproc.c')
-rw-r--r-- | fs/lockd/clntproc.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 145524039577..970b6a6aa337 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -22,12 +22,14 @@ | |||
22 | #define NLMDBG_FACILITY NLMDBG_CLIENT | 22 | #define NLMDBG_FACILITY NLMDBG_CLIENT |
23 | #define NLMCLNT_GRACE_WAIT (5*HZ) | 23 | #define NLMCLNT_GRACE_WAIT (5*HZ) |
24 | #define NLMCLNT_POLL_TIMEOUT (30*HZ) | 24 | #define NLMCLNT_POLL_TIMEOUT (30*HZ) |
25 | #define NLMCLNT_MAX_RETRIES 3 | ||
25 | 26 | ||
26 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); | 27 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); |
27 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); | 28 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); |
28 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); | 29 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); |
29 | static int nlm_stat_to_errno(u32 stat); | 30 | static int nlm_stat_to_errno(u32 stat); |
30 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); | 31 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); |
32 | static int nlmclnt_cancel(struct nlm_host *, int , struct file_lock *); | ||
31 | 33 | ||
32 | static const struct rpc_call_ops nlmclnt_unlock_ops; | 34 | static const struct rpc_call_ops nlmclnt_unlock_ops; |
33 | static const struct rpc_call_ops nlmclnt_cancel_ops; | 35 | static const struct rpc_call_ops nlmclnt_cancel_ops; |
@@ -598,7 +600,7 @@ out_unblock: | |||
598 | nlmclnt_finish_block(req); | 600 | nlmclnt_finish_block(req); |
599 | /* Cancel the blocked request if it is still pending */ | 601 | /* Cancel the blocked request if it is still pending */ |
600 | if (resp->status == NLM_LCK_BLOCKED) | 602 | if (resp->status == NLM_LCK_BLOCKED) |
601 | nlmclnt_cancel(host, fl); | 603 | nlmclnt_cancel(host, req->a_args.block, fl); |
602 | out: | 604 | out: |
603 | nlmclnt_release_lockargs(req); | 605 | nlmclnt_release_lockargs(req); |
604 | return status; | 606 | return status; |
@@ -660,12 +662,18 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
660 | * reclaimed while we're stuck in the unlock call. */ | 662 | * reclaimed while we're stuck in the unlock call. */ |
661 | fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; | 663 | fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; |
662 | 664 | ||
665 | /* | ||
666 | * Note: the server is supposed to either grant us the unlock | ||
667 | * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either | ||
668 | * case, we want to unlock. | ||
669 | */ | ||
670 | do_vfs_lock(fl); | ||
671 | |||
663 | if (req->a_flags & RPC_TASK_ASYNC) { | 672 | if (req->a_flags & RPC_TASK_ASYNC) { |
664 | status = nlmclnt_async_call(req, NLMPROC_UNLOCK, | 673 | status = nlmclnt_async_call(req, NLMPROC_UNLOCK, |
665 | &nlmclnt_unlock_ops); | 674 | &nlmclnt_unlock_ops); |
666 | /* Hrmf... Do the unlock early since locks_remove_posix() | 675 | /* Hrmf... Do the unlock early since locks_remove_posix() |
667 | * really expects us to free the lock synchronously */ | 676 | * really expects us to free the lock synchronously */ |
668 | do_vfs_lock(fl); | ||
669 | if (status < 0) { | 677 | if (status < 0) { |
670 | nlmclnt_release_lockargs(req); | 678 | nlmclnt_release_lockargs(req); |
671 | kfree(req); | 679 | kfree(req); |
@@ -678,7 +686,6 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
678 | if (status < 0) | 686 | if (status < 0) |
679 | return status; | 687 | return status; |
680 | 688 | ||
681 | do_vfs_lock(fl); | ||
682 | if (resp->status == NLM_LCK_GRANTED) | 689 | if (resp->status == NLM_LCK_GRANTED) |
683 | return 0; | 690 | return 0; |
684 | 691 | ||
@@ -728,8 +735,7 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = { | |||
728 | * We always use an async RPC call for this in order not to hang a | 735 | * We always use an async RPC call for this in order not to hang a |
729 | * process that has been Ctrl-C'ed. | 736 | * process that has been Ctrl-C'ed. |
730 | */ | 737 | */ |
731 | int | 738 | static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl) |
732 | nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) | ||
733 | { | 739 | { |
734 | struct nlm_rqst *req; | 740 | struct nlm_rqst *req; |
735 | unsigned long flags; | 741 | unsigned long flags; |
@@ -750,6 +756,7 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) | |||
750 | req->a_flags = RPC_TASK_ASYNC; | 756 | req->a_flags = RPC_TASK_ASYNC; |
751 | 757 | ||
752 | nlmclnt_setlockargs(req, fl); | 758 | nlmclnt_setlockargs(req, fl); |
759 | req->a_args.block = block; | ||
753 | 760 | ||
754 | status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); | 761 | status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); |
755 | if (status < 0) { | 762 | if (status < 0) { |
@@ -801,6 +808,9 @@ die: | |||
801 | return; | 808 | return; |
802 | 809 | ||
803 | retry_cancel: | 810 | retry_cancel: |
811 | /* Don't ever retry more than 3 times */ | ||
812 | if (req->a_retries++ >= NLMCLNT_MAX_RETRIES) | ||
813 | goto die; | ||
804 | nlm_rebind_host(req->a_host); | 814 | nlm_rebind_host(req->a_host); |
805 | rpc_restart_call(task); | 815 | rpc_restart_call(task); |
806 | rpc_delay(task, 30 * HZ); | 816 | rpc_delay(task, 30 * HZ); |