Merge branch 'clockevents/cmt-mtu2-tmu-cleanups' of git://git.linaro.org/people/danie...
[deliverable/linux.git] / fs / locks.c
index 3b54b98236eeeccf2588eadb5a6df82b45d591f4..13fc7a6d380ae6648945c8956cc53901de2d0ccc 100644 (file)
@@ -1155,13 +1155,14 @@ EXPORT_SYMBOL(posix_lock_file_wait);
 
 /**
  * locks_mandatory_locked - Check for an active lock
- * @inode: the file to check
+ * @file: the file to check
  *
  * Searches the inode's list of locks to find any POSIX locks which conflict.
  * This function is called from locks_verify_locked() only.
  */
-int locks_mandatory_locked(struct inode *inode)
+int locks_mandatory_locked(struct file *file)
 {
+       struct inode *inode = file_inode(file);
        fl_owner_t owner = current->files;
        struct file_lock *fl;
 
@@ -1172,7 +1173,7 @@ int locks_mandatory_locked(struct inode *inode)
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (!IS_POSIX(fl))
                        continue;
-               if (fl->fl_owner != owner)
+               if (fl->fl_owner != owner && fl->fl_owner != (fl_owner_t)file)
                        break;
        }
        spin_unlock(&inode->i_lock);
@@ -1198,19 +1199,30 @@ int locks_mandatory_area(int read_write, struct inode *inode,
 {
        struct file_lock fl;
        int error;
+       bool sleep = false;
 
        locks_init_lock(&fl);
-       fl.fl_owner = current->files;
        fl.fl_pid = current->tgid;
        fl.fl_file = filp;
        fl.fl_flags = FL_POSIX | FL_ACCESS;
        if (filp && !(filp->f_flags & O_NONBLOCK))
-               fl.fl_flags |= FL_SLEEP;
+               sleep = true;
        fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
        fl.fl_start = offset;
        fl.fl_end = offset + count - 1;
 
        for (;;) {
+               if (filp) {
+                       fl.fl_owner = (fl_owner_t)filp;
+                       fl.fl_flags &= ~FL_SLEEP;
+                       error = __posix_lock_file(inode, &fl, NULL);
+                       if (!error)
+                               break;
+               }
+
+               if (sleep)
+                       fl.fl_flags |= FL_SLEEP;
+               fl.fl_owner = current->files;
                error = __posix_lock_file(inode, &fl, NULL);
                if (error != FILE_LOCK_DEFERRED)
                        break;
@@ -1931,6 +1943,10 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
                goto out;
 
        if (cmd == F_GETLKP) {
+               error = -EINVAL;
+               if (flock.l_pid != 0)
+                       goto out;
+
                cmd = F_GETLK;
                file_lock.fl_flags |= FL_FILE_PVT;
                file_lock.fl_owner = (fl_owner_t)filp;
@@ -2062,11 +2078,19 @@ again:
         */
        switch (cmd) {
        case F_SETLKP:
+               error = -EINVAL;
+               if (flock.l_pid != 0)
+                       goto out;
+
                cmd = F_SETLK;
                file_lock->fl_flags |= FL_FILE_PVT;
                file_lock->fl_owner = (fl_owner_t)filp;
                break;
        case F_SETLKPW:
+               error = -EINVAL;
+               if (flock.l_pid != 0)
+                       goto out;
+
                cmd = F_SETLKW;
                file_lock->fl_flags |= FL_FILE_PVT;
                file_lock->fl_owner = (fl_owner_t)filp;
@@ -2121,6 +2145,10 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
                goto out;
 
        if (cmd == F_GETLKP) {
+               error = -EINVAL;
+               if (flock.l_pid != 0)
+                       goto out;
+
                cmd = F_GETLK64;
                file_lock.fl_flags |= FL_FILE_PVT;
                file_lock.fl_owner = (fl_owner_t)filp;
@@ -2185,11 +2213,19 @@ again:
         */
        switch (cmd) {
        case F_SETLKP:
+               error = -EINVAL;
+               if (flock.l_pid != 0)
+                       goto out;
+
                cmd = F_SETLK64;
                file_lock->fl_flags |= FL_FILE_PVT;
                file_lock->fl_owner = (fl_owner_t)filp;
                break;
        case F_SETLKPW:
+               error = -EINVAL;
+               if (flock.l_pid != 0)
+                       goto out;
+
                cmd = F_SETLKW64;
                file_lock->fl_flags |= FL_FILE_PVT;
                file_lock->fl_owner = (fl_owner_t)filp;
This page took 0.029898 seconds and 5 git commands to generate.