aboutsummaryrefslogtreecommitdiff
path: root/fs/locks.c
diff options
context:
space:
mode:
authorAlex Shi <alex.shi@linaro.org>2016-03-14 15:37:56 +0800
committerAlex Shi <alex.shi@linaro.org>2016-03-14 15:37:56 +0800
commit0f7fc48d4378ac087ef7e69a6e675b0d9280999e (patch)
treef0c005b00166eca0ce2648487cde89866447645f /fs/locks.c
parent4fc0eccae84a29106ed944588ba641e9039ccfbc (diff)
parentfbb0b56de45bc81681eeeaec29e6c1e3ff12a200 (diff)
Merge branch 'linux-linaro-lsk-v3.10' into linux-linaro-lsk-v3.10-androidlsk-v3.10-16.03-androidlinux-linaro-lsk-v3.10-android
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 0274c953b07d..f7b1de7e6735 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1852,7 +1852,6 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
goto out;
}
-again:
error = flock_to_posix_lock(filp, file_lock, &flock);
if (error)
goto out;
@@ -1883,19 +1882,22 @@ again:
* Attempt to detect a close/fcntl race and recover by
* releasing the lock that was just acquired.
*/
- /*
- * we need that spin_lock here - it prevents reordering between
- * update of inode->i_flock and check for it done in close().
- * rcu_read_lock() wouldn't do.
- */
- spin_lock(&current->files->file_lock);
- f = fcheck(fd);
- spin_unlock(&current->files->file_lock);
- if (!error && f != filp && flock.l_type != F_UNLCK) {
- flock.l_type = F_UNLCK;
- goto again;
+ if (!error && file_lock->fl_type != F_UNLCK) {
+ /*
+ * We need that spin_lock here - it prevents reordering between
+ * update of inode->i_flock and check for it done in
+ * close(). rcu_read_lock() wouldn't do.
+ */
+ spin_lock(&current->files->file_lock);
+ f = fcheck(fd);
+ spin_unlock(&current->files->file_lock);
+ if (f != filp) {
+ file_lock->fl_type = F_UNLCK;
+ error = do_lock_file_wait(filp, cmd, file_lock);
+ WARN_ON_ONCE(error);
+ error = -EBADF;
+ }
}
-
out:
locks_free_lock(file_lock);
return error;
@@ -1970,7 +1972,6 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
goto out;
}
-again:
error = flock64_to_posix_lock(filp, file_lock, &flock);
if (error)
goto out;
@@ -2001,14 +2002,22 @@ again:
* Attempt to detect a close/fcntl race and recover by
* releasing the lock that was just acquired.
*/
- spin_lock(&current->files->file_lock);
- f = fcheck(fd);
- spin_unlock(&current->files->file_lock);
- if (!error && f != filp && flock.l_type != F_UNLCK) {
- flock.l_type = F_UNLCK;
- goto again;
+ if (!error && file_lock->fl_type != F_UNLCK) {
+ /*
+ * We need that spin_lock here - it prevents reordering between
+ * update of inode->i_flock and check for it done in
+ * close(). rcu_read_lock() wouldn't do.
+ */
+ spin_lock(&current->files->file_lock);
+ f = fcheck(fd);
+ spin_unlock(&current->files->file_lock);
+ if (f != filp) {
+ file_lock->fl_type = F_UNLCK;
+ error = do_lock_file_wait(filp, cmd, file_lock);
+ WARN_ON_ONCE(error);
+ error = -EBADF;
+ }
}
-
out:
locks_free_lock(file_lock);
return error;