diff options
-rw-r--r-- | fs/lockd/clntlock.c | 43 | ||||
-rw-r--r-- | fs/lockd/clntproc.c | 39 | ||||
-rw-r--r-- | include/linux/lockd/lockd.h | 7 |
3 files changed, 35 insertions, 54 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 7cf41c1e1a88..bce744468708 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -44,32 +44,25 @@ static LIST_HEAD(nlm_blocked); | |||
44 | /* | 44 | /* |
45 | * Queue up a lock for blocking so that the GRANTED request can see it | 45 | * Queue up a lock for blocking so that the GRANTED request can see it |
46 | */ | 46 | */ |
47 | int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl) | 47 | struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl) |
48 | { | 48 | { |
49 | struct nlm_wait *block; | 49 | struct nlm_wait *block; |
50 | 50 | ||
51 | BUG_ON(req->a_block != NULL); | ||
52 | block = kmalloc(sizeof(*block), GFP_KERNEL); | 51 | block = kmalloc(sizeof(*block), GFP_KERNEL); |
53 | if (block == NULL) | 52 | if (block != NULL) { |
54 | return -ENOMEM; | 53 | block->b_host = host; |
55 | block->b_host = host; | 54 | block->b_lock = fl; |
56 | block->b_lock = fl; | 55 | init_waitqueue_head(&block->b_wait); |
57 | init_waitqueue_head(&block->b_wait); | 56 | block->b_status = NLM_LCK_BLOCKED; |
58 | block->b_status = NLM_LCK_BLOCKED; | 57 | list_add(&block->b_list, &nlm_blocked); |
59 | 58 | } | |
60 | list_add(&block->b_list, &nlm_blocked); | 59 | return block; |
61 | req->a_block = block; | ||
62 | |||
63 | return 0; | ||
64 | } | 60 | } |
65 | 61 | ||
66 | void nlmclnt_finish_block(struct nlm_rqst *req) | 62 | void nlmclnt_finish_block(struct nlm_wait *block) |
67 | { | 63 | { |
68 | struct nlm_wait *block = req->a_block; | ||
69 | |||
70 | if (block == NULL) | 64 | if (block == NULL) |
71 | return; | 65 | return; |
72 | req->a_block = NULL; | ||
73 | list_del(&block->b_list); | 66 | list_del(&block->b_list); |
74 | kfree(block); | 67 | kfree(block); |
75 | } | 68 | } |
@@ -77,15 +70,14 @@ void nlmclnt_finish_block(struct nlm_rqst *req) | |||
77 | /* | 70 | /* |
78 | * Block on a lock | 71 | * Block on a lock |
79 | */ | 72 | */ |
80 | long nlmclnt_block(struct nlm_rqst *req, long timeout) | 73 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) |
81 | { | 74 | { |
82 | struct nlm_wait *block = req->a_block; | ||
83 | long ret; | 75 | long ret; |
84 | 76 | ||
85 | /* A borken server might ask us to block even if we didn't | 77 | /* A borken server might ask us to block even if we didn't |
86 | * request it. Just say no! | 78 | * request it. Just say no! |
87 | */ | 79 | */ |
88 | if (!req->a_args.block) | 80 | if (block == NULL) |
89 | return -EAGAIN; | 81 | return -EAGAIN; |
90 | 82 | ||
91 | /* Go to sleep waiting for GRANT callback. Some servers seem | 83 | /* Go to sleep waiting for GRANT callback. Some servers seem |
@@ -99,13 +91,10 @@ long nlmclnt_block(struct nlm_rqst *req, long timeout) | |||
99 | ret = wait_event_interruptible_timeout(block->b_wait, | 91 | ret = wait_event_interruptible_timeout(block->b_wait, |
100 | block->b_status != NLM_LCK_BLOCKED, | 92 | block->b_status != NLM_LCK_BLOCKED, |
101 | timeout); | 93 | timeout); |
102 | 94 | if (ret < 0) | |
103 | if (block->b_status != NLM_LCK_BLOCKED) { | 95 | return -ERESTARTSYS; |
104 | req->a_res.status = block->b_status; | 96 | req->a_res.status = block->b_status; |
105 | block->b_status = NLM_LCK_BLOCKED; | 97 | return 0; |
106 | } | ||
107 | |||
108 | return ret; | ||
109 | } | 98 | } |
110 | 99 | ||
111 | /* | 100 | /* |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index c25044f3b660..8af017105854 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -136,15 +136,14 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) | |||
136 | (unsigned int)fl->fl_u.nfs_fl.owner->pid, | 136 | (unsigned int)fl->fl_u.nfs_fl.owner->pid, |
137 | system_utsname.nodename); | 137 | system_utsname.nodename); |
138 | lock->svid = fl->fl_u.nfs_fl.owner->pid; | 138 | lock->svid = fl->fl_u.nfs_fl.owner->pid; |
139 | locks_copy_lock(&lock->fl, fl); | 139 | lock->fl.fl_start = fl->fl_start; |
140 | lock->fl.fl_end = fl->fl_end; | ||
141 | lock->fl.fl_type = fl->fl_type; | ||
140 | } | 142 | } |
141 | 143 | ||
142 | static void nlmclnt_release_lockargs(struct nlm_rqst *req) | 144 | static void nlmclnt_release_lockargs(struct nlm_rqst *req) |
143 | { | 145 | { |
144 | struct file_lock *fl = &req->a_args.lock.fl; | 146 | BUG_ON(req->a_args.lock.fl.fl_ops != NULL); |
145 | |||
146 | if (fl->fl_ops && fl->fl_ops->fl_release_private) | ||
147 | fl->fl_ops->fl_release_private(fl); | ||
148 | } | 147 | } |
149 | 148 | ||
150 | /* | 149 | /* |
@@ -455,7 +454,6 @@ static void nlmclnt_locks_release_private(struct file_lock *fl) | |||
455 | { | 454 | { |
456 | list_del(&fl->fl_u.nfs_fl.list); | 455 | list_del(&fl->fl_u.nfs_fl.list); |
457 | nlm_put_lockowner(fl->fl_u.nfs_fl.owner); | 456 | nlm_put_lockowner(fl->fl_u.nfs_fl.owner); |
458 | fl->fl_ops = NULL; | ||
459 | } | 457 | } |
460 | 458 | ||
461 | static struct file_lock_operations nlmclnt_lock_ops = { | 459 | static struct file_lock_operations nlmclnt_lock_ops = { |
@@ -515,41 +513,36 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) | |||
515 | { | 513 | { |
516 | struct nlm_host *host = req->a_host; | 514 | struct nlm_host *host = req->a_host; |
517 | struct nlm_res *resp = &req->a_res; | 515 | struct nlm_res *resp = &req->a_res; |
518 | long timeout; | 516 | struct nlm_wait *block = NULL; |
519 | int status; | 517 | int status = -ENOLCK; |
520 | 518 | ||
521 | if (!host->h_monitored && nsm_monitor(host) < 0) { | 519 | if (!host->h_monitored && nsm_monitor(host) < 0) { |
522 | printk(KERN_NOTICE "lockd: failed to monitor %s\n", | 520 | printk(KERN_NOTICE "lockd: failed to monitor %s\n", |
523 | host->h_name); | 521 | host->h_name); |
524 | status = -ENOLCK; | ||
525 | goto out; | 522 | goto out; |
526 | } | 523 | } |
527 | 524 | ||
528 | if (req->a_args.block) { | 525 | block = nlmclnt_prepare_block(host, fl); |
529 | status = nlmclnt_prepare_block(req, host, fl); | ||
530 | if (status < 0) | ||
531 | goto out; | ||
532 | } | ||
533 | for(;;) { | 526 | for(;;) { |
534 | status = nlmclnt_call(req, NLMPROC_LOCK); | 527 | status = nlmclnt_call(req, NLMPROC_LOCK); |
535 | if (status < 0) | 528 | if (status < 0) |
536 | goto out_unblock; | 529 | goto out_unblock; |
537 | if (resp->status != NLM_LCK_BLOCKED) | 530 | if (!req->a_args.block) |
538 | break; | 531 | break; |
539 | /* Wait on an NLM blocking lock */ | ||
540 | timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT); | ||
541 | /* Did a reclaimer thread notify us of a server reboot? */ | 532 | /* Did a reclaimer thread notify us of a server reboot? */ |
542 | if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) | 533 | if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) |
543 | continue; | 534 | continue; |
544 | if (resp->status != NLM_LCK_BLOCKED) | 535 | if (resp->status != NLM_LCK_BLOCKED) |
545 | break; | 536 | break; |
546 | if (timeout >= 0) | 537 | /* Wait on an NLM blocking lock */ |
547 | continue; | 538 | status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT); |
548 | /* We were interrupted. Send a CANCEL request to the server | 539 | /* if we were interrupted. Send a CANCEL request to the server |
549 | * and exit | 540 | * and exit |
550 | */ | 541 | */ |
551 | status = (int)timeout; | 542 | if (status < 0) |
552 | goto out_unblock; | 543 | goto out_unblock; |
544 | if (resp->status != NLM_LCK_BLOCKED) | ||
545 | break; | ||
553 | } | 546 | } |
554 | 547 | ||
555 | if (resp->status == NLM_LCK_GRANTED) { | 548 | if (resp->status == NLM_LCK_GRANTED) { |
@@ -560,7 +553,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) | |||
560 | } | 553 | } |
561 | status = nlm_stat_to_errno(resp->status); | 554 | status = nlm_stat_to_errno(resp->status); |
562 | out_unblock: | 555 | out_unblock: |
563 | nlmclnt_finish_block(req); | 556 | nlmclnt_finish_block(block); |
564 | /* Cancel the blocked request if it is still pending */ | 557 | /* Cancel the blocked request if it is still pending */ |
565 | if (resp->status == NLM_LCK_BLOCKED) | 558 | if (resp->status == NLM_LCK_BLOCKED) |
566 | nlmclnt_cancel(host, req->a_args.block, fl); | 559 | nlmclnt_cancel(host, req->a_args.block, fl); |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index b0f63b6ab0d4..cb9933d04091 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
@@ -86,7 +86,6 @@ struct nlm_rqst { | |||
86 | struct nlm_host * a_host; /* host handle */ | 86 | struct nlm_host * a_host; /* host handle */ |
87 | struct nlm_args a_args; /* arguments */ | 87 | struct nlm_args a_args; /* arguments */ |
88 | struct nlm_res a_res; /* result */ | 88 | struct nlm_res a_res; /* result */ |
89 | struct nlm_wait * a_block; | ||
90 | unsigned int a_retries; /* Retry count */ | 89 | unsigned int a_retries; /* Retry count */ |
91 | char a_owner[NLMCLNT_OHSIZE]; | 90 | char a_owner[NLMCLNT_OHSIZE]; |
92 | }; | 91 | }; |
@@ -149,9 +148,9 @@ extern unsigned long nlmsvc_timeout; | |||
149 | * Lockd client functions | 148 | * Lockd client functions |
150 | */ | 149 | */ |
151 | struct nlm_rqst * nlmclnt_alloc_call(void); | 150 | struct nlm_rqst * nlmclnt_alloc_call(void); |
152 | int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl); | 151 | struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); |
153 | void nlmclnt_finish_block(struct nlm_rqst *req); | 152 | void nlmclnt_finish_block(struct nlm_wait *block); |
154 | long nlmclnt_block(struct nlm_rqst *req, long timeout); | 153 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); |
155 | u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); | 154 | u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); |
156 | void nlmclnt_recovery(struct nlm_host *, u32); | 155 | void nlmclnt_recovery(struct nlm_host *, u32); |
157 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); | 156 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); |