diff options
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/svclock.c | 81 |
1 files changed, 46 insertions, 35 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index c16c94f5a856..ce754efe2841 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -103,11 +103,10 @@ nlmsvc_remove_block(struct nlm_block *block) | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Find a block for a given lock and optionally remove it from | 106 | * Find a block for a given lock |
107 | * the list. | ||
108 | */ | 107 | */ |
109 | static struct nlm_block * | 108 | static struct nlm_block * |
110 | nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) | 109 | nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) |
111 | { | 110 | { |
112 | struct nlm_block **head, *block; | 111 | struct nlm_block **head, *block; |
113 | struct file_lock *fl; | 112 | struct file_lock *fl; |
@@ -124,10 +123,6 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) | |||
124 | (long long)fl->fl_end, fl->fl_type, | 123 | (long long)fl->fl_end, fl->fl_type, |
125 | nlmdbg_cookie2a(&block->b_call->a_args.cookie)); | 124 | nlmdbg_cookie2a(&block->b_call->a_args.cookie)); |
126 | if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { | 125 | if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { |
127 | if (remove) { | ||
128 | *head = block->b_next; | ||
129 | block->b_queued = 0; | ||
130 | } | ||
131 | kref_get(&block->b_count); | 126 | kref_get(&block->b_count); |
132 | return block; | 127 | return block; |
133 | } | 128 | } |
@@ -213,6 +208,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
213 | block->b_daemon = rqstp->rq_server; | 208 | block->b_daemon = rqstp->rq_server; |
214 | block->b_host = host; | 209 | block->b_host = host; |
215 | block->b_file = file; | 210 | block->b_file = file; |
211 | file->f_count++; | ||
216 | 212 | ||
217 | /* Add to file's list of blocks */ | 213 | /* Add to file's list of blocks */ |
218 | block->b_fnext = file->f_blocks; | 214 | block->b_fnext = file->f_blocks; |
@@ -257,6 +253,7 @@ static void nlmsvc_free_block(struct kref *kref) | |||
257 | 253 | ||
258 | dprintk("lockd: freeing block %p...\n", block); | 254 | dprintk("lockd: freeing block %p...\n", block); |
259 | 255 | ||
256 | down(&file->f_sema); | ||
260 | /* Remove block from file's list of blocks */ | 257 | /* Remove block from file's list of blocks */ |
261 | for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { | 258 | for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { |
262 | if (*bp == block) { | 259 | if (*bp == block) { |
@@ -264,9 +261,11 @@ static void nlmsvc_free_block(struct kref *kref) | |||
264 | break; | 261 | break; |
265 | } | 262 | } |
266 | } | 263 | } |
264 | up(&file->f_sema); | ||
267 | 265 | ||
268 | nlmsvc_freegrantargs(block->b_call); | 266 | nlmsvc_freegrantargs(block->b_call); |
269 | nlm_release_call(block->b_call); | 267 | nlm_release_call(block->b_call); |
268 | nlm_release_file(block->b_file); | ||
270 | kfree(block); | 269 | kfree(block); |
271 | } | 270 | } |
272 | 271 | ||
@@ -276,6 +275,36 @@ static void nlmsvc_release_block(struct nlm_block *block) | |||
276 | kref_put(&block->b_count, nlmsvc_free_block); | 275 | kref_put(&block->b_count, nlmsvc_free_block); |
277 | } | 276 | } |
278 | 277 | ||
278 | static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file) | ||
279 | { | ||
280 | struct nlm_block *block; | ||
281 | |||
282 | down(&file->f_sema); | ||
283 | for (block = file->f_blocks; block != NULL; block = block->b_fnext) | ||
284 | block->b_host->h_inuse = 1; | ||
285 | up(&file->f_sema); | ||
286 | } | ||
287 | |||
288 | static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file) | ||
289 | { | ||
290 | struct nlm_block *block; | ||
291 | |||
292 | restart: | ||
293 | down(&file->f_sema); | ||
294 | for (block = file->f_blocks; block != NULL; block = block->b_fnext) { | ||
295 | if (host != NULL && host != block->b_host) | ||
296 | continue; | ||
297 | if (!block->b_queued) | ||
298 | continue; | ||
299 | kref_get(&block->b_count); | ||
300 | up(&file->f_sema); | ||
301 | nlmsvc_unlink_block(block); | ||
302 | nlmsvc_release_block(block); | ||
303 | goto restart; | ||
304 | } | ||
305 | up(&file->f_sema); | ||
306 | } | ||
307 | |||
279 | /* | 308 | /* |
280 | * Loop over all blocks and perform the action specified. | 309 | * Loop over all blocks and perform the action specified. |
281 | * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). | 310 | * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). |
@@ -283,20 +312,10 @@ static void nlmsvc_release_block(struct nlm_block *block) | |||
283 | int | 312 | int |
284 | nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) | 313 | nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) |
285 | { | 314 | { |
286 | struct nlm_block *block, *next; | 315 | if (action == NLM_ACT_MARK) |
287 | /* XXX: Will everything get cleaned up if we don't unlock here? */ | 316 | nlmsvc_act_mark(host, file); |
288 | 317 | else | |
289 | down(&file->f_sema); | 318 | nlmsvc_act_unlock(host, file); |
290 | for (block = file->f_blocks; block; block = next) { | ||
291 | next = block->b_fnext; | ||
292 | if (action == NLM_ACT_MARK) | ||
293 | block->b_host->h_inuse = 1; | ||
294 | else if (action == NLM_ACT_UNLOCK) { | ||
295 | if (host == NULL || host == block->b_host) | ||
296 | nlmsvc_unlink_block(block); | ||
297 | } | ||
298 | } | ||
299 | up(&file->f_sema); | ||
300 | return 0; | 319 | return 0; |
301 | } | 320 | } |
302 | 321 | ||
@@ -358,7 +377,7 @@ again: | |||
358 | /* Lock file against concurrent access */ | 377 | /* Lock file against concurrent access */ |
359 | down(&file->f_sema); | 378 | down(&file->f_sema); |
360 | /* Get existing block (in case client is busy-waiting) */ | 379 | /* Get existing block (in case client is busy-waiting) */ |
361 | block = nlmsvc_lookup_block(file, lock, 0); | 380 | block = nlmsvc_lookup_block(file, lock); |
362 | if (block == NULL) { | 381 | if (block == NULL) { |
363 | if (newblock != NULL) | 382 | if (newblock != NULL) |
364 | lock = &newblock->b_call->a_args.lock; | 383 | lock = &newblock->b_call->a_args.lock; |
@@ -491,11 +510,12 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
491 | (long long)lock->fl.fl_end); | 510 | (long long)lock->fl.fl_end); |
492 | 511 | ||
493 | down(&file->f_sema); | 512 | down(&file->f_sema); |
494 | if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) { | 513 | block = nlmsvc_lookup_block(file, lock); |
514 | up(&file->f_sema); | ||
515 | if (block != NULL) { | ||
495 | status = nlmsvc_unlink_block(block); | 516 | status = nlmsvc_unlink_block(block); |
496 | nlmsvc_release_block(block); | 517 | nlmsvc_release_block(block); |
497 | } | 518 | } |
498 | up(&file->f_sema); | ||
499 | return status ? nlm_lck_denied : nlm_granted; | 519 | return status ? nlm_lck_denied : nlm_granted; |
500 | } | 520 | } |
501 | 521 | ||
@@ -553,9 +573,6 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
553 | 573 | ||
554 | dprintk("lockd: grant blocked lock %p\n", block); | 574 | dprintk("lockd: grant blocked lock %p\n", block); |
555 | 575 | ||
556 | /* First thing is lock the file */ | ||
557 | down(&file->f_sema); | ||
558 | |||
559 | /* Unlink block request from list */ | 576 | /* Unlink block request from list */ |
560 | nlmsvc_unlink_block(block); | 577 | nlmsvc_unlink_block(block); |
561 | 578 | ||
@@ -578,12 +595,12 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
578 | case -EAGAIN: | 595 | case -EAGAIN: |
579 | dprintk("lockd: lock still blocked\n"); | 596 | dprintk("lockd: lock still blocked\n"); |
580 | nlmsvc_insert_block(block, NLM_NEVER); | 597 | nlmsvc_insert_block(block, NLM_NEVER); |
581 | goto out_unlock; | 598 | return; |
582 | default: | 599 | default: |
583 | printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", | 600 | printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", |
584 | -error, __FUNCTION__); | 601 | -error, __FUNCTION__); |
585 | nlmsvc_insert_block(block, 10 * HZ); | 602 | nlmsvc_insert_block(block, 10 * HZ); |
586 | goto out_unlock; | 603 | return; |
587 | } | 604 | } |
588 | 605 | ||
589 | callback: | 606 | callback: |
@@ -599,8 +616,6 @@ callback: | |||
599 | if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, | 616 | if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, |
600 | &nlmsvc_grant_ops) < 0) | 617 | &nlmsvc_grant_ops) < 0) |
601 | nlmsvc_release_block(block); | 618 | nlmsvc_release_block(block); |
602 | out_unlock: | ||
603 | up(&file->f_sema); | ||
604 | } | 619 | } |
605 | 620 | ||
606 | /* | 621 | /* |
@@ -665,8 +680,6 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status | |||
665 | return; | 680 | return; |
666 | file = block->b_file; | 681 | file = block->b_file; |
667 | 682 | ||
668 | file->f_count++; | ||
669 | down(&file->f_sema); | ||
670 | if (block) { | 683 | if (block) { |
671 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { | 684 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { |
672 | /* Try again in a couple of seconds */ | 685 | /* Try again in a couple of seconds */ |
@@ -677,8 +690,6 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status | |||
677 | nlmsvc_unlink_block(block); | 690 | nlmsvc_unlink_block(block); |
678 | } | 691 | } |
679 | } | 692 | } |
680 | up(&file->f_sema); | ||
681 | nlm_release_file(file); | ||
682 | nlmsvc_release_block(block); | 693 | nlmsvc_release_block(block); |
683 | } | 694 | } |
684 | 695 | ||