diff options
Diffstat (limited to 'fs/locks.c')
| -rw-r--r-- | fs/locks.c | 112 |
1 files changed, 70 insertions, 42 deletions
diff --git a/fs/locks.c b/fs/locks.c index 717fbc404e6b..cb66fb05ad4a 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -247,6 +247,18 @@ void locks_free_lock(struct file_lock *fl) | |||
| 247 | } | 247 | } |
| 248 | EXPORT_SYMBOL(locks_free_lock); | 248 | EXPORT_SYMBOL(locks_free_lock); |
| 249 | 249 | ||
| 250 | static void | ||
| 251 | locks_dispose_list(struct list_head *dispose) | ||
| 252 | { | ||
| 253 | struct file_lock *fl; | ||
| 254 | |||
| 255 | while (!list_empty(dispose)) { | ||
| 256 | fl = list_first_entry(dispose, struct file_lock, fl_block); | ||
| 257 | list_del_init(&fl->fl_block); | ||
| 258 | locks_free_lock(fl); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 250 | void locks_init_lock(struct file_lock *fl) | 262 | void locks_init_lock(struct file_lock *fl) |
| 251 | { | 263 | { |
| 252 | memset(fl, 0, sizeof(struct file_lock)); | 264 | memset(fl, 0, sizeof(struct file_lock)); |
| @@ -285,7 +297,8 @@ EXPORT_SYMBOL(__locks_copy_lock); | |||
| 285 | 297 | ||
| 286 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) | 298 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) |
| 287 | { | 299 | { |
| 288 | locks_release_private(new); | 300 | /* "new" must be a freshly-initialized lock */ |
| 301 | WARN_ON_ONCE(new->fl_ops); | ||
| 289 | 302 | ||
| 290 | __locks_copy_lock(new, fl); | 303 | __locks_copy_lock(new, fl); |
| 291 | new->fl_file = fl->fl_file; | 304 | new->fl_file = fl->fl_file; |
| @@ -325,7 +338,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock, | |||
| 325 | return -ENOMEM; | 338 | return -ENOMEM; |
| 326 | 339 | ||
| 327 | fl->fl_file = filp; | 340 | fl->fl_file = filp; |
| 328 | fl->fl_owner = (fl_owner_t)filp; | 341 | fl->fl_owner = filp; |
| 329 | fl->fl_pid = current->tgid; | 342 | fl->fl_pid = current->tgid; |
| 330 | fl->fl_flags = FL_FLOCK; | 343 | fl->fl_flags = FL_FLOCK; |
| 331 | fl->fl_type = type; | 344 | fl->fl_type = type; |
| @@ -431,7 +444,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl) | |||
| 431 | if (assign_type(fl, type) != 0) | 444 | if (assign_type(fl, type) != 0) |
| 432 | return -EINVAL; | 445 | return -EINVAL; |
| 433 | 446 | ||
| 434 | fl->fl_owner = (fl_owner_t)current->files; | 447 | fl->fl_owner = current->files; |
| 435 | fl->fl_pid = current->tgid; | 448 | fl->fl_pid = current->tgid; |
| 436 | 449 | ||
| 437 | fl->fl_file = filp; | 450 | fl->fl_file = filp; |
| @@ -650,12 +663,16 @@ static void locks_unlink_lock(struct file_lock **thisfl_p) | |||
| 650 | * | 663 | * |
| 651 | * Must be called with i_lock held! | 664 | * Must be called with i_lock held! |
| 652 | */ | 665 | */ |
| 653 | static void locks_delete_lock(struct file_lock **thisfl_p) | 666 | static void locks_delete_lock(struct file_lock **thisfl_p, |
| 667 | struct list_head *dispose) | ||
| 654 | { | 668 | { |
| 655 | struct file_lock *fl = *thisfl_p; | 669 | struct file_lock *fl = *thisfl_p; |
| 656 | 670 | ||
| 657 | locks_unlink_lock(thisfl_p); | 671 | locks_unlink_lock(thisfl_p); |
| 658 | locks_free_lock(fl); | 672 | if (dispose) |
| 673 | list_add(&fl->fl_block, dispose); | ||
| 674 | else | ||
| 675 | locks_free_lock(fl); | ||
| 659 | } | 676 | } |
| 660 | 677 | ||
| 661 | /* Determine if lock sys_fl blocks lock caller_fl. Common functionality | 678 | /* Determine if lock sys_fl blocks lock caller_fl. Common functionality |
| @@ -811,6 +828,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) | |||
| 811 | struct inode * inode = file_inode(filp); | 828 | struct inode * inode = file_inode(filp); |
| 812 | int error = 0; | 829 | int error = 0; |
| 813 | int found = 0; | 830 | int found = 0; |
| 831 | LIST_HEAD(dispose); | ||
| 814 | 832 | ||
| 815 | if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { | 833 | if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { |
| 816 | new_fl = locks_alloc_lock(); | 834 | new_fl = locks_alloc_lock(); |
| @@ -833,7 +851,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) | |||
| 833 | if (request->fl_type == fl->fl_type) | 851 | if (request->fl_type == fl->fl_type) |
| 834 | goto out; | 852 | goto out; |
| 835 | found = 1; | 853 | found = 1; |
| 836 | locks_delete_lock(before); | 854 | locks_delete_lock(before, &dispose); |
| 837 | break; | 855 | break; |
| 838 | } | 856 | } |
| 839 | 857 | ||
| @@ -880,6 +898,7 @@ out: | |||
| 880 | spin_unlock(&inode->i_lock); | 898 | spin_unlock(&inode->i_lock); |
| 881 | if (new_fl) | 899 | if (new_fl) |
| 882 | locks_free_lock(new_fl); | 900 | locks_free_lock(new_fl); |
| 901 | locks_dispose_list(&dispose); | ||
| 883 | return error; | 902 | return error; |
| 884 | } | 903 | } |
| 885 | 904 | ||
| @@ -893,6 +912,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 893 | struct file_lock **before; | 912 | struct file_lock **before; |
| 894 | int error; | 913 | int error; |
| 895 | bool added = false; | 914 | bool added = false; |
| 915 | LIST_HEAD(dispose); | ||
| 896 | 916 | ||
| 897 | /* | 917 | /* |
| 898 | * We may need two file_lock structures for this operation, | 918 | * We may need two file_lock structures for this operation, |
| @@ -988,7 +1008,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 988 | else | 1008 | else |
| 989 | request->fl_end = fl->fl_end; | 1009 | request->fl_end = fl->fl_end; |
| 990 | if (added) { | 1010 | if (added) { |
| 991 | locks_delete_lock(before); | 1011 | locks_delete_lock(before, &dispose); |
| 992 | continue; | 1012 | continue; |
| 993 | } | 1013 | } |
| 994 | request = fl; | 1014 | request = fl; |
| @@ -1018,21 +1038,24 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 1018 | * one (This may happen several times). | 1038 | * one (This may happen several times). |
| 1019 | */ | 1039 | */ |
| 1020 | if (added) { | 1040 | if (added) { |
| 1021 | locks_delete_lock(before); | 1041 | locks_delete_lock(before, &dispose); |
| 1022 | continue; | 1042 | continue; |
| 1023 | } | 1043 | } |
| 1024 | /* Replace the old lock with the new one. | 1044 | /* |
| 1025 | * Wake up anybody waiting for the old one, | 1045 | * Replace the old lock with new_fl, and |
| 1026 | * as the change in lock type might satisfy | 1046 | * remove the old one. It's safe to do the |
| 1027 | * their needs. | 1047 | * insert here since we know that we won't be |
| 1048 | * using new_fl later, and that the lock is | ||
| 1049 | * just replacing an existing lock. | ||
| 1028 | */ | 1050 | */ |
| 1029 | locks_wake_up_blocks(fl); | 1051 | error = -ENOLCK; |
| 1030 | fl->fl_start = request->fl_start; | 1052 | if (!new_fl) |
| 1031 | fl->fl_end = request->fl_end; | 1053 | goto out; |
| 1032 | fl->fl_type = request->fl_type; | 1054 | locks_copy_lock(new_fl, request); |
| 1033 | locks_release_private(fl); | 1055 | request = new_fl; |
| 1034 | locks_copy_private(fl, request); | 1056 | new_fl = NULL; |
| 1035 | request = fl; | 1057 | locks_delete_lock(before, &dispose); |
| 1058 | locks_insert_lock(before, request); | ||
| 1036 | added = true; | 1059 | added = true; |
| 1037 | } | 1060 | } |
| 1038 | } | 1061 | } |
| @@ -1093,6 +1116,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 1093 | locks_free_lock(new_fl); | 1116 | locks_free_lock(new_fl); |
| 1094 | if (new_fl2) | 1117 | if (new_fl2) |
| 1095 | locks_free_lock(new_fl2); | 1118 | locks_free_lock(new_fl2); |
| 1119 | locks_dispose_list(&dispose); | ||
| 1096 | return error; | 1120 | return error; |
| 1097 | } | 1121 | } |
| 1098 | 1122 | ||
| @@ -1155,7 +1179,6 @@ EXPORT_SYMBOL(posix_lock_file_wait); | |||
| 1155 | int locks_mandatory_locked(struct file *file) | 1179 | int locks_mandatory_locked(struct file *file) |
| 1156 | { | 1180 | { |
| 1157 | struct inode *inode = file_inode(file); | 1181 | struct inode *inode = file_inode(file); |
| 1158 | fl_owner_t owner = current->files; | ||
| 1159 | struct file_lock *fl; | 1182 | struct file_lock *fl; |
| 1160 | 1183 | ||
| 1161 | /* | 1184 | /* |
| @@ -1165,7 +1188,8 @@ int locks_mandatory_locked(struct file *file) | |||
| 1165 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 1188 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
| 1166 | if (!IS_POSIX(fl)) | 1189 | if (!IS_POSIX(fl)) |
| 1167 | continue; | 1190 | continue; |
| 1168 | if (fl->fl_owner != owner && fl->fl_owner != (fl_owner_t)file) | 1191 | if (fl->fl_owner != current->files && |
| 1192 | fl->fl_owner != file) | ||
| 1169 | break; | 1193 | break; |
| 1170 | } | 1194 | } |
| 1171 | spin_unlock(&inode->i_lock); | 1195 | spin_unlock(&inode->i_lock); |
| @@ -1205,7 +1229,7 @@ int locks_mandatory_area(int read_write, struct inode *inode, | |||
| 1205 | 1229 | ||
| 1206 | for (;;) { | 1230 | for (;;) { |
| 1207 | if (filp) { | 1231 | if (filp) { |
| 1208 | fl.fl_owner = (fl_owner_t)filp; | 1232 | fl.fl_owner = filp; |
| 1209 | fl.fl_flags &= ~FL_SLEEP; | 1233 | fl.fl_flags &= ~FL_SLEEP; |
| 1210 | error = __posix_lock_file(inode, &fl, NULL); | 1234 | error = __posix_lock_file(inode, &fl, NULL); |
| 1211 | if (!error) | 1235 | if (!error) |
| @@ -1268,7 +1292,7 @@ int lease_modify(struct file_lock **before, int arg) | |||
| 1268 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); | 1292 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); |
| 1269 | fl->fl_fasync = NULL; | 1293 | fl->fl_fasync = NULL; |
| 1270 | } | 1294 | } |
| 1271 | locks_delete_lock(before); | 1295 | locks_delete_lock(before, NULL); |
| 1272 | } | 1296 | } |
| 1273 | return 0; | 1297 | return 0; |
| 1274 | } | 1298 | } |
| @@ -1737,13 +1761,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
| 1737 | ret = fl; | 1761 | ret = fl; |
| 1738 | spin_lock(&inode->i_lock); | 1762 | spin_lock(&inode->i_lock); |
| 1739 | error = __vfs_setlease(filp, arg, &ret); | 1763 | error = __vfs_setlease(filp, arg, &ret); |
| 1740 | if (error) { | 1764 | if (error) |
| 1741 | spin_unlock(&inode->i_lock); | 1765 | goto out_unlock; |
| 1742 | locks_free_lock(fl); | 1766 | if (ret == fl) |
| 1743 | goto out_free_fasync; | 1767 | fl = NULL; |
| 1744 | } | ||
| 1745 | if (ret != fl) | ||
| 1746 | locks_free_lock(fl); | ||
| 1747 | 1768 | ||
| 1748 | /* | 1769 | /* |
| 1749 | * fasync_insert_entry() returns the old entry if any. | 1770 | * fasync_insert_entry() returns the old entry if any. |
| @@ -1755,9 +1776,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
| 1755 | new = NULL; | 1776 | new = NULL; |
| 1756 | 1777 | ||
| 1757 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); | 1778 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); |
| 1779 | out_unlock: | ||
| 1758 | spin_unlock(&inode->i_lock); | 1780 | spin_unlock(&inode->i_lock); |
| 1759 | 1781 | if (fl) | |
| 1760 | out_free_fasync: | 1782 | locks_free_lock(fl); |
| 1761 | if (new) | 1783 | if (new) |
| 1762 | fasync_free(new); | 1784 | fasync_free(new); |
| 1763 | return error; | 1785 | return error; |
| @@ -1948,7 +1970,7 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) | |||
| 1948 | 1970 | ||
| 1949 | cmd = F_GETLK; | 1971 | cmd = F_GETLK; |
| 1950 | file_lock.fl_flags |= FL_OFDLCK; | 1972 | file_lock.fl_flags |= FL_OFDLCK; |
| 1951 | file_lock.fl_owner = (fl_owner_t)filp; | 1973 | file_lock.fl_owner = filp; |
| 1952 | } | 1974 | } |
| 1953 | 1975 | ||
| 1954 | error = vfs_test_lock(filp, &file_lock); | 1976 | error = vfs_test_lock(filp, &file_lock); |
| @@ -2103,7 +2125,7 @@ again: | |||
| 2103 | 2125 | ||
| 2104 | cmd = F_SETLK; | 2126 | cmd = F_SETLK; |
| 2105 | file_lock->fl_flags |= FL_OFDLCK; | 2127 | file_lock->fl_flags |= FL_OFDLCK; |
| 2106 | file_lock->fl_owner = (fl_owner_t)filp; | 2128 | file_lock->fl_owner = filp; |
| 2107 | break; | 2129 | break; |
| 2108 | case F_OFD_SETLKW: | 2130 | case F_OFD_SETLKW: |
| 2109 | error = -EINVAL; | 2131 | error = -EINVAL; |
| @@ -2112,7 +2134,7 @@ again: | |||
| 2112 | 2134 | ||
| 2113 | cmd = F_SETLKW; | 2135 | cmd = F_SETLKW; |
| 2114 | file_lock->fl_flags |= FL_OFDLCK; | 2136 | file_lock->fl_flags |= FL_OFDLCK; |
| 2115 | file_lock->fl_owner = (fl_owner_t)filp; | 2137 | file_lock->fl_owner = filp; |
| 2116 | /* Fallthrough */ | 2138 | /* Fallthrough */ |
| 2117 | case F_SETLKW: | 2139 | case F_SETLKW: |
| 2118 | file_lock->fl_flags |= FL_SLEEP; | 2140 | file_lock->fl_flags |= FL_SLEEP; |
| @@ -2170,7 +2192,7 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) | |||
| 2170 | 2192 | ||
| 2171 | cmd = F_GETLK64; | 2193 | cmd = F_GETLK64; |
| 2172 | file_lock.fl_flags |= FL_OFDLCK; | 2194 | file_lock.fl_flags |= FL_OFDLCK; |
| 2173 | file_lock.fl_owner = (fl_owner_t)filp; | 2195 | file_lock.fl_owner = filp; |
| 2174 | } | 2196 | } |
| 2175 | 2197 | ||
| 2176 | error = vfs_test_lock(filp, &file_lock); | 2198 | error = vfs_test_lock(filp, &file_lock); |
| @@ -2242,7 +2264,7 @@ again: | |||
| 2242 | 2264 | ||
| 2243 | cmd = F_SETLK64; | 2265 | cmd = F_SETLK64; |
| 2244 | file_lock->fl_flags |= FL_OFDLCK; | 2266 | file_lock->fl_flags |= FL_OFDLCK; |
| 2245 | file_lock->fl_owner = (fl_owner_t)filp; | 2267 | file_lock->fl_owner = filp; |
| 2246 | break; | 2268 | break; |
| 2247 | case F_OFD_SETLKW: | 2269 | case F_OFD_SETLKW: |
| 2248 | error = -EINVAL; | 2270 | error = -EINVAL; |
| @@ -2251,7 +2273,7 @@ again: | |||
| 2251 | 2273 | ||
| 2252 | cmd = F_SETLKW64; | 2274 | cmd = F_SETLKW64; |
| 2253 | file_lock->fl_flags |= FL_OFDLCK; | 2275 | file_lock->fl_flags |= FL_OFDLCK; |
| 2254 | file_lock->fl_owner = (fl_owner_t)filp; | 2276 | file_lock->fl_owner = filp; |
| 2255 | /* Fallthrough */ | 2277 | /* Fallthrough */ |
| 2256 | case F_SETLKW64: | 2278 | case F_SETLKW64: |
| 2257 | file_lock->fl_flags |= FL_SLEEP; | 2279 | file_lock->fl_flags |= FL_SLEEP; |
| @@ -2320,15 +2342,16 @@ void locks_remove_file(struct file *filp) | |||
| 2320 | struct inode * inode = file_inode(filp); | 2342 | struct inode * inode = file_inode(filp); |
| 2321 | struct file_lock *fl; | 2343 | struct file_lock *fl; |
| 2322 | struct file_lock **before; | 2344 | struct file_lock **before; |
| 2345 | LIST_HEAD(dispose); | ||
| 2323 | 2346 | ||
| 2324 | if (!inode->i_flock) | 2347 | if (!inode->i_flock) |
| 2325 | return; | 2348 | return; |
| 2326 | 2349 | ||
| 2327 | locks_remove_posix(filp, (fl_owner_t)filp); | 2350 | locks_remove_posix(filp, filp); |
| 2328 | 2351 | ||
| 2329 | if (filp->f_op->flock) { | 2352 | if (filp->f_op->flock) { |
| 2330 | struct file_lock fl = { | 2353 | struct file_lock fl = { |
| 2331 | .fl_owner = (fl_owner_t)filp, | 2354 | .fl_owner = filp, |
| 2332 | .fl_pid = current->tgid, | 2355 | .fl_pid = current->tgid, |
| 2333 | .fl_file = filp, | 2356 | .fl_file = filp, |
| 2334 | .fl_flags = FL_FLOCK, | 2357 | .fl_flags = FL_FLOCK, |
| @@ -2365,12 +2388,13 @@ void locks_remove_file(struct file *filp) | |||
| 2365 | fl->fl_type, fl->fl_flags, | 2388 | fl->fl_type, fl->fl_flags, |
| 2366 | fl->fl_start, fl->fl_end); | 2389 | fl->fl_start, fl->fl_end); |
| 2367 | 2390 | ||
| 2368 | locks_delete_lock(before); | 2391 | locks_delete_lock(before, &dispose); |
| 2369 | continue; | 2392 | continue; |
| 2370 | } | 2393 | } |
| 2371 | before = &fl->fl_next; | 2394 | before = &fl->fl_next; |
| 2372 | } | 2395 | } |
| 2373 | spin_unlock(&inode->i_lock); | 2396 | spin_unlock(&inode->i_lock); |
| 2397 | locks_dispose_list(&dispose); | ||
| 2374 | } | 2398 | } |
| 2375 | 2399 | ||
| 2376 | /** | 2400 | /** |
| @@ -2452,7 +2476,11 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
| 2452 | seq_puts(f, "FLOCK ADVISORY "); | 2476 | seq_puts(f, "FLOCK ADVISORY "); |
| 2453 | } | 2477 | } |
| 2454 | } else if (IS_LEASE(fl)) { | 2478 | } else if (IS_LEASE(fl)) { |
| 2455 | seq_puts(f, "LEASE "); | 2479 | if (fl->fl_flags & FL_DELEG) |
| 2480 | seq_puts(f, "DELEG "); | ||
| 2481 | else | ||
| 2482 | seq_puts(f, "LEASE "); | ||
| 2483 | |||
| 2456 | if (lease_breaking(fl)) | 2484 | if (lease_breaking(fl)) |
| 2457 | seq_puts(f, "BREAKING "); | 2485 | seq_puts(f, "BREAKING "); |
| 2458 | else if (fl->fl_file) | 2486 | else if (fl->fl_file) |
