Merge git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs
[cascardo/linux.git] / fs / locks.c
index 7d627ac..735b8d3 100644 (file)
@@ -326,17 +326,18 @@ static inline int flock_translate_cmd(int cmd) {
 }
 
 /* Fill in a file_lock structure with an appropriate FLOCK lock. */
-static int flock_make_lock(struct file *filp, struct file_lock **lock,
-               unsigned int cmd)
+static struct file_lock *
+flock_make_lock(struct file *filp, unsigned int cmd)
 {
        struct file_lock *fl;
        int type = flock_translate_cmd(cmd);
+
        if (type < 0)
-               return type;
+               return ERR_PTR(type);
        
        fl = locks_alloc_lock();
        if (fl == NULL)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        fl->fl_file = filp;
        fl->fl_owner = filp;
@@ -345,8 +346,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
        fl->fl_type = type;
        fl->fl_end = OFFSET_MAX;
        
-       *lock = fl;
-       return 0;
+       return fl;
 }
 
 static int assign_type(struct file_lock *fl, long type)
@@ -427,9 +427,11 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
 }
 
 /* default lease lock manager operations */
-static void lease_break_callback(struct file_lock *fl)
+static bool
+lease_break_callback(struct file_lock *fl)
 {
        kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
+       return false;
 }
 
 static void
@@ -463,7 +465,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl)
        if (assign_type(fl, type) != 0)
                return -EINVAL;
 
-       fl->fl_owner = current->files;
+       fl->fl_owner = filp;
        fl->fl_pid = current->tgid;
 
        fl->fl_file = filp;
@@ -1382,7 +1384,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
 {
        int error = 0;
        struct file_lock *new_fl;
-       struct file_lock *fl;
+       struct file_lock *fl, **before;
        unsigned long break_time;
        int want_write = (mode & O_ACCMODE) != O_RDONLY;
        LIST_HEAD(dispose);
@@ -1406,7 +1408,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
                        break_time++;   /* so that 0 means no break time */
        }
 
-       for (fl = inode->i_flock; fl && IS_LEASE(fl); fl = fl->fl_next) {
+       for (before = &inode->i_flock;
+                       ((fl = *before) != NULL) && IS_LEASE(fl);
+                       before = &fl->fl_next) {
                if (!leases_conflict(fl, new_fl))
                        continue;
                if (want_write) {
@@ -1420,9 +1424,14 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
                        fl->fl_flags |= FL_DOWNGRADE_PENDING;
                        fl->fl_downgrade_time = break_time;
                }
-               fl->fl_lmops->lm_break(fl);
+               if (fl->fl_lmops->lm_break(fl))
+                       locks_delete_lock(before, &dispose);
        }
 
+       fl = inode->i_flock;
+       if (!fl || !IS_LEASE(fl))
+               goto out;
+
        if (mode & O_NONBLOCK) {
                trace_break_lease_noblock(inode, new_fl);
                error = -EWOULDBLOCK;
@@ -1876,9 +1885,12 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
            !(f.file->f_mode & (FMODE_READ|FMODE_WRITE)))
                goto out_putf;
 
-       error = flock_make_lock(f.file, &lock, cmd);
-       if (error)
+       lock = flock_make_lock(f.file, cmd);
+       if (IS_ERR(lock)) {
+               error = PTR_ERR(lock);
                goto out_putf;
+       }
+
        if (can_sleep)
                lock->fl_flags |= FL_SLEEP;