diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:47 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:47 -0500 |
| commit | d9f6eb75d4900782a095b98470decfe98971f920 (patch) | |
| tree | 6378e43b6fba38a2ee8359379aedf3b07daeea21 | |
| parent | 51581f3bf922512880f52a7777923fd6dcfc792b (diff) | |
lockd: blocks should hold a reference to the nlm_file
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -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 | ||
