wext: fix message delay/ordering
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / locks.c
index cb424a4fed71a42d237b72d16de8318bbbeb0fbd..f7b1de7e67358b8ae5006be68a4679d70e67aa8c 100644 (file)
@@ -1243,11 +1243,10 @@ int __break_lease(struct inode *inode, unsigned int mode)
 
 restart:
        break_time = flock->fl_break_time;
-       if (break_time != 0) {
+       if (break_time != 0)
                break_time -= jiffies;
-               if (break_time == 0)
-                       break_time++;
-       }
+       if (break_time == 0)
+               break_time++;
        locks_insert_block(flock, new_fl);
        unlock_flocks();
        error = wait_event_interruptible_timeout(new_fl->fl_wait,
@@ -1853,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;
@@ -1884,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;
@@ -1971,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;
@@ -2002,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;