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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'locks-v3.17-2' of git://git.samba.org/jlayton/linux

Pull file locking bugfixes from Jeff Layton:
"Most of these patches are to fix a long-standing regression that crept
in when the BKL was removed from the file-locking code. The code was
converted to use a conventional spinlock, but some fl_release_private
ops can block and you can end up sleeping inside the lock.

There's also a patch to make /proc/locks show delegations as 'DELEG'"

* tag 'locks-v3.17-2' of git://git.samba.org/jlayton/linux:
locks: update Locking documentation to clarify fl_release_private behavior
locks: move locks_free_lock calls in do_fcntl_add_lease outside spinlock
locks: defer freeing locks in locks_delete_lock until after i_lock has been dropped
locks: don't reuse file_lock in __posix_lock_file
locks: don't call locks_release_private from locks_copy_lock
locks: show delegations as "DELEG" in /proc/locks

+62 -30
+5 -1
Documentation/filesystems/Locking
··· 349 349 locking rules: 350 350 inode->i_lock may block 351 351 fl_copy_lock: yes no 352 - fl_release_private: maybe no 352 + fl_release_private: maybe maybe[1] 353 + 354 + [1]: ->fl_release_private for flock or POSIX locks is currently allowed 355 + to block. Leases however can still be freed while the i_lock is held and 356 + so fl_release_private called on a lease should not block. 353 357 354 358 ----------------------- lock_manager_operations --------------------------- 355 359 prototypes:
+57 -29
fs/locks.c
··· 247 247 } 248 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 262 void locks_init_lock(struct file_lock *fl) 251 263 { 252 264 memset(fl, 0, sizeof(struct file_lock)); ··· 297 285 298 286 void locks_copy_lock(struct file_lock *new, struct file_lock *fl) 299 287 { 300 - locks_release_private(new); 288 + /* "new" must be a freshly-initialized lock */ 289 + WARN_ON_ONCE(new->fl_ops); 301 290 302 291 __locks_copy_lock(new, fl); 303 292 new->fl_file = fl->fl_file; ··· 663 650 * 664 651 * Must be called with i_lock held! 665 652 */ 666 - static void locks_delete_lock(struct file_lock **thisfl_p) 653 + static void locks_delete_lock(struct file_lock **thisfl_p, 654 + struct list_head *dispose) 667 655 { 668 656 struct file_lock *fl = *thisfl_p; 669 657 670 658 locks_unlink_lock(thisfl_p); 671 - locks_free_lock(fl); 659 + if (dispose) 660 + list_add(&fl->fl_block, dispose); 661 + else 662 + locks_free_lock(fl); 672 663 } 673 664 674 665 /* Determine if lock sys_fl blocks lock caller_fl. Common functionality ··· 828 811 struct inode * inode = file_inode(filp); 829 812 int error = 0; 830 813 int found = 0; 814 + LIST_HEAD(dispose); 831 815 832 816 if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { 833 817 new_fl = locks_alloc_lock(); ··· 851 833 if (request->fl_type == fl->fl_type) 852 834 goto out; 853 835 found = 1; 854 - locks_delete_lock(before); 836 + locks_delete_lock(before, &dispose); 855 837 break; 856 838 } 857 839 ··· 898 880 spin_unlock(&inode->i_lock); 899 881 if (new_fl) 900 882 locks_free_lock(new_fl); 883 + locks_dispose_list(&dispose); 901 884 return error; 902 885 } 903 886 ··· 912 893 struct file_lock **before; 913 894 int error; 914 895 bool added = false; 896 + LIST_HEAD(dispose); 915 897 916 898 /* 917 899 * We may need two file_lock structures for this operation, ··· 1008 988 else 1009 989 request->fl_end = fl->fl_end; 1010 990 if (added) { 1011 - locks_delete_lock(before); 991 + locks_delete_lock(before, &dispose); 1012 992 continue; 1013 993 } 1014 994 request = fl; ··· 1038 1018 * one (This may happen several times). 1039 1019 */ 1040 1020 if (added) { 1041 - locks_delete_lock(before); 1021 + locks_delete_lock(before, &dispose); 1042 1022 continue; 1043 1023 } 1044 - /* Replace the old lock with the new one. 1045 - * Wake up anybody waiting for the old one, 1046 - * as the change in lock type might satisfy 1047 - * their needs. 1024 + /* 1025 + * Replace the old lock with new_fl, and 1026 + * remove the old one. It's safe to do the 1027 + * insert here since we know that we won't be 1028 + * using new_fl later, and that the lock is 1029 + * just replacing an existing lock. 1048 1030 */ 1049 - locks_wake_up_blocks(fl); 1050 - fl->fl_start = request->fl_start; 1051 - fl->fl_end = request->fl_end; 1052 - fl->fl_type = request->fl_type; 1053 - locks_release_private(fl); 1054 - locks_copy_private(fl, request); 1055 - request = fl; 1031 + error = -ENOLCK; 1032 + if (!new_fl) 1033 + goto out; 1034 + locks_copy_lock(new_fl, request); 1035 + request = new_fl; 1036 + new_fl = NULL; 1037 + locks_delete_lock(before, &dispose); 1038 + locks_insert_lock(before, request); 1056 1039 added = true; 1057 1040 } 1058 1041 } ··· 1116 1093 locks_free_lock(new_fl); 1117 1094 if (new_fl2) 1118 1095 locks_free_lock(new_fl2); 1096 + locks_dispose_list(&dispose); 1119 1097 return error; 1120 1098 } 1121 1099 ··· 1292 1268 printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); 1293 1269 fl->fl_fasync = NULL; 1294 1270 } 1295 - locks_delete_lock(before); 1271 + locks_delete_lock(before, NULL); 1296 1272 } 1297 1273 return 0; 1298 1274 } ··· 1761 1737 ret = fl; 1762 1738 spin_lock(&inode->i_lock); 1763 1739 error = __vfs_setlease(filp, arg, &ret); 1764 - if (error) { 1765 - spin_unlock(&inode->i_lock); 1766 - locks_free_lock(fl); 1767 - goto out_free_fasync; 1768 - } 1769 - if (ret != fl) 1770 - locks_free_lock(fl); 1740 + if (error) 1741 + goto out_unlock; 1742 + if (ret == fl) 1743 + fl = NULL; 1771 1744 1772 1745 /* 1773 1746 * fasync_insert_entry() returns the old entry if any. ··· 1776 1755 new = NULL; 1777 1756 1778 1757 error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); 1758 + out_unlock: 1779 1759 spin_unlock(&inode->i_lock); 1780 - 1781 - out_free_fasync: 1760 + if (fl) 1761 + locks_free_lock(fl); 1782 1762 if (new) 1783 1763 fasync_free(new); 1784 1764 return error; ··· 2342 2320 struct inode * inode = file_inode(filp); 2343 2321 struct file_lock *fl; 2344 2322 struct file_lock **before; 2323 + LIST_HEAD(dispose); 2345 2324 2346 2325 if (!inode->i_flock) 2347 2326 return; ··· 2388 2365 fl->fl_type, fl->fl_flags, 2389 2366 fl->fl_start, fl->fl_end); 2390 2367 2391 - locks_delete_lock(before); 2368 + locks_delete_lock(before, &dispose); 2392 2369 continue; 2393 2370 } 2394 2371 before = &fl->fl_next; 2395 2372 } 2396 2373 spin_unlock(&inode->i_lock); 2374 + locks_dispose_list(&dispose); 2397 2375 } 2398 2376 2399 2377 /** ··· 2476 2452 seq_puts(f, "FLOCK ADVISORY "); 2477 2453 } 2478 2454 } else if (IS_LEASE(fl)) { 2479 - seq_puts(f, "LEASE "); 2455 + if (fl->fl_flags & FL_DELEG) 2456 + seq_puts(f, "DELEG "); 2457 + else 2458 + seq_puts(f, "LEASE "); 2459 + 2480 2460 if (lease_breaking(fl)) 2481 2461 seq_puts(f, "BREAKING "); 2482 2462 else if (fl->fl_file)