Merge branch 'locks'

+80 -44
+17 -9
fs/lockd/clntproc.c
··· 454 fl->fl_ops = &nlmclnt_lock_ops; 455 } 456 457 - static void do_vfs_lock(struct file_lock *fl) 458 { 459 int res = 0; 460 switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) { ··· 467 default: 468 BUG(); 469 } 470 - if (res < 0) 471 - printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", 472 - __FUNCTION__); 473 } 474 475 /* ··· 496 struct nlm_host *host = req->a_host; 497 struct nlm_res *resp = &req->a_res; 498 struct nlm_wait *block = NULL; 499 int status = -ENOLCK; 500 501 if (!host->h_monitored && nsm_monitor(host) < 0) { ··· 504 host->h_name); 505 goto out; 506 } 507 508 block = nlmclnt_prepare_block(host, fl); 509 again: ··· 542 up_read(&host->h_rwsem); 543 goto again; 544 } 545 - fl->fl_flags |= FL_SLEEP; 546 /* Ensure the resulting lock will get added to granted list */ 547 - do_vfs_lock(fl); 548 up_read(&host->h_rwsem); 549 } 550 status = nlm_stat_to_errno(resp->status); ··· 556 nlmclnt_cancel(host, req->a_args.block, fl); 557 out: 558 nlm_release_call(req); 559 return status; 560 } 561 ··· 611 { 612 struct nlm_host *host = req->a_host; 613 struct nlm_res *resp = &req->a_res; 614 - int status; 615 616 /* 617 * Note: the server is supposed to either grant us the unlock 618 * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either 619 * case, we want to unlock. 620 */ 621 down_read(&host->h_rwsem); 622 - do_vfs_lock(fl); 623 up_read(&host->h_rwsem); 624 625 if (req->a_flags & RPC_TASK_ASYNC) ··· 633 if (status < 0) 634 goto out; 635 636 - status = 0; 637 if (resp->status == NLM_LCK_GRANTED) 638 goto out; 639
··· 454 fl->fl_ops = &nlmclnt_lock_ops; 455 } 456 457 + static int do_vfs_lock(struct file_lock *fl) 458 { 459 int res = 0; 460 switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) { ··· 467 default: 468 BUG(); 469 } 470 + return res; 471 } 472 473 /* ··· 498 struct nlm_host *host = req->a_host; 499 struct nlm_res *resp = &req->a_res; 500 struct nlm_wait *block = NULL; 501 + unsigned char fl_flags = fl->fl_flags; 502 int status = -ENOLCK; 503 504 if (!host->h_monitored && nsm_monitor(host) < 0) { ··· 505 host->h_name); 506 goto out; 507 } 508 + fl->fl_flags |= FL_ACCESS; 509 + status = do_vfs_lock(fl); 510 + if (status < 0) 511 + goto out; 512 513 block = nlmclnt_prepare_block(host, fl); 514 again: ··· 539 up_read(&host->h_rwsem); 540 goto again; 541 } 542 /* Ensure the resulting lock will get added to granted list */ 543 + fl->fl_flags = fl_flags | FL_SLEEP; 544 + if (do_vfs_lock(fl) < 0) 545 + printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); 546 up_read(&host->h_rwsem); 547 } 548 status = nlm_stat_to_errno(resp->status); ··· 552 nlmclnt_cancel(host, req->a_args.block, fl); 553 out: 554 nlm_release_call(req); 555 + fl->fl_flags = fl_flags; 556 return status; 557 } 558 ··· 606 { 607 struct nlm_host *host = req->a_host; 608 struct nlm_res *resp = &req->a_res; 609 + int status = 0; 610 611 /* 612 * Note: the server is supposed to either grant us the unlock 613 * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either 614 * case, we want to unlock. 615 */ 616 + fl->fl_flags |= FL_EXISTS; 617 down_read(&host->h_rwsem); 618 + if (do_vfs_lock(fl) == -ENOENT) { 619 + up_read(&host->h_rwsem); 620 + goto out; 621 + } 622 up_read(&host->h_rwsem); 623 624 if (req->a_flags & RPC_TASK_ASYNC) ··· 624 if (status < 0) 625 goto out; 626 627 if (resp->status == NLM_LCK_GRANTED) 628 goto out; 629
+21 -2
fs/locks.c
··· 725 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks 726 * at the head of the list, but that's secret knowledge known only to 727 * flock_lock_file and posix_lock_file. 728 */ 729 static int flock_lock_file(struct file *filp, struct file_lock *request) 730 { ··· 739 int found = 0; 740 741 lock_kernel(); 742 for_each_lock(inode, before) { 743 struct file_lock *fl = *before; 744 if (IS_POSIX(fl)) ··· 756 break; 757 } 758 759 - if (request->fl_type == F_UNLCK) 760 goto out; 761 762 error = -ENOMEM; 763 new_fl = locks_alloc_lock(); ··· 773 if (found) 774 cond_resched(); 775 776 for_each_lock(inode, before) { 777 struct file_lock *fl = *before; 778 if (IS_POSIX(fl)) ··· 787 locks_insert_block(fl, request); 788 goto out; 789 } 790 locks_copy_lock(new_fl, request); 791 locks_insert_lock(&inode->i_flock, new_fl); 792 new_fl = NULL; ··· 960 961 error = 0; 962 if (!added) { 963 - if (request->fl_type == F_UNLCK) 964 goto out; 965 966 if (!new_fl) { 967 error = -ENOLCK; ··· 1011 * Add a POSIX style lock to a file. 1012 * We merge adjacent & overlapping locks whenever possible. 1013 * POSIX locks are sorted by owner task, then by starting address 1014 */ 1015 int posix_lock_file(struct file *filp, struct file_lock *fl) 1016 {
··· 725 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks 726 * at the head of the list, but that's secret knowledge known only to 727 * flock_lock_file and posix_lock_file. 728 + * 729 + * Note that if called with an FL_EXISTS argument, the caller may determine 730 + * whether or not a lock was successfully freed by testing the return 731 + * value for -ENOENT. 732 */ 733 static int flock_lock_file(struct file *filp, struct file_lock *request) 734 { ··· 735 int found = 0; 736 737 lock_kernel(); 738 + if (request->fl_flags & FL_ACCESS) 739 + goto find_conflict; 740 for_each_lock(inode, before) { 741 struct file_lock *fl = *before; 742 if (IS_POSIX(fl)) ··· 750 break; 751 } 752 753 + if (request->fl_type == F_UNLCK) { 754 + if ((request->fl_flags & FL_EXISTS) && !found) 755 + error = -ENOENT; 756 goto out; 757 + } 758 759 error = -ENOMEM; 760 new_fl = locks_alloc_lock(); ··· 764 if (found) 765 cond_resched(); 766 767 + find_conflict: 768 for_each_lock(inode, before) { 769 struct file_lock *fl = *before; 770 if (IS_POSIX(fl)) ··· 777 locks_insert_block(fl, request); 778 goto out; 779 } 780 + if (request->fl_flags & FL_ACCESS) 781 + goto out; 782 locks_copy_lock(new_fl, request); 783 locks_insert_lock(&inode->i_flock, new_fl); 784 new_fl = NULL; ··· 948 949 error = 0; 950 if (!added) { 951 + if (request->fl_type == F_UNLCK) { 952 + if (request->fl_flags & FL_EXISTS) 953 + error = -ENOENT; 954 goto out; 955 + } 956 957 if (!new_fl) { 958 error = -ENOLCK; ··· 996 * Add a POSIX style lock to a file. 997 * We merge adjacent & overlapping locks whenever possible. 998 * POSIX locks are sorted by owner task, then by starting address 999 + * 1000 + * Note that if called with an FL_EXISTS argument, the caller may determine 1001 + * whether or not a lock was successfully freed by testing the return 1002 + * value for -ENOENT. 1003 */ 1004 int posix_lock_file(struct file *filp, struct file_lock *fl) 1005 {
+41 -33
fs/nfs/nfs4proc.c
··· 3144 default: 3145 BUG(); 3146 } 3147 - if (res < 0) 3148 - printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", 3149 - __FUNCTION__); 3150 return res; 3151 } 3152 ··· 3255 return ERR_PTR(-ENOMEM); 3256 } 3257 3258 - /* Unlock _before_ we do the RPC call */ 3259 - do_vfs_lock(fl->fl_file, fl); 3260 return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); 3261 } 3262 ··· 3265 struct rpc_task *task; 3266 int status = 0; 3267 3268 /* Is this a delegated lock? */ 3269 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) 3270 - goto out_unlock; 3271 - /* Is this open_owner holding any locks on the server? */ 3272 - if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) 3273 - goto out_unlock; 3274 - 3275 - status = nfs4_set_lock_state(state, request); 3276 - if (status != 0) 3277 - goto out_unlock; 3278 lsp = request->fl_u.nfs4_fl.owner; 3279 - status = -ENOMEM; 3280 seqid = nfs_alloc_seqid(&lsp->ls_seqid); 3281 if (seqid == NULL) 3282 - goto out_unlock; 3283 task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid); 3284 status = PTR_ERR(task); 3285 if (IS_ERR(task)) 3286 - goto out_unlock; 3287 status = nfs4_wait_for_completion_rpc_task(task); 3288 rpc_release_task(task); 3289 - return status; 3290 - out_unlock: 3291 - do_vfs_lock(request->fl_file, request); 3292 return status; 3293 } 3294 ··· 3454 struct nfs4_exception exception = { }; 3455 int err; 3456 3457 - /* Cache the lock if possible... */ 3458 - if (test_bit(NFS_DELEGATED_STATE, &state->flags)) 3459 - return 0; 3460 do { 3461 err = _nfs4_do_setlk(state, F_SETLK, request, 1); 3462 if (err != -NFS4ERR_DELAY) 3463 break; ··· 3476 if (err != 0) 3477 return err; 3478 do { 3479 err = _nfs4_do_setlk(state, F_SETLK, request, 0); 3480 if (err != -NFS4ERR_DELAY) 3481 break; ··· 3489 static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) 3490 { 3491 struct nfs4_client *clp = state->owner->so_client; 3492 int status; 3493 3494 /* Is this a delegated open? */ 3495 - if (NFS_I(state->inode)->delegation_state != 0) { 3496 - /* Yes: cache locks! */ 3497 - status = do_vfs_lock(request->fl_file, request); 3498 - /* ...but avoid races with delegation recall... */ 3499 - if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags)) 3500 - return status; 3501 - } 3502 - down_read(&clp->cl_sem); 3503 status = nfs4_set_lock_state(state, request); 3504 if (status != 0) 3505 goto out; 3506 status = _nfs4_do_setlk(state, cmd, request, 0); 3507 if (status != 0) 3508 - goto out; 3509 /* Note: we always want to sleep here! */ 3510 - request->fl_flags |= FL_SLEEP; 3511 if (do_vfs_lock(request->fl_file, request) < 0) 3512 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); 3513 - out: 3514 up_read(&clp->cl_sem); 3515 return status; 3516 } 3517
··· 3144 default: 3145 BUG(); 3146 } 3147 return res; 3148 } 3149 ··· 3258 return ERR_PTR(-ENOMEM); 3259 } 3260 3261 return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); 3262 } 3263 ··· 3270 struct rpc_task *task; 3271 int status = 0; 3272 3273 + status = nfs4_set_lock_state(state, request); 3274 + /* Unlock _before_ we do the RPC call */ 3275 + request->fl_flags |= FL_EXISTS; 3276 + if (do_vfs_lock(request->fl_file, request) == -ENOENT) 3277 + goto out; 3278 + if (status != 0) 3279 + goto out; 3280 /* Is this a delegated lock? */ 3281 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) 3282 + goto out; 3283 lsp = request->fl_u.nfs4_fl.owner; 3284 seqid = nfs_alloc_seqid(&lsp->ls_seqid); 3285 + status = -ENOMEM; 3286 if (seqid == NULL) 3287 + goto out; 3288 task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid); 3289 status = PTR_ERR(task); 3290 if (IS_ERR(task)) 3291 + goto out; 3292 status = nfs4_wait_for_completion_rpc_task(task); 3293 rpc_release_task(task); 3294 + out: 3295 return status; 3296 } 3297 ··· 3461 struct nfs4_exception exception = { }; 3462 int err; 3463 3464 do { 3465 + /* Cache the lock if possible... */ 3466 + if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) 3467 + return 0; 3468 err = _nfs4_do_setlk(state, F_SETLK, request, 1); 3469 if (err != -NFS4ERR_DELAY) 3470 break; ··· 3483 if (err != 0) 3484 return err; 3485 do { 3486 + if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) 3487 + return 0; 3488 err = _nfs4_do_setlk(state, F_SETLK, request, 0); 3489 if (err != -NFS4ERR_DELAY) 3490 break; ··· 3494 static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) 3495 { 3496 struct nfs4_client *clp = state->owner->so_client; 3497 + unsigned char fl_flags = request->fl_flags; 3498 int status; 3499 3500 /* Is this a delegated open? */ 3501 status = nfs4_set_lock_state(state, request); 3502 if (status != 0) 3503 goto out; 3504 + request->fl_flags |= FL_ACCESS; 3505 + status = do_vfs_lock(request->fl_file, request); 3506 + if (status < 0) 3507 + goto out; 3508 + down_read(&clp->cl_sem); 3509 + if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { 3510 + struct nfs_inode *nfsi = NFS_I(state->inode); 3511 + /* Yes: cache locks! */ 3512 + down_read(&nfsi->rwsem); 3513 + /* ...but avoid races with delegation recall... */ 3514 + if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { 3515 + request->fl_flags = fl_flags & ~FL_SLEEP; 3516 + status = do_vfs_lock(request->fl_file, request); 3517 + up_read(&nfsi->rwsem); 3518 + goto out_unlock; 3519 + } 3520 + up_read(&nfsi->rwsem); 3521 + } 3522 status = _nfs4_do_setlk(state, cmd, request, 0); 3523 if (status != 0) 3524 + goto out_unlock; 3525 /* Note: we always want to sleep here! */ 3526 + request->fl_flags = fl_flags | FL_SLEEP; 3527 if (do_vfs_lock(request->fl_file, request) < 0) 3528 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); 3529 + out_unlock: 3530 up_read(&clp->cl_sem); 3531 + out: 3532 + request->fl_flags = fl_flags; 3533 return status; 3534 } 3535
+1
include/linux/fs.h
··· 716 #define FL_POSIX 1 717 #define FL_FLOCK 2 718 #define FL_ACCESS 8 /* not trying to lock, just looking */ 719 #define FL_LEASE 32 /* lease held on this file */ 720 #define FL_CLOSE 64 /* unlock on close */ 721 #define FL_SLEEP 128 /* A blocking lock */
··· 716 #define FL_POSIX 1 717 #define FL_FLOCK 2 718 #define FL_ACCESS 8 /* not trying to lock, just looking */ 719 + #define FL_EXISTS 16 /* when unlocking, test for existence */ 720 #define FL_LEASE 32 /* lease held on this file */ 721 #define FL_CLOSE 64 /* unlock on close */ 722 #define FL_SLEEP 128 /* A blocking lock */