Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

locks: add special return value for asynchronous locks

Use a special error value FILE_LOCK_DEFERRED to mean that a locking
operation returned asynchronously. This is returned by

posix_lock_file() for sleeping locks to mean that the lock has been
queued on the block list, and will be woken up when it might become
available and needs to be retried (either fl_lmops->fl_notify() is
called or fl_wait is woken up).

f_op->lock() to mean either the above, or that the filesystem will
call back with fl_lmops->fl_grant() when the result of the locking
operation is known. The filesystem can do this for sleeping as well
as non-sleeping locks.

This is to make sure, that return values of -EAGAIN and -EINPROGRESS by
filesystems are not mistaken to mean an asynchronous locking.

This also makes error handling in fs/locks.c and lockd/svclock.c slightly
cleaner.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: David Teigland <teigland@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Miklos Szeredi and committed by
Linus Torvalds
bde74e4b cc77b152

+25 -24
+1 -1
fs/dlm/plock.c
··· 116 116 if (xop->callback == NULL) 117 117 wait_event(recv_wq, (op->done != 0)); 118 118 else { 119 - rv = -EINPROGRESS; 119 + rv = FILE_LOCK_DEFERRED; 120 120 goto out; 121 121 } 122 122
+4 -9
fs/lockd/svclock.c
··· 418 418 goto out; 419 419 case -EAGAIN: 420 420 ret = nlm_lck_denied; 421 - break; 422 - case -EINPROGRESS: 421 + goto out; 422 + case FILE_LOCK_DEFERRED: 423 423 if (wait) 424 424 break; 425 425 /* Filesystem lock operation is in progress ··· 433 433 ret = nlm_lck_denied_nolocks; 434 434 goto out; 435 435 } 436 - 437 - ret = nlm_lck_denied; 438 - if (!wait) 439 - goto out; 440 436 441 437 ret = nlm_lck_blocked; 442 438 ··· 503 507 } 504 508 505 509 error = vfs_test_lock(file->f_file, &lock->fl); 506 - if (error == -EINPROGRESS) { 510 + if (error == FILE_LOCK_DEFERRED) { 507 511 ret = nlmsvc_defer_lock_rqst(rqstp, block); 508 512 goto out; 509 513 } ··· 727 731 switch (error) { 728 732 case 0: 729 733 break; 730 - case -EAGAIN: 731 - case -EINPROGRESS: 734 + case FILE_LOCK_DEFERRED: 732 735 dprintk("lockd: lock still blocked error %d\n", error); 733 736 nlmsvc_insert_block(block, NLM_NEVER); 734 737 nlmsvc_release_block(block);
+14 -14
fs/locks.c
··· 779 779 if (!flock_locks_conflict(request, fl)) 780 780 continue; 781 781 error = -EAGAIN; 782 - if (request->fl_flags & FL_SLEEP) 783 - locks_insert_block(fl, request); 782 + if (!(request->fl_flags & FL_SLEEP)) 783 + goto out; 784 + error = FILE_LOCK_DEFERRED; 785 + locks_insert_block(fl, request); 784 786 goto out; 785 787 } 786 788 if (request->fl_flags & FL_ACCESS) ··· 838 836 error = -EDEADLK; 839 837 if (posix_locks_deadlock(request, fl)) 840 838 goto out; 841 - error = -EAGAIN; 839 + error = FILE_LOCK_DEFERRED; 842 840 locks_insert_block(fl, request); 843 841 goto out; 844 842 } ··· 1037 1035 might_sleep (); 1038 1036 for (;;) { 1039 1037 error = posix_lock_file(filp, fl, NULL); 1040 - if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) 1038 + if (error != FILE_LOCK_DEFERRED) 1041 1039 break; 1042 1040 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); 1043 1041 if (!error) ··· 1109 1107 1110 1108 for (;;) { 1111 1109 error = __posix_lock_file(inode, &fl, NULL); 1112 - if (error != -EAGAIN) 1113 - break; 1114 - if (!(fl.fl_flags & FL_SLEEP)) 1110 + if (error != FILE_LOCK_DEFERRED) 1115 1111 break; 1116 1112 error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); 1117 1113 if (!error) { ··· 1531 1531 might_sleep(); 1532 1532 for (;;) { 1533 1533 error = flock_lock_file(filp, fl); 1534 - if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) 1534 + if (error != FILE_LOCK_DEFERRED) 1535 1535 break; 1536 1536 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); 1537 1537 if (!error) ··· 1716 1716 * fl_grant is set. Callers expecting ->lock() to return asynchronously 1717 1717 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) 1718 1718 * the request is for a blocking lock. When ->lock() does return asynchronously, 1719 - * it must return -EINPROGRESS, and call ->fl_grant() when the lock 1719 + * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock 1720 1720 * request completes. 1721 1721 * If the request is for non-blocking lock the file system should return 1722 - * -EINPROGRESS then try to get the lock and call the callback routine with 1723 - * the result. If the request timed out the callback routine will return a 1722 + * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine 1723 + * with the result. If the request timed out the callback routine will return a 1724 1724 * nonzero return code and the file system should release the lock. The file 1725 1725 * system is also responsible to keep a corresponding posix lock when it 1726 1726 * grants a lock so the VFS can find out which locks are locally held and do 1727 1727 * the correct lock cleanup when required. 1728 1728 * The underlying filesystem must not drop the kernel lock or call 1729 - * ->fl_grant() before returning to the caller with a -EINPROGRESS 1729 + * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED 1730 1730 * return code. 1731 1731 */ 1732 1732 int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) ··· 1804 1804 else { 1805 1805 for (;;) { 1806 1806 error = posix_lock_file(filp, file_lock, NULL); 1807 - if (error != -EAGAIN || cmd == F_SETLK) 1807 + if (error != FILE_LOCK_DEFERRED) 1808 1808 break; 1809 1809 error = wait_event_interruptible(file_lock->fl_wait, 1810 1810 !file_lock->fl_next); ··· 1941 1941 else { 1942 1942 for (;;) { 1943 1943 error = posix_lock_file(filp, file_lock, NULL); 1944 - if (error != -EAGAIN || cmd == F_SETLK64) 1944 + if (error != FILE_LOCK_DEFERRED) 1945 1945 break; 1946 1946 error = wait_event_interruptible(file_lock->fl_wait, 1947 1947 !file_lock->fl_next);
+6
include/linux/fs.h
··· 886 886 #define FL_SLEEP 128 /* A blocking lock */ 887 887 888 888 /* 889 + * Special return value from posix_lock_file() and vfs_lock_file() for 890 + * asynchronous locking. 891 + */ 892 + #define FILE_LOCK_DEFERRED 1 893 + 894 + /* 889 895 * The POSIX file lock owner is determined by 890 896 * the "struct files_struct" in the thread group 891 897 * (or NULL for no owner - BSD locks).