diff options
Diffstat (limited to 'fs/locks.c')
| -rw-r--r-- | fs/locks.c | 45 |
1 files changed, 19 insertions, 26 deletions
diff --git a/fs/locks.c b/fs/locks.c index 4d9e71d43e7e..dda83d6cd48b 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -168,18 +168,9 @@ static void locks_release_private(struct file_lock *fl) | |||
| 168 | /* Free a lock which is not in use. */ | 168 | /* Free a lock which is not in use. */ |
| 169 | static void locks_free_lock(struct file_lock *fl) | 169 | static void locks_free_lock(struct file_lock *fl) |
| 170 | { | 170 | { |
| 171 | if (fl == NULL) { | 171 | BUG_ON(waitqueue_active(&fl->fl_wait)); |
| 172 | BUG(); | 172 | BUG_ON(!list_empty(&fl->fl_block)); |
| 173 | return; | 173 | BUG_ON(!list_empty(&fl->fl_link)); |
| 174 | } | ||
| 175 | if (waitqueue_active(&fl->fl_wait)) | ||
| 176 | panic("Attempting to free lock with active wait queue"); | ||
| 177 | |||
| 178 | if (!list_empty(&fl->fl_block)) | ||
| 179 | panic("Attempting to free lock with active block list"); | ||
| 180 | |||
| 181 | if (!list_empty(&fl->fl_link)) | ||
| 182 | panic("Attempting to free lock on active lock list"); | ||
| 183 | 174 | ||
| 184 | locks_release_private(fl); | 175 | locks_release_private(fl); |
| 185 | kmem_cache_free(filelock_cache, fl); | 176 | kmem_cache_free(filelock_cache, fl); |
| @@ -735,8 +726,9 @@ EXPORT_SYMBOL(posix_locks_deadlock); | |||
| 735 | * at the head of the list, but that's secret knowledge known only to | 726 | * at the head of the list, but that's secret knowledge known only to |
| 736 | * flock_lock_file and posix_lock_file. | 727 | * flock_lock_file and posix_lock_file. |
| 737 | */ | 728 | */ |
| 738 | static int flock_lock_file(struct file *filp, struct file_lock *new_fl) | 729 | static int flock_lock_file(struct file *filp, struct file_lock *request) |
| 739 | { | 730 | { |
| 731 | struct file_lock *new_fl = NULL; | ||
| 740 | struct file_lock **before; | 732 | struct file_lock **before; |
| 741 | struct inode * inode = filp->f_dentry->d_inode; | 733 | struct inode * inode = filp->f_dentry->d_inode; |
| 742 | int error = 0; | 734 | int error = 0; |
| @@ -751,17 +743,19 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl) | |||
| 751 | continue; | 743 | continue; |
| 752 | if (filp != fl->fl_file) | 744 | if (filp != fl->fl_file) |
| 753 | continue; | 745 | continue; |
| 754 | if (new_fl->fl_type == fl->fl_type) | 746 | if (request->fl_type == fl->fl_type) |
| 755 | goto out; | 747 | goto out; |
| 756 | found = 1; | 748 | found = 1; |
| 757 | locks_delete_lock(before); | 749 | locks_delete_lock(before); |
| 758 | break; | 750 | break; |
| 759 | } | 751 | } |
| 760 | unlock_kernel(); | ||
| 761 | 752 | ||
| 762 | if (new_fl->fl_type == F_UNLCK) | 753 | if (request->fl_type == F_UNLCK) |
| 763 | return 0; | 754 | goto out; |
| 764 | 755 | ||
| 756 | new_fl = locks_alloc_lock(); | ||
| 757 | if (new_fl == NULL) | ||
| 758 | goto out; | ||
| 765 | /* | 759 | /* |
| 766 | * If a higher-priority process was blocked on the old file lock, | 760 | * If a higher-priority process was blocked on the old file lock, |
| 767 | * give it the opportunity to lock the file. | 761 | * give it the opportunity to lock the file. |
| @@ -769,26 +763,27 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl) | |||
| 769 | if (found) | 763 | if (found) |
| 770 | cond_resched(); | 764 | cond_resched(); |
| 771 | 765 | ||
| 772 | lock_kernel(); | ||
| 773 | for_each_lock(inode, before) { | 766 | for_each_lock(inode, before) { |
| 774 | struct file_lock *fl = *before; | 767 | struct file_lock *fl = *before; |
| 775 | if (IS_POSIX(fl)) | 768 | if (IS_POSIX(fl)) |
| 776 | break; | 769 | break; |
| 777 | if (IS_LEASE(fl)) | 770 | if (IS_LEASE(fl)) |
| 778 | continue; | 771 | continue; |
| 779 | if (!flock_locks_conflict(new_fl, fl)) | 772 | if (!flock_locks_conflict(request, fl)) |
| 780 | continue; | 773 | continue; |
| 781 | error = -EAGAIN; | 774 | error = -EAGAIN; |
| 782 | if (new_fl->fl_flags & FL_SLEEP) { | 775 | if (request->fl_flags & FL_SLEEP) |
| 783 | locks_insert_block(fl, new_fl); | 776 | locks_insert_block(fl, request); |
| 784 | } | ||
| 785 | goto out; | 777 | goto out; |
| 786 | } | 778 | } |
| 779 | locks_copy_lock(new_fl, request); | ||
| 787 | locks_insert_lock(&inode->i_flock, new_fl); | 780 | locks_insert_lock(&inode->i_flock, new_fl); |
| 788 | error = 0; | 781 | new_fl = NULL; |
| 789 | 782 | ||
| 790 | out: | 783 | out: |
| 791 | unlock_kernel(); | 784 | unlock_kernel(); |
| 785 | if (new_fl) | ||
| 786 | locks_free_lock(new_fl); | ||
| 792 | return error; | 787 | return error; |
| 793 | } | 788 | } |
| 794 | 789 | ||
| @@ -1569,9 +1564,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) | |||
| 1569 | error = flock_lock_file_wait(filp, lock); | 1564 | error = flock_lock_file_wait(filp, lock); |
| 1570 | 1565 | ||
| 1571 | out_free: | 1566 | out_free: |
| 1572 | if (list_empty(&lock->fl_link)) { | 1567 | locks_free_lock(lock); |
| 1573 | locks_free_lock(lock); | ||
| 1574 | } | ||
| 1575 | 1568 | ||
| 1576 | out_putf: | 1569 | out_putf: |
| 1577 | fput(filp); | 1570 | fput(filp); |
