diff options
Diffstat (limited to 'fs/locks.c')
| -rw-r--r-- | fs/locks.c | 92 |
1 files changed, 39 insertions, 53 deletions
diff --git a/fs/locks.c b/fs/locks.c index dce8c747371c..5eb259e3cd38 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -201,7 +201,7 @@ EXPORT_SYMBOL(locks_init_lock); | |||
| 201 | * Initialises the fields of the file lock which are invariant for | 201 | * Initialises the fields of the file lock which are invariant for |
| 202 | * free file_locks. | 202 | * free file_locks. |
| 203 | */ | 203 | */ |
| 204 | static void init_once(struct kmem_cache *cache, void *foo) | 204 | static void init_once(void *foo) |
| 205 | { | 205 | { |
| 206 | struct file_lock *lock = (struct file_lock *) foo; | 206 | struct file_lock *lock = (struct file_lock *) foo; |
| 207 | 207 | ||
| @@ -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 |
