diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 164 |
1 files changed, 104 insertions, 60 deletions
diff --git a/fs/locks.c b/fs/locks.c index 89d898bce166..ce302d43822b 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -153,27 +153,37 @@ int lease_break_time = 45; | |||
153 | #define for_each_lock(inode, lockp) \ | 153 | #define for_each_lock(inode, lockp) \ |
154 | for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next) | 154 | for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next) |
155 | 155 | ||
156 | /* The global file_lock_list is only used for displaying /proc/locks. */ | 156 | /* |
157 | * The global file_lock_list is only used for displaying /proc/locks. Protected | ||
158 | * by the file_lock_lock. | ||
159 | */ | ||
157 | static LIST_HEAD(file_lock_list); | 160 | static LIST_HEAD(file_lock_list); |
158 | 161 | ||
159 | /* The blocked_list is used to find POSIX lock loops for deadlock detection. */ | 162 | /* |
163 | * The blocked_list is used to find POSIX lock loops for deadlock detection. | ||
164 | * Protected by file_lock_lock. | ||
165 | */ | ||
160 | static LIST_HEAD(blocked_list); | 166 | static LIST_HEAD(blocked_list); |
161 | 167 | ||
162 | /* Protects the two list heads above, plus the inode->i_flock list */ | 168 | /* |
169 | * This lock protects the blocked_list, and the file_lock_list. Generally, if | ||
170 | * you're accessing one of those lists, you want to be holding this lock. | ||
171 | * | ||
172 | * In addition, it also protects the fl->fl_block list, and the fl->fl_next | ||
173 | * pointer for file_lock structures that are acting as lock requests (in | ||
174 | * contrast to those that are acting as records of acquired locks). | ||
175 | * | ||
176 | * Note that when we acquire this lock in order to change the above fields, | ||
177 | * we often hold the i_lock as well. In certain cases, when reading the fields | ||
178 | * protected by this lock, we can skip acquiring it iff we already hold the | ||
179 | * i_lock. | ||
180 | * | ||
181 | * In particular, adding an entry to the fl_block list requires that you hold | ||
182 | * both the i_lock and the blocked_lock_lock (acquired in that order). Deleting | ||
183 | * an entry from the list however only requires the file_lock_lock. | ||
184 | */ | ||
163 | static DEFINE_SPINLOCK(file_lock_lock); | 185 | static DEFINE_SPINLOCK(file_lock_lock); |
164 | 186 | ||
165 | void lock_flocks(void) | ||
166 | { | ||
167 | spin_lock(&file_lock_lock); | ||
168 | } | ||
169 | EXPORT_SYMBOL_GPL(lock_flocks); | ||
170 | |||
171 | void unlock_flocks(void) | ||
172 | { | ||
173 | spin_unlock(&file_lock_lock); | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(unlock_flocks); | ||
176 | |||
177 | static struct kmem_cache *filelock_cache __read_mostly; | 187 | static struct kmem_cache *filelock_cache __read_mostly; |
178 | 188 | ||
179 | static void locks_init_lock_heads(struct file_lock *fl) | 189 | static void locks_init_lock_heads(struct file_lock *fl) |
@@ -489,13 +499,17 @@ static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2) | |||
489 | static inline void | 499 | static inline void |
490 | locks_insert_global_locks(struct file_lock *fl) | 500 | locks_insert_global_locks(struct file_lock *fl) |
491 | { | 501 | { |
502 | spin_lock(&file_lock_lock); | ||
492 | list_add_tail(&fl->fl_link, &file_lock_list); | 503 | list_add_tail(&fl->fl_link, &file_lock_list); |
504 | spin_unlock(&file_lock_lock); | ||
493 | } | 505 | } |
494 | 506 | ||
495 | static inline void | 507 | static inline void |
496 | locks_delete_global_locks(struct file_lock *fl) | 508 | locks_delete_global_locks(struct file_lock *fl) |
497 | { | 509 | { |
510 | spin_lock(&file_lock_lock); | ||
498 | list_del_init(&fl->fl_link); | 511 | list_del_init(&fl->fl_link); |
512 | spin_unlock(&file_lock_lock); | ||
499 | } | 513 | } |
500 | 514 | ||
501 | static inline void | 515 | static inline void |
@@ -512,6 +526,8 @@ locks_delete_global_blocked(struct file_lock *waiter) | |||
512 | 526 | ||
513 | /* Remove waiter from blocker's block list. | 527 | /* Remove waiter from blocker's block list. |
514 | * When blocker ends up pointing to itself then the list is empty. | 528 | * When blocker ends up pointing to itself then the list is empty. |
529 | * | ||
530 | * Must be called with file_lock_lock held. | ||
515 | */ | 531 | */ |
516 | static void __locks_delete_block(struct file_lock *waiter) | 532 | static void __locks_delete_block(struct file_lock *waiter) |
517 | { | 533 | { |
@@ -520,37 +536,47 @@ static void __locks_delete_block(struct file_lock *waiter) | |||
520 | waiter->fl_next = NULL; | 536 | waiter->fl_next = NULL; |
521 | } | 537 | } |
522 | 538 | ||
523 | /* | ||
524 | */ | ||
525 | static void locks_delete_block(struct file_lock *waiter) | 539 | static void locks_delete_block(struct file_lock *waiter) |
526 | { | 540 | { |
527 | lock_flocks(); | 541 | spin_lock(&file_lock_lock); |
528 | __locks_delete_block(waiter); | 542 | __locks_delete_block(waiter); |
529 | unlock_flocks(); | 543 | spin_unlock(&file_lock_lock); |
530 | } | 544 | } |
531 | 545 | ||
532 | /* Insert waiter into blocker's block list. | 546 | /* Insert waiter into blocker's block list. |
533 | * We use a circular list so that processes can be easily woken up in | 547 | * We use a circular list so that processes can be easily woken up in |
534 | * the order they blocked. The documentation doesn't require this but | 548 | * the order they blocked. The documentation doesn't require this but |
535 | * it seems like the reasonable thing to do. | 549 | * it seems like the reasonable thing to do. |
550 | * | ||
551 | * Must be called with file_lock_lock held! | ||
536 | */ | 552 | */ |
537 | static void locks_insert_block(struct file_lock *blocker, | 553 | static void __locks_insert_block(struct file_lock *blocker, |
538 | struct file_lock *waiter) | 554 | struct file_lock *waiter) |
539 | { | 555 | { |
540 | BUG_ON(!list_empty(&waiter->fl_block)); | 556 | BUG_ON(!list_empty(&waiter->fl_block)); |
541 | waiter->fl_next = blocker; | 557 | waiter->fl_next = blocker; |
542 | list_add_tail(&waiter->fl_block, &blocker->fl_block); | 558 | list_add_tail(&waiter->fl_block, &blocker->fl_block); |
543 | if (IS_POSIX(blocker)) | 559 | if (IS_POSIX(blocker)) |
544 | locks_insert_global_blocked(request); | 560 | locks_insert_global_blocked(waiter); |
561 | } | ||
562 | |||
563 | /* Must be called with i_lock held. */ | ||
564 | static void locks_insert_block(struct file_lock *blocker, | ||
565 | struct file_lock *waiter) | ||
566 | { | ||
567 | spin_lock(&file_lock_lock); | ||
568 | __locks_insert_block(blocker, waiter); | ||
569 | spin_unlock(&file_lock_lock); | ||
545 | } | 570 | } |
546 | 571 | ||
547 | /* | 572 | /* |
548 | * Wake up processes blocked waiting for blocker. | 573 | * Wake up processes blocked waiting for blocker. |
549 | * | 574 | * |
550 | * Must be called with the file_lock_lock held! | 575 | * Must be called with the inode->i_lock held! |
551 | */ | 576 | */ |
552 | static void locks_wake_up_blocks(struct file_lock *blocker) | 577 | static void locks_wake_up_blocks(struct file_lock *blocker) |
553 | { | 578 | { |
579 | spin_lock(&file_lock_lock); | ||
554 | while (!list_empty(&blocker->fl_block)) { | 580 | while (!list_empty(&blocker->fl_block)) { |
555 | struct file_lock *waiter; | 581 | struct file_lock *waiter; |
556 | 582 | ||
@@ -562,10 +588,13 @@ static void locks_wake_up_blocks(struct file_lock *blocker) | |||
562 | else | 588 | else |
563 | wake_up(&waiter->fl_wait); | 589 | wake_up(&waiter->fl_wait); |
564 | } | 590 | } |
591 | spin_unlock(&file_lock_lock); | ||
565 | } | 592 | } |
566 | 593 | ||
567 | /* Insert file lock fl into an inode's lock list at the position indicated | 594 | /* Insert file lock fl into an inode's lock list at the position indicated |
568 | * by pos. At the same time add the lock to the global file lock list. | 595 | * by pos. At the same time add the lock to the global file lock list. |
596 | * | ||
597 | * Must be called with the i_lock held! | ||
569 | */ | 598 | */ |
570 | static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) | 599 | static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) |
571 | { | 600 | { |
@@ -583,6 +612,8 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) | |||
583 | * Wake up processes that are blocked waiting for this lock, | 612 | * Wake up processes that are blocked waiting for this lock, |
584 | * notify the FS that the lock has been cleared and | 613 | * notify the FS that the lock has been cleared and |
585 | * finally free the lock. | 614 | * finally free the lock. |
615 | * | ||
616 | * Must be called with the i_lock held! | ||
586 | */ | 617 | */ |
587 | static void locks_delete_lock(struct file_lock **thisfl_p) | 618 | static void locks_delete_lock(struct file_lock **thisfl_p) |
588 | { | 619 | { |
@@ -652,8 +683,9 @@ void | |||
652 | posix_test_lock(struct file *filp, struct file_lock *fl) | 683 | posix_test_lock(struct file *filp, struct file_lock *fl) |
653 | { | 684 | { |
654 | struct file_lock *cfl; | 685 | struct file_lock *cfl; |
686 | struct inode *inode = file_inode(filp); | ||
655 | 687 | ||
656 | lock_flocks(); | 688 | spin_lock(&inode->i_lock); |
657 | for (cfl = file_inode(filp)->i_flock; cfl; cfl = cfl->fl_next) { | 689 | for (cfl = file_inode(filp)->i_flock; cfl; cfl = cfl->fl_next) { |
658 | if (!IS_POSIX(cfl)) | 690 | if (!IS_POSIX(cfl)) |
659 | continue; | 691 | continue; |
@@ -666,7 +698,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl) | |||
666 | fl->fl_pid = pid_vnr(cfl->fl_nspid); | 698 | fl->fl_pid = pid_vnr(cfl->fl_nspid); |
667 | } else | 699 | } else |
668 | fl->fl_type = F_UNLCK; | 700 | fl->fl_type = F_UNLCK; |
669 | unlock_flocks(); | 701 | spin_unlock(&inode->i_lock); |
670 | return; | 702 | return; |
671 | } | 703 | } |
672 | EXPORT_SYMBOL(posix_test_lock); | 704 | EXPORT_SYMBOL(posix_test_lock); |
@@ -710,6 +742,7 @@ static struct file_lock *what_owner_is_waiting_for(struct file_lock *block_fl) | |||
710 | return NULL; | 742 | return NULL; |
711 | } | 743 | } |
712 | 744 | ||
745 | /* Must be called with the file_lock_lock held! */ | ||
713 | static int posix_locks_deadlock(struct file_lock *caller_fl, | 746 | static int posix_locks_deadlock(struct file_lock *caller_fl, |
714 | struct file_lock *block_fl) | 747 | struct file_lock *block_fl) |
715 | { | 748 | { |
@@ -745,7 +778,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) | |||
745 | return -ENOMEM; | 778 | return -ENOMEM; |
746 | } | 779 | } |
747 | 780 | ||
748 | lock_flocks(); | 781 | spin_lock(&inode->i_lock); |
749 | if (request->fl_flags & FL_ACCESS) | 782 | if (request->fl_flags & FL_ACCESS) |
750 | goto find_conflict; | 783 | goto find_conflict; |
751 | 784 | ||
@@ -775,9 +808,9 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) | |||
775 | * give it the opportunity to lock the file. | 808 | * give it the opportunity to lock the file. |
776 | */ | 809 | */ |
777 | if (found) { | 810 | if (found) { |
778 | unlock_flocks(); | 811 | spin_unlock(&inode->i_lock); |
779 | cond_resched(); | 812 | cond_resched(); |
780 | lock_flocks(); | 813 | spin_lock(&inode->i_lock); |
781 | } | 814 | } |
782 | 815 | ||
783 | find_conflict: | 816 | find_conflict: |
@@ -804,7 +837,7 @@ find_conflict: | |||
804 | error = 0; | 837 | error = 0; |
805 | 838 | ||
806 | out: | 839 | out: |
807 | unlock_flocks(); | 840 | spin_unlock(&inode->i_lock); |
808 | if (new_fl) | 841 | if (new_fl) |
809 | locks_free_lock(new_fl); | 842 | locks_free_lock(new_fl); |
810 | return error; | 843 | return error; |
@@ -834,7 +867,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
834 | new_fl2 = locks_alloc_lock(); | 867 | new_fl2 = locks_alloc_lock(); |
835 | } | 868 | } |
836 | 869 | ||
837 | lock_flocks(); | 870 | spin_lock(&inode->i_lock); |
838 | /* | 871 | /* |
839 | * New lock request. Walk all POSIX locks and look for conflicts. If | 872 | * New lock request. Walk all POSIX locks and look for conflicts. If |
840 | * there are any, either return error or put the request on the | 873 | * there are any, either return error or put the request on the |
@@ -852,11 +885,17 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
852 | error = -EAGAIN; | 885 | error = -EAGAIN; |
853 | if (!(request->fl_flags & FL_SLEEP)) | 886 | if (!(request->fl_flags & FL_SLEEP)) |
854 | goto out; | 887 | goto out; |
888 | /* | ||
889 | * Deadlock detection and insertion into the blocked | ||
890 | * locks list must be done while holding the same lock! | ||
891 | */ | ||
855 | error = -EDEADLK; | 892 | error = -EDEADLK; |
856 | if (posix_locks_deadlock(request, fl)) | 893 | spin_lock(&file_lock_lock); |
857 | goto out; | 894 | if (likely(!posix_locks_deadlock(request, fl))) { |
858 | error = FILE_LOCK_DEFERRED; | 895 | error = FILE_LOCK_DEFERRED; |
859 | locks_insert_block(fl, request); | 896 | __locks_insert_block(fl, request); |
897 | } | ||
898 | spin_unlock(&file_lock_lock); | ||
860 | goto out; | 899 | goto out; |
861 | } | 900 | } |
862 | } | 901 | } |
@@ -1006,7 +1045,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
1006 | locks_wake_up_blocks(left); | 1045 | locks_wake_up_blocks(left); |
1007 | } | 1046 | } |
1008 | out: | 1047 | out: |
1009 | unlock_flocks(); | 1048 | spin_unlock(&inode->i_lock); |
1010 | /* | 1049 | /* |
1011 | * Free any unused locks. | 1050 | * Free any unused locks. |
1012 | */ | 1051 | */ |
@@ -1081,14 +1120,14 @@ int locks_mandatory_locked(struct inode *inode) | |||
1081 | /* | 1120 | /* |
1082 | * Search the lock list for this inode for any POSIX locks. | 1121 | * Search the lock list for this inode for any POSIX locks. |
1083 | */ | 1122 | */ |
1084 | lock_flocks(); | 1123 | spin_lock(&inode->i_lock); |
1085 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 1124 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
1086 | if (!IS_POSIX(fl)) | 1125 | if (!IS_POSIX(fl)) |
1087 | continue; | 1126 | continue; |
1088 | if (fl->fl_owner != owner) | 1127 | if (fl->fl_owner != owner) |
1089 | break; | 1128 | break; |
1090 | } | 1129 | } |
1091 | unlock_flocks(); | 1130 | spin_unlock(&inode->i_lock); |
1092 | return fl ? -EAGAIN : 0; | 1131 | return fl ? -EAGAIN : 0; |
1093 | } | 1132 | } |
1094 | 1133 | ||
@@ -1231,7 +1270,7 @@ int __break_lease(struct inode *inode, unsigned int mode) | |||
1231 | if (IS_ERR(new_fl)) | 1270 | if (IS_ERR(new_fl)) |
1232 | return PTR_ERR(new_fl); | 1271 | return PTR_ERR(new_fl); |
1233 | 1272 | ||
1234 | lock_flocks(); | 1273 | spin_lock(&inode->i_lock); |
1235 | 1274 | ||
1236 | time_out_leases(inode); | 1275 | time_out_leases(inode); |
1237 | 1276 | ||
@@ -1281,11 +1320,11 @@ restart: | |||
1281 | break_time++; | 1320 | break_time++; |
1282 | } | 1321 | } |
1283 | locks_insert_block(flock, new_fl); | 1322 | locks_insert_block(flock, new_fl); |
1284 | unlock_flocks(); | 1323 | spin_unlock(&inode->i_lock); |
1285 | error = wait_event_interruptible_timeout(new_fl->fl_wait, | 1324 | error = wait_event_interruptible_timeout(new_fl->fl_wait, |
1286 | !new_fl->fl_next, break_time); | 1325 | !new_fl->fl_next, break_time); |
1287 | lock_flocks(); | 1326 | spin_lock(&inode->i_lock); |
1288 | __locks_delete_block(new_fl); | 1327 | locks_delete_block(new_fl); |
1289 | if (error >= 0) { | 1328 | if (error >= 0) { |
1290 | if (error == 0) | 1329 | if (error == 0) |
1291 | time_out_leases(inode); | 1330 | time_out_leases(inode); |
@@ -1302,7 +1341,7 @@ restart: | |||
1302 | } | 1341 | } |
1303 | 1342 | ||
1304 | out: | 1343 | out: |
1305 | unlock_flocks(); | 1344 | spin_unlock(&inode->i_lock); |
1306 | locks_free_lock(new_fl); | 1345 | locks_free_lock(new_fl); |
1307 | return error; | 1346 | return error; |
1308 | } | 1347 | } |
@@ -1355,9 +1394,10 @@ EXPORT_SYMBOL(lease_get_mtime); | |||
1355 | int fcntl_getlease(struct file *filp) | 1394 | int fcntl_getlease(struct file *filp) |
1356 | { | 1395 | { |
1357 | struct file_lock *fl; | 1396 | struct file_lock *fl; |
1397 | struct inode *inode = file_inode(filp); | ||
1358 | int type = F_UNLCK; | 1398 | int type = F_UNLCK; |
1359 | 1399 | ||
1360 | lock_flocks(); | 1400 | spin_lock(&inode->i_lock); |
1361 | time_out_leases(file_inode(filp)); | 1401 | time_out_leases(file_inode(filp)); |
1362 | for (fl = file_inode(filp)->i_flock; fl && IS_LEASE(fl); | 1402 | for (fl = file_inode(filp)->i_flock; fl && IS_LEASE(fl); |
1363 | fl = fl->fl_next) { | 1403 | fl = fl->fl_next) { |
@@ -1366,7 +1406,7 @@ int fcntl_getlease(struct file *filp) | |||
1366 | break; | 1406 | break; |
1367 | } | 1407 | } |
1368 | } | 1408 | } |
1369 | unlock_flocks(); | 1409 | spin_unlock(&inode->i_lock); |
1370 | return type; | 1410 | return type; |
1371 | } | 1411 | } |
1372 | 1412 | ||
@@ -1460,7 +1500,7 @@ static int generic_delete_lease(struct file *filp, struct file_lock **flp) | |||
1460 | * The (input) flp->fl_lmops->lm_break function is required | 1500 | * The (input) flp->fl_lmops->lm_break function is required |
1461 | * by break_lease(). | 1501 | * by break_lease(). |
1462 | * | 1502 | * |
1463 | * Called with file_lock_lock held. | 1503 | * Called with inode->i_lock held. |
1464 | */ | 1504 | */ |
1465 | int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | 1505 | int generic_setlease(struct file *filp, long arg, struct file_lock **flp) |
1466 | { | 1506 | { |
@@ -1529,11 +1569,12 @@ static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease) | |||
1529 | 1569 | ||
1530 | int vfs_setlease(struct file *filp, long arg, struct file_lock **lease) | 1570 | int vfs_setlease(struct file *filp, long arg, struct file_lock **lease) |
1531 | { | 1571 | { |
1572 | struct inode *inode = file_inode(filp); | ||
1532 | int error; | 1573 | int error; |
1533 | 1574 | ||
1534 | lock_flocks(); | 1575 | spin_lock(&inode->i_lock); |
1535 | error = __vfs_setlease(filp, arg, lease); | 1576 | error = __vfs_setlease(filp, arg, lease); |
1536 | unlock_flocks(); | 1577 | spin_unlock(&inode->i_lock); |
1537 | 1578 | ||
1538 | return error; | 1579 | return error; |
1539 | } | 1580 | } |
@@ -1551,6 +1592,7 @@ static int do_fcntl_delete_lease(struct file *filp) | |||
1551 | static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | 1592 | static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) |
1552 | { | 1593 | { |
1553 | struct file_lock *fl, *ret; | 1594 | struct file_lock *fl, *ret; |
1595 | struct inode *inode = file_inode(filp); | ||
1554 | struct fasync_struct *new; | 1596 | struct fasync_struct *new; |
1555 | int error; | 1597 | int error; |
1556 | 1598 | ||
@@ -1564,10 +1606,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
1564 | return -ENOMEM; | 1606 | return -ENOMEM; |
1565 | } | 1607 | } |
1566 | ret = fl; | 1608 | ret = fl; |
1567 | lock_flocks(); | 1609 | spin_lock(&inode->i_lock); |
1568 | error = __vfs_setlease(filp, arg, &ret); | 1610 | error = __vfs_setlease(filp, arg, &ret); |
1569 | if (error) { | 1611 | if (error) { |
1570 | unlock_flocks(); | 1612 | spin_unlock(&inode->i_lock); |
1571 | locks_free_lock(fl); | 1613 | locks_free_lock(fl); |
1572 | goto out_free_fasync; | 1614 | goto out_free_fasync; |
1573 | } | 1615 | } |
@@ -1584,7 +1626,7 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
1584 | new = NULL; | 1626 | new = NULL; |
1585 | 1627 | ||
1586 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); | 1628 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); |
1587 | unlock_flocks(); | 1629 | spin_unlock(&inode->i_lock); |
1588 | 1630 | ||
1589 | out_free_fasync: | 1631 | out_free_fasync: |
1590 | if (new) | 1632 | if (new) |
@@ -2108,7 +2150,7 @@ void locks_remove_flock(struct file *filp) | |||
2108 | fl.fl_ops->fl_release_private(&fl); | 2150 | fl.fl_ops->fl_release_private(&fl); |
2109 | } | 2151 | } |
2110 | 2152 | ||
2111 | lock_flocks(); | 2153 | spin_lock(&inode->i_lock); |
2112 | before = &inode->i_flock; | 2154 | before = &inode->i_flock; |
2113 | 2155 | ||
2114 | while ((fl = *before) != NULL) { | 2156 | while ((fl = *before) != NULL) { |
@@ -2126,7 +2168,7 @@ void locks_remove_flock(struct file *filp) | |||
2126 | } | 2168 | } |
2127 | before = &fl->fl_next; | 2169 | before = &fl->fl_next; |
2128 | } | 2170 | } |
2129 | unlock_flocks(); | 2171 | spin_unlock(&inode->i_lock); |
2130 | } | 2172 | } |
2131 | 2173 | ||
2132 | /** | 2174 | /** |
@@ -2140,12 +2182,12 @@ posix_unblock_lock(struct file_lock *waiter) | |||
2140 | { | 2182 | { |
2141 | int status = 0; | 2183 | int status = 0; |
2142 | 2184 | ||
2143 | lock_flocks(); | 2185 | spin_lock(&file_lock_lock); |
2144 | if (waiter->fl_next) | 2186 | if (waiter->fl_next) |
2145 | __locks_delete_block(waiter); | 2187 | __locks_delete_block(waiter); |
2146 | else | 2188 | else |
2147 | status = -ENOENT; | 2189 | status = -ENOENT; |
2148 | unlock_flocks(); | 2190 | spin_unlock(&file_lock_lock); |
2149 | return status; | 2191 | return status; |
2150 | } | 2192 | } |
2151 | EXPORT_SYMBOL(posix_unblock_lock); | 2193 | EXPORT_SYMBOL(posix_unblock_lock); |
@@ -2259,7 +2301,7 @@ static void *locks_start(struct seq_file *f, loff_t *pos) | |||
2259 | { | 2301 | { |
2260 | loff_t *p = f->private; | 2302 | loff_t *p = f->private; |
2261 | 2303 | ||
2262 | lock_flocks(); | 2304 | spin_lock(&file_lock_lock); |
2263 | *p = (*pos + 1); | 2305 | *p = (*pos + 1); |
2264 | return seq_list_start(&file_lock_list, *pos); | 2306 | return seq_list_start(&file_lock_list, *pos); |
2265 | } | 2307 | } |
@@ -2273,7 +2315,7 @@ static void *locks_next(struct seq_file *f, void *v, loff_t *pos) | |||
2273 | 2315 | ||
2274 | static void locks_stop(struct seq_file *f, void *v) | 2316 | static void locks_stop(struct seq_file *f, void *v) |
2275 | { | 2317 | { |
2276 | unlock_flocks(); | 2318 | spin_unlock(&file_lock_lock); |
2277 | } | 2319 | } |
2278 | 2320 | ||
2279 | static const struct seq_operations locks_seq_operations = { | 2321 | static const struct seq_operations locks_seq_operations = { |
@@ -2320,7 +2362,8 @@ int lock_may_read(struct inode *inode, loff_t start, unsigned long len) | |||
2320 | { | 2362 | { |
2321 | struct file_lock *fl; | 2363 | struct file_lock *fl; |
2322 | int result = 1; | 2364 | int result = 1; |
2323 | lock_flocks(); | 2365 | |
2366 | spin_lock(&inode->i_lock); | ||
2324 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 2367 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
2325 | if (IS_POSIX(fl)) { | 2368 | if (IS_POSIX(fl)) { |
2326 | if (fl->fl_type == F_RDLCK) | 2369 | if (fl->fl_type == F_RDLCK) |
@@ -2337,7 +2380,7 @@ int lock_may_read(struct inode *inode, loff_t start, unsigned long len) | |||
2337 | result = 0; | 2380 | result = 0; |
2338 | break; | 2381 | break; |
2339 | } | 2382 | } |
2340 | unlock_flocks(); | 2383 | spin_unlock(&inode->i_lock); |
2341 | return result; | 2384 | return result; |
2342 | } | 2385 | } |
2343 | 2386 | ||
@@ -2360,7 +2403,8 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) | |||
2360 | { | 2403 | { |
2361 | struct file_lock *fl; | 2404 | struct file_lock *fl; |
2362 | int result = 1; | 2405 | int result = 1; |
2363 | lock_flocks(); | 2406 | |
2407 | spin_lock(&inode->i_lock); | ||
2364 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 2408 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
2365 | if (IS_POSIX(fl)) { | 2409 | if (IS_POSIX(fl)) { |
2366 | if ((fl->fl_end < start) || (fl->fl_start > (start + len))) | 2410 | if ((fl->fl_end < start) || (fl->fl_start > (start + len))) |
@@ -2375,7 +2419,7 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) | |||
2375 | result = 0; | 2419 | result = 0; |
2376 | break; | 2420 | break; |
2377 | } | 2421 | } |
2378 | unlock_flocks(); | 2422 | spin_unlock(&inode->i_lock); |
2379 | return result; | 2423 | return result; |
2380 | } | 2424 | } |
2381 | 2425 | ||