diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 90 |
1 files changed, 38 insertions, 52 deletions
diff --git a/fs/locks.c b/fs/locks.c index dce8c747371c..01490300f7cb 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -779,8 +779,10 @@ find_conflict: | |||
779 | if (!flock_locks_conflict(request, fl)) | 779 | if (!flock_locks_conflict(request, fl)) |
780 | continue; | 780 | continue; |
781 | error = -EAGAIN; | 781 | error = -EAGAIN; |
782 | if (request->fl_flags & FL_SLEEP) | 782 | if (!(request->fl_flags & FL_SLEEP)) |
783 | locks_insert_block(fl, request); | 783 | goto out; |
784 | error = FILE_LOCK_DEFERRED; | ||
785 | locks_insert_block(fl, request); | ||
784 | goto out; | 786 | goto out; |
785 | } | 787 | } |
786 | if (request->fl_flags & FL_ACCESS) | 788 | if (request->fl_flags & FL_ACCESS) |
@@ -836,7 +838,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
836 | error = -EDEADLK; | 838 | error = -EDEADLK; |
837 | if (posix_locks_deadlock(request, fl)) | 839 | if (posix_locks_deadlock(request, fl)) |
838 | goto out; | 840 | goto out; |
839 | error = -EAGAIN; | 841 | error = FILE_LOCK_DEFERRED; |
840 | locks_insert_block(fl, request); | 842 | locks_insert_block(fl, request); |
841 | goto out; | 843 | goto out; |
842 | } | 844 | } |
@@ -1035,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl) | |||
1035 | might_sleep (); | 1037 | might_sleep (); |
1036 | for (;;) { | 1038 | for (;;) { |
1037 | error = posix_lock_file(filp, fl, NULL); | 1039 | error = posix_lock_file(filp, fl, NULL); |
1038 | if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) | 1040 | if (error != FILE_LOCK_DEFERRED) |
1039 | break; | 1041 | break; |
1040 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | 1042 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); |
1041 | if (!error) | 1043 | if (!error) |
@@ -1107,9 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode, | |||
1107 | 1109 | ||
1108 | for (;;) { | 1110 | for (;;) { |
1109 | error = __posix_lock_file(inode, &fl, NULL); | 1111 | error = __posix_lock_file(inode, &fl, NULL); |
1110 | if (error != -EAGAIN) | 1112 | if (error != FILE_LOCK_DEFERRED) |
1111 | break; | ||
1112 | if (!(fl.fl_flags & FL_SLEEP)) | ||
1113 | break; | 1113 | break; |
1114 | error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); | 1114 | error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); |
1115 | if (!error) { | 1115 | if (!error) { |
@@ -1531,7 +1531,7 @@ int flock_lock_file_wait(struct file *filp, struct file_lock *fl) | |||
1531 | might_sleep(); | 1531 | might_sleep(); |
1532 | for (;;) { | 1532 | for (;;) { |
1533 | error = flock_lock_file(filp, fl); | 1533 | error = flock_lock_file(filp, fl); |
1534 | if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) | 1534 | if (error != FILE_LOCK_DEFERRED) |
1535 | break; | 1535 | break; |
1536 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | 1536 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); |
1537 | if (!error) | 1537 | if (!error) |
@@ -1716,17 +1716,17 @@ out: | |||
1716 | * fl_grant is set. Callers expecting ->lock() to return asynchronously | 1716 | * fl_grant is set. Callers expecting ->lock() to return asynchronously |
1717 | * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) | 1717 | * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) |
1718 | * the request is for a blocking lock. When ->lock() does return asynchronously, | 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 | * request completes. | 1720 | * request completes. |
1721 | * If the request is for non-blocking lock the file system should return | 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 | 1722 | * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine |
1723 | * the result. If the request timed out the callback routine will return a | 1723 | * with the result. If the request timed out the callback routine will return a |
1724 | * nonzero return code and the file system should release the lock. The file | 1724 | * nonzero return code and the file system should release the lock. The file |
1725 | * system is also responsible to keep a corresponding posix lock when it | 1725 | * system is also responsible to keep a corresponding posix lock when it |
1726 | * grants a lock so the VFS can find out which locks are locally held and do | 1726 | * grants a lock so the VFS can find out which locks are locally held and do |
1727 | * the correct lock cleanup when required. | 1727 | * the correct lock cleanup when required. |
1728 | * The underlying filesystem must not drop the kernel lock or call | 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 | * return code. | 1730 | * return code. |
1731 | */ | 1731 | */ |
1732 | int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) | 1732 | int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) |
@@ -1738,6 +1738,30 @@ int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, str | |||
1738 | } | 1738 | } |
1739 | EXPORT_SYMBOL_GPL(vfs_lock_file); | 1739 | EXPORT_SYMBOL_GPL(vfs_lock_file); |
1740 | 1740 | ||
1741 | static int do_lock_file_wait(struct file *filp, unsigned int cmd, | ||
1742 | struct file_lock *fl) | ||
1743 | { | ||
1744 | int error; | ||
1745 | |||
1746 | error = security_file_lock(filp, fl->fl_type); | ||
1747 | if (error) | ||
1748 | return error; | ||
1749 | |||
1750 | for (;;) { | ||
1751 | error = vfs_lock_file(filp, cmd, fl, NULL); | ||
1752 | if (error != FILE_LOCK_DEFERRED) | ||
1753 | break; | ||
1754 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | ||
1755 | if (!error) | ||
1756 | continue; | ||
1757 | |||
1758 | locks_delete_block(fl); | ||
1759 | break; | ||
1760 | } | ||
1761 | |||
1762 | return error; | ||
1763 | } | ||
1764 | |||
1741 | /* Apply the lock described by l to an open file descriptor. | 1765 | /* Apply the lock described by l to an open file descriptor. |
1742 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 1766 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
1743 | */ | 1767 | */ |
@@ -1795,26 +1819,7 @@ again: | |||
1795 | goto out; | 1819 | goto out; |
1796 | } | 1820 | } |
1797 | 1821 | ||
1798 | error = security_file_lock(filp, file_lock->fl_type); | 1822 | error = do_lock_file_wait(filp, cmd, file_lock); |
1799 | if (error) | ||
1800 | goto out; | ||
1801 | |||
1802 | if (filp->f_op && filp->f_op->lock != NULL) | ||
1803 | error = filp->f_op->lock(filp, cmd, file_lock); | ||
1804 | else { | ||
1805 | for (;;) { | ||
1806 | error = posix_lock_file(filp, file_lock, NULL); | ||
1807 | if (error != -EAGAIN || cmd == F_SETLK) | ||
1808 | break; | ||
1809 | error = wait_event_interruptible(file_lock->fl_wait, | ||
1810 | !file_lock->fl_next); | ||
1811 | if (!error) | ||
1812 | continue; | ||
1813 | |||
1814 | locks_delete_block(file_lock); | ||
1815 | break; | ||
1816 | } | ||
1817 | } | ||
1818 | 1823 | ||
1819 | /* | 1824 | /* |
1820 | * Attempt to detect a close/fcntl race and recover by | 1825 | * Attempt to detect a close/fcntl race and recover by |
@@ -1932,26 +1937,7 @@ again: | |||
1932 | goto out; | 1937 | goto out; |
1933 | } | 1938 | } |
1934 | 1939 | ||
1935 | error = security_file_lock(filp, file_lock->fl_type); | 1940 | error = do_lock_file_wait(filp, cmd, file_lock); |
1936 | if (error) | ||
1937 | goto out; | ||
1938 | |||
1939 | if (filp->f_op && filp->f_op->lock != NULL) | ||
1940 | error = filp->f_op->lock(filp, cmd, file_lock); | ||
1941 | else { | ||
1942 | for (;;) { | ||
1943 | error = posix_lock_file(filp, file_lock, NULL); | ||
1944 | if (error != -EAGAIN || cmd == F_SETLK64) | ||
1945 | break; | ||
1946 | error = wait_event_interruptible(file_lock->fl_wait, | ||
1947 | !file_lock->fl_next); | ||
1948 | if (!error) | ||
1949 | continue; | ||
1950 | |||
1951 | locks_delete_block(file_lock); | ||
1952 | break; | ||
1953 | } | ||
1954 | } | ||
1955 | 1941 | ||
1956 | /* | 1942 | /* |
1957 | * Attempt to detect a close/fcntl race and recover by | 1943 | * Attempt to detect a close/fcntl race and recover by |