aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-16 10:58:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-16 10:58:47 -0400
commit53b95d6341c142a02538e41bdf1405ef8888bf8b (patch)
treef87d6f57029b6c101c9909cd143de34196c63b1f /fs
parentda06df548e2b82848bcc32342234d0f04340a41c (diff)
parent2ece173e4715031c031de9114491eee80a69cf68 (diff)
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
Diffstat (limited to 'fs')
-rw-r--r--fs/locks.c86
1 files changed, 57 insertions, 29 deletions
diff --git a/fs/locks.c b/fs/locks.c
index a6f54802d277..cb66fb05ad4a 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -247,6 +247,18 @@ void locks_free_lock(struct file_lock *fl)
247} 247}
248EXPORT_SYMBOL(locks_free_lock); 248EXPORT_SYMBOL(locks_free_lock);
249 249
250static void
251locks_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
250void locks_init_lock(struct file_lock *fl) 262void 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
286void locks_copy_lock(struct file_lock *new, struct file_lock *fl) 298void 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;
@@ -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 */
653static void locks_delete_lock(struct file_lock **thisfl_p) 666static 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
@@ -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);
1779out_unlock:
1758 spin_unlock(&inode->i_lock); 1780 spin_unlock(&inode->i_lock);
1759 1781 if (fl)
1760out_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;
@@ -2320,6 +2342,7 @@ 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;
@@ -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)