diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 91 |
1 files changed, 51 insertions, 40 deletions
diff --git a/fs/locks.c b/fs/locks.c index 13fc7a6d380a..e390bd9ae068 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -135,7 +135,7 @@ | |||
135 | #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) | 135 | #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) |
136 | #define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK) | 136 | #define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK) |
137 | #define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG)) | 137 | #define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG)) |
138 | #define IS_FILE_PVT(fl) (fl->fl_flags & FL_FILE_PVT) | 138 | #define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK) |
139 | 139 | ||
140 | static bool lease_breaking(struct file_lock *fl) | 140 | static bool lease_breaking(struct file_lock *fl) |
141 | { | 141 | { |
@@ -389,18 +389,6 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, | |||
389 | fl->fl_ops = NULL; | 389 | fl->fl_ops = NULL; |
390 | fl->fl_lmops = NULL; | 390 | fl->fl_lmops = NULL; |
391 | 391 | ||
392 | /* Ensure that fl->fl_filp has compatible f_mode */ | ||
393 | switch (l->l_type) { | ||
394 | case F_RDLCK: | ||
395 | if (!(filp->f_mode & FMODE_READ)) | ||
396 | return -EBADF; | ||
397 | break; | ||
398 | case F_WRLCK: | ||
399 | if (!(filp->f_mode & FMODE_WRITE)) | ||
400 | return -EBADF; | ||
401 | break; | ||
402 | } | ||
403 | |||
404 | return assign_type(fl, l->l_type); | 392 | return assign_type(fl, l->l_type); |
405 | } | 393 | } |
406 | 394 | ||
@@ -564,7 +552,7 @@ static void __locks_insert_block(struct file_lock *blocker, | |||
564 | BUG_ON(!list_empty(&waiter->fl_block)); | 552 | BUG_ON(!list_empty(&waiter->fl_block)); |
565 | waiter->fl_next = blocker; | 553 | waiter->fl_next = blocker; |
566 | list_add_tail(&waiter->fl_block, &blocker->fl_block); | 554 | list_add_tail(&waiter->fl_block, &blocker->fl_block); |
567 | if (IS_POSIX(blocker) && !IS_FILE_PVT(blocker)) | 555 | if (IS_POSIX(blocker) && !IS_OFDLCK(blocker)) |
568 | locks_insert_global_blocked(waiter); | 556 | locks_insert_global_blocked(waiter); |
569 | } | 557 | } |
570 | 558 | ||
@@ -759,12 +747,12 @@ EXPORT_SYMBOL(posix_test_lock); | |||
759 | * of tasks (such as posix threads) sharing the same open file table. | 747 | * of tasks (such as posix threads) sharing the same open file table. |
760 | * To handle those cases, we just bail out after a few iterations. | 748 | * To handle those cases, we just bail out after a few iterations. |
761 | * | 749 | * |
762 | * For FL_FILE_PVT locks, the owner is the filp, not the files_struct. | 750 | * For FL_OFDLCK locks, the owner is the filp, not the files_struct. |
763 | * Because the owner is not even nominally tied to a thread of | 751 | * Because the owner is not even nominally tied to a thread of |
764 | * execution, the deadlock detection below can't reasonably work well. Just | 752 | * execution, the deadlock detection below can't reasonably work well. Just |
765 | * skip it for those. | 753 | * skip it for those. |
766 | * | 754 | * |
767 | * In principle, we could do a more limited deadlock detection on FL_FILE_PVT | 755 | * In principle, we could do a more limited deadlock detection on FL_OFDLCK |
768 | * locks that just checks for the case where two tasks are attempting to | 756 | * locks that just checks for the case where two tasks are attempting to |
769 | * upgrade from read to write locks on the same inode. | 757 | * upgrade from read to write locks on the same inode. |
770 | */ | 758 | */ |
@@ -791,9 +779,9 @@ static int posix_locks_deadlock(struct file_lock *caller_fl, | |||
791 | 779 | ||
792 | /* | 780 | /* |
793 | * This deadlock detector can't reasonably detect deadlocks with | 781 | * This deadlock detector can't reasonably detect deadlocks with |
794 | * FL_FILE_PVT locks, since they aren't owned by a process, per-se. | 782 | * FL_OFDLCK locks, since they aren't owned by a process, per-se. |
795 | */ | 783 | */ |
796 | if (IS_FILE_PVT(caller_fl)) | 784 | if (IS_OFDLCK(caller_fl)) |
797 | return 0; | 785 | return 0; |
798 | 786 | ||
799 | while ((block_fl = what_owner_is_waiting_for(block_fl))) { | 787 | while ((block_fl = what_owner_is_waiting_for(block_fl))) { |
@@ -1391,11 +1379,10 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) | |||
1391 | 1379 | ||
1392 | restart: | 1380 | restart: |
1393 | break_time = flock->fl_break_time; | 1381 | break_time = flock->fl_break_time; |
1394 | if (break_time != 0) { | 1382 | if (break_time != 0) |
1395 | break_time -= jiffies; | 1383 | break_time -= jiffies; |
1396 | if (break_time == 0) | 1384 | if (break_time == 0) |
1397 | break_time++; | 1385 | break_time++; |
1398 | } | ||
1399 | locks_insert_block(flock, new_fl); | 1386 | locks_insert_block(flock, new_fl); |
1400 | spin_unlock(&inode->i_lock); | 1387 | spin_unlock(&inode->i_lock); |
1401 | error = wait_event_interruptible_timeout(new_fl->fl_wait, | 1388 | error = wait_event_interruptible_timeout(new_fl->fl_wait, |
@@ -1891,7 +1878,7 @@ EXPORT_SYMBOL_GPL(vfs_test_lock); | |||
1891 | 1878 | ||
1892 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) | 1879 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) |
1893 | { | 1880 | { |
1894 | flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid; | 1881 | flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid; |
1895 | #if BITS_PER_LONG == 32 | 1882 | #if BITS_PER_LONG == 32 |
1896 | /* | 1883 | /* |
1897 | * Make sure we can represent the posix lock via | 1884 | * Make sure we can represent the posix lock via |
@@ -1913,7 +1900,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) | |||
1913 | #if BITS_PER_LONG == 32 | 1900 | #if BITS_PER_LONG == 32 |
1914 | static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) | 1901 | static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) |
1915 | { | 1902 | { |
1916 | flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid; | 1903 | flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid; |
1917 | flock->l_start = fl->fl_start; | 1904 | flock->l_start = fl->fl_start; |
1918 | flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : | 1905 | flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : |
1919 | fl->fl_end - fl->fl_start + 1; | 1906 | fl->fl_end - fl->fl_start + 1; |
@@ -1942,13 +1929,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) | |||
1942 | if (error) | 1929 | if (error) |
1943 | goto out; | 1930 | goto out; |
1944 | 1931 | ||
1945 | if (cmd == F_GETLKP) { | 1932 | if (cmd == F_OFD_GETLK) { |
1946 | error = -EINVAL; | 1933 | error = -EINVAL; |
1947 | if (flock.l_pid != 0) | 1934 | if (flock.l_pid != 0) |
1948 | goto out; | 1935 | goto out; |
1949 | 1936 | ||
1950 | cmd = F_GETLK; | 1937 | cmd = F_GETLK; |
1951 | file_lock.fl_flags |= FL_FILE_PVT; | 1938 | file_lock.fl_flags |= FL_OFDLCK; |
1952 | file_lock.fl_owner = (fl_owner_t)filp; | 1939 | file_lock.fl_owner = (fl_owner_t)filp; |
1953 | } | 1940 | } |
1954 | 1941 | ||
@@ -2035,6 +2022,22 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd, | |||
2035 | return error; | 2022 | return error; |
2036 | } | 2023 | } |
2037 | 2024 | ||
2025 | /* Ensure that fl->fl_filp has compatible f_mode for F_SETLK calls */ | ||
2026 | static int | ||
2027 | check_fmode_for_setlk(struct file_lock *fl) | ||
2028 | { | ||
2029 | switch (fl->fl_type) { | ||
2030 | case F_RDLCK: | ||
2031 | if (!(fl->fl_file->f_mode & FMODE_READ)) | ||
2032 | return -EBADF; | ||
2033 | break; | ||
2034 | case F_WRLCK: | ||
2035 | if (!(fl->fl_file->f_mode & FMODE_WRITE)) | ||
2036 | return -EBADF; | ||
2037 | } | ||
2038 | return 0; | ||
2039 | } | ||
2040 | |||
2038 | /* Apply the lock described by l to an open file descriptor. | 2041 | /* Apply the lock described by l to an open file descriptor. |
2039 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 2042 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
2040 | */ | 2043 | */ |
@@ -2072,27 +2075,31 @@ again: | |||
2072 | if (error) | 2075 | if (error) |
2073 | goto out; | 2076 | goto out; |
2074 | 2077 | ||
2078 | error = check_fmode_for_setlk(file_lock); | ||
2079 | if (error) | ||
2080 | goto out; | ||
2081 | |||
2075 | /* | 2082 | /* |
2076 | * If the cmd is requesting file-private locks, then set the | 2083 | * If the cmd is requesting file-private locks, then set the |
2077 | * FL_FILE_PVT flag and override the owner. | 2084 | * FL_OFDLCK flag and override the owner. |
2078 | */ | 2085 | */ |
2079 | switch (cmd) { | 2086 | switch (cmd) { |
2080 | case F_SETLKP: | 2087 | case F_OFD_SETLK: |
2081 | error = -EINVAL; | 2088 | error = -EINVAL; |
2082 | if (flock.l_pid != 0) | 2089 | if (flock.l_pid != 0) |
2083 | goto out; | 2090 | goto out; |
2084 | 2091 | ||
2085 | cmd = F_SETLK; | 2092 | cmd = F_SETLK; |
2086 | file_lock->fl_flags |= FL_FILE_PVT; | 2093 | file_lock->fl_flags |= FL_OFDLCK; |
2087 | file_lock->fl_owner = (fl_owner_t)filp; | 2094 | file_lock->fl_owner = (fl_owner_t)filp; |
2088 | break; | 2095 | break; |
2089 | case F_SETLKPW: | 2096 | case F_OFD_SETLKW: |
2090 | error = -EINVAL; | 2097 | error = -EINVAL; |
2091 | if (flock.l_pid != 0) | 2098 | if (flock.l_pid != 0) |
2092 | goto out; | 2099 | goto out; |
2093 | 2100 | ||
2094 | cmd = F_SETLKW; | 2101 | cmd = F_SETLKW; |
2095 | file_lock->fl_flags |= FL_FILE_PVT; | 2102 | file_lock->fl_flags |= FL_OFDLCK; |
2096 | file_lock->fl_owner = (fl_owner_t)filp; | 2103 | file_lock->fl_owner = (fl_owner_t)filp; |
2097 | /* Fallthrough */ | 2104 | /* Fallthrough */ |
2098 | case F_SETLKW: | 2105 | case F_SETLKW: |
@@ -2144,13 +2151,13 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) | |||
2144 | if (error) | 2151 | if (error) |
2145 | goto out; | 2152 | goto out; |
2146 | 2153 | ||
2147 | if (cmd == F_GETLKP) { | 2154 | if (cmd == F_OFD_GETLK) { |
2148 | error = -EINVAL; | 2155 | error = -EINVAL; |
2149 | if (flock.l_pid != 0) | 2156 | if (flock.l_pid != 0) |
2150 | goto out; | 2157 | goto out; |
2151 | 2158 | ||
2152 | cmd = F_GETLK64; | 2159 | cmd = F_GETLK64; |
2153 | file_lock.fl_flags |= FL_FILE_PVT; | 2160 | file_lock.fl_flags |= FL_OFDLCK; |
2154 | file_lock.fl_owner = (fl_owner_t)filp; | 2161 | file_lock.fl_owner = (fl_owner_t)filp; |
2155 | } | 2162 | } |
2156 | 2163 | ||
@@ -2207,27 +2214,31 @@ again: | |||
2207 | if (error) | 2214 | if (error) |
2208 | goto out; | 2215 | goto out; |
2209 | 2216 | ||
2217 | error = check_fmode_for_setlk(file_lock); | ||
2218 | if (error) | ||
2219 | goto out; | ||
2220 | |||
2210 | /* | 2221 | /* |
2211 | * If the cmd is requesting file-private locks, then set the | 2222 | * If the cmd is requesting file-private locks, then set the |
2212 | * FL_FILE_PVT flag and override the owner. | 2223 | * FL_OFDLCK flag and override the owner. |
2213 | */ | 2224 | */ |
2214 | switch (cmd) { | 2225 | switch (cmd) { |
2215 | case F_SETLKP: | 2226 | case F_OFD_SETLK: |
2216 | error = -EINVAL; | 2227 | error = -EINVAL; |
2217 | if (flock.l_pid != 0) | 2228 | if (flock.l_pid != 0) |
2218 | goto out; | 2229 | goto out; |
2219 | 2230 | ||
2220 | cmd = F_SETLK64; | 2231 | cmd = F_SETLK64; |
2221 | file_lock->fl_flags |= FL_FILE_PVT; | 2232 | file_lock->fl_flags |= FL_OFDLCK; |
2222 | file_lock->fl_owner = (fl_owner_t)filp; | 2233 | file_lock->fl_owner = (fl_owner_t)filp; |
2223 | break; | 2234 | break; |
2224 | case F_SETLKPW: | 2235 | case F_OFD_SETLKW: |
2225 | error = -EINVAL; | 2236 | error = -EINVAL; |
2226 | if (flock.l_pid != 0) | 2237 | if (flock.l_pid != 0) |
2227 | goto out; | 2238 | goto out; |
2228 | 2239 | ||
2229 | cmd = F_SETLKW64; | 2240 | cmd = F_SETLKW64; |
2230 | file_lock->fl_flags |= FL_FILE_PVT; | 2241 | file_lock->fl_flags |= FL_OFDLCK; |
2231 | file_lock->fl_owner = (fl_owner_t)filp; | 2242 | file_lock->fl_owner = (fl_owner_t)filp; |
2232 | /* Fallthrough */ | 2243 | /* Fallthrough */ |
2233 | case F_SETLKW64: | 2244 | case F_SETLKW64: |
@@ -2413,8 +2424,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
2413 | if (IS_POSIX(fl)) { | 2424 | if (IS_POSIX(fl)) { |
2414 | if (fl->fl_flags & FL_ACCESS) | 2425 | if (fl->fl_flags & FL_ACCESS) |
2415 | seq_printf(f, "ACCESS"); | 2426 | seq_printf(f, "ACCESS"); |
2416 | else if (IS_FILE_PVT(fl)) | 2427 | else if (IS_OFDLCK(fl)) |
2417 | seq_printf(f, "FLPVT "); | 2428 | seq_printf(f, "OFDLCK"); |
2418 | else | 2429 | else |
2419 | seq_printf(f, "POSIX "); | 2430 | seq_printf(f, "POSIX "); |
2420 | 2431 | ||