fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / locks.c
index 8724f22..9f4fd59 100644 (file)
 #include <linux/syscalls.h>
 #include <linux/time.h>
 #include <linux/rcupdate.h>
+#include <linux/vs_base.h>
 #include <linux/vs_limit.h>
 
 #include <asm/semaphore.h>
@@ -140,53 +141,43 @@ int lease_break_time = 45;
 #define for_each_lock(inode, lockp) \
        for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
 
-LIST_HEAD(file_lock_list);
-
-EXPORT_SYMBOL(file_lock_list);
-
+static LIST_HEAD(file_lock_list);
 static LIST_HEAD(blocked_list);
 
-static kmem_cache_t *filelock_cache;
+static struct kmem_cache *filelock_cache __read_mostly;
 
 /* Allocate an empty lock structure. */
 static struct file_lock *locks_alloc_lock(void)
 {
        if (!vx_locks_avail(1))
                return NULL;
-       return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
+       return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
 }
 
-/* Free a lock which is not in use. */
-static void locks_free_lock(struct file_lock *fl)
+static void locks_release_private(struct file_lock *fl)
 {
-       if (fl == NULL) {
-               BUG();
-               return;
-       }
-
-       vx_locks_dec(fl);
-
-       if (waitqueue_active(&fl->fl_wait))
-               panic("Attempting to free lock with active wait queue");
-
-       if (!list_empty(&fl->fl_block))
-               panic("Attempting to free lock with active block list");
-
-       if (!list_empty(&fl->fl_link))
-               panic("Attempting to free lock on active lock list");
-
        if (fl->fl_ops) {
                if (fl->fl_ops->fl_release_private)
                        fl->fl_ops->fl_release_private(fl);
                fl->fl_ops = NULL;
        }
-
        if (fl->fl_lmops) {
                if (fl->fl_lmops->fl_release_private)
                        fl->fl_lmops->fl_release_private(fl);
                fl->fl_lmops = NULL;
        }
 
+}
+
+/* Free a lock which is not in use. */
+static void locks_free_lock(struct file_lock *fl)
+{
+       BUG_ON(waitqueue_active(&fl->fl_wait));
+       BUG_ON(!list_empty(&fl->fl_block));
+       BUG_ON(!list_empty(&fl->fl_link));
+
+       vx_locks_dec(fl);
+       locks_release_private(fl);
        kmem_cache_free(filelock_cache, fl);
 }
 
@@ -214,7 +205,7 @@ EXPORT_SYMBOL(locks_init_lock);
  * Initialises the fields of the file lock which are invariant for
  * free file_locks.
  */
-static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags)
 {
        struct file_lock *lock = (struct file_lock *) foo;
 
@@ -225,26 +216,47 @@ static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags)
        locks_init_lock(lock);
 }
 
+static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
+{
+       if (fl->fl_ops) {
+               if (fl->fl_ops->fl_copy_lock)
+                       fl->fl_ops->fl_copy_lock(new, fl);
+               new->fl_ops = fl->fl_ops;
+       }
+       if (fl->fl_lmops) {
+               if (fl->fl_lmops->fl_copy_lock)
+                       fl->fl_lmops->fl_copy_lock(new, fl);
+               new->fl_lmops = fl->fl_lmops;
+       }
+}
+
 /*
  * Initialize a new lock from an existing file_lock structure.
  */
-void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
+static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
 {
        new->fl_owner = fl->fl_owner;
        new->fl_pid = fl->fl_pid;
-       new->fl_file = fl->fl_file;
+       new->fl_file = NULL;
        new->fl_flags = fl->fl_flags;
        new->fl_type = fl->fl_type;
        new->fl_start = fl->fl_start;
        new->fl_end = fl->fl_end;
+       new->fl_ops = NULL;
+       new->fl_lmops = NULL;
+}
+
+void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
+{
+       locks_release_private(new);
+
+       __locks_copy_lock(new, fl);
+       new->fl_file = fl->fl_file;
        new->fl_ops = fl->fl_ops;
        new->fl_lmops = fl->fl_lmops;
-       if (fl->fl_ops && fl->fl_ops->fl_copy_lock)
-               fl->fl_ops->fl_copy_lock(new, fl);
-       if (fl->fl_lmops && fl->fl_lmops->fl_copy_lock)
-               fl->fl_lmops->fl_copy_lock(new, fl);
-
        new->fl_xid = fl->fl_xid;
+
+       locks_copy_private(new, fl);
 }
 
 EXPORT_SYMBOL(locks_copy_lock);
@@ -282,6 +294,8 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
        fl->fl_type = type;
        fl->fl_end = OFFSET_MAX;
 
+       vxd_assert(filp->f_xid == vx_current_xid(),
+               "f_xid(%d) == current(%d)", filp->f_xid, vx_current_xid());
        fl->fl_xid = filp->f_xid;
        vx_locks_inc(fl);
        
@@ -312,14 +326,14 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
        off_t start, end;
 
        switch (l->l_whence) {
-       case 0: /*SEEK_SET*/
+       case SEEK_SET:
                start = 0;
                break;
-       case 1: /*SEEK_CUR*/
+       case SEEK_CUR:
                start = filp->f_pos;
                break;
-       case 2: /*SEEK_END*/
-               start = i_size_read(filp->f_dentry->d_inode);
+       case SEEK_END:
+               start = i_size_read(filp->f_path.dentry->d_inode);
                break;
        default:
                return -EINVAL;
@@ -362,14 +376,14 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
        loff_t start;
 
        switch (l->l_whence) {
-       case 0: /*SEEK_SET*/
+       case SEEK_SET:
                start = 0;
                break;
-       case 1: /*SEEK_CUR*/
+       case SEEK_CUR:
                start = filp->f_pos;
                break;
-       case 2: /*SEEK_END*/
-               start = i_size_read(filp->f_dentry->d_inode);
+       case SEEK_END:
+               start = i_size_read(filp->f_path.dentry->d_inode);
                break;
        default:
                return -EINVAL;
@@ -470,6 +484,9 @@ static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
                goto out;
 
        fl->fl_xid = vx_current_xid();
+       if (filp)
+               vxd_assert(filp->f_xid == fl->fl_xid,
+                       "f_xid(%d) == fl_xid(%d)", filp->f_xid, fl->fl_xid);
        vx_locks_inc(fl);
        error = lease_init(filp, type, fl);
        if (error) {
@@ -527,12 +544,7 @@ static void locks_delete_block(struct file_lock *waiter)
 static void locks_insert_block(struct file_lock *blocker, 
                               struct file_lock *waiter)
 {
-       if (!list_empty(&waiter->fl_block)) {
-               printk(KERN_ERR "locks_insert_block: removing duplicated lock "
-                       "(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid,
-                       waiter->fl_start, waiter->fl_end, waiter->fl_type);
-               __locks_delete_block(waiter);
-       }
+       BUG_ON(!list_empty(&waiter->fl_block));
        list_add_tail(&waiter->fl_block, &blocker->fl_block);
        waiter->fl_next = blocker;
        if (IS_POSIX(blocker))
@@ -671,21 +683,26 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
        return result;
 }
 
-struct file_lock *
-posix_test_lock(struct file *filp, struct file_lock *fl)
+int
+posix_test_lock(struct file *filp, struct file_lock *fl,
+               struct file_lock *conflock)
 {
        struct file_lock *cfl;
 
        lock_kernel();
-       for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
+       for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
                if (!IS_POSIX(cfl))
                        continue;
                if (posix_locks_conflict(cfl, fl))
                        break;
        }
+       if (cfl) {
+               __locks_copy_lock(conflock, cfl);
+               unlock_kernel();
+               return 1;
+       }
        unlock_kernel();
-
-       return (cfl);
+       return 0;
 }
 
 EXPORT_SYMBOL(posix_test_lock);
@@ -704,7 +721,7 @@ EXPORT_SYMBOL(posix_test_lock);
  * from a broken NFS client. But broken NFS clients have a lot more to
  * worry about than proper deadlock detection anyway... --okir
  */
-int posix_locks_deadlock(struct file_lock *caller_fl,
+static int posix_locks_deadlock(struct file_lock *caller_fl,
                                struct file_lock *block_fl)
 {
        struct list_head *tmp;
@@ -723,21 +740,25 @@ next_task:
        return 0;
 }
 
-EXPORT_SYMBOL(posix_locks_deadlock);
-
 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
  * at the head of the list, but that's secret knowledge known only to
  * flock_lock_file and posix_lock_file.
+ *
+ * Note that if called with an FL_EXISTS argument, the caller may determine
+ * whether or not a lock was successfully freed by testing the return
+ * value for -ENOENT.
  */
 static int flock_lock_file(struct file *filp, struct file_lock *request)
 {
        struct file_lock *new_fl = NULL;
        struct file_lock **before;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode * inode = filp->f_path.dentry->d_inode;
        int error = 0;
        int found = 0;
 
        lock_kernel();
+       if (request->fl_flags & FL_ACCESS)
+               goto find_conflict;
        for_each_lock(inode, before) {
                struct file_lock *fl = *before;
                if (IS_POSIX(fl))
@@ -753,9 +774,13 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
                break;
        }
 
-       if (request->fl_type == F_UNLCK)
+       if (request->fl_type == F_UNLCK) {
+               if ((request->fl_flags & FL_EXISTS) && !found)
+                       error = -ENOENT;
                goto out;
+       }
 
+       error = -ENOMEM;
        new_fl = locks_alloc_lock();
        if (new_fl == NULL)
                goto out;
@@ -766,6 +791,8 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
        if (found)
                cond_resched();
 
+       new_fl->fl_xid = -1;
+find_conflict:
        for_each_lock(inode, before) {
                struct file_lock *fl = *before;
                if (IS_POSIX(fl))
@@ -779,10 +806,13 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
                        locks_insert_block(fl, request);
                goto out;
        }
+       if (request->fl_flags & FL_ACCESS)
+               goto out;
        locks_copy_lock(new_fl, request);
-       vx_locks_inc(new_fl);
        locks_insert_lock(&inode->i_flock, new_fl);
+       vx_locks_inc(new_fl);
        new_fl = NULL;
+       error = 0;
 
 out:
        unlock_kernel();
@@ -791,27 +821,35 @@ out:
        return error;
 }
 
-EXPORT_SYMBOL(posix_lock_file);
-
-static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid_t xid)
+static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request,
+       struct file_lock *conflock, xid_t xid)
 {
        struct file_lock *fl;
-       struct file_lock *new_fl, *new_fl2;
+       struct file_lock *new_fl = NULL;
+       struct file_lock *new_fl2 = NULL;
        struct file_lock *left = NULL;
        struct file_lock *right = NULL;
        struct file_lock **before;
        int error, added = 0;
 
+       vxd_assert(xid == vx_current_xid(),
+               "xid(%d) == current(%d)", xid, vx_current_xid());
        /*
         * We may need two file_lock structures for this operation,
         * so we get them in advance to avoid races.
+        *
+        * In some cases we can be sure, that no new locks will be needed
         */
-       new_fl = locks_alloc_lock();
-       new_fl->fl_xid = xid;
-       vx_locks_inc(new_fl);
-       new_fl2 = locks_alloc_lock();
-       new_fl2->fl_xid = xid;
-       vx_locks_inc(new_fl2);
+       if (!(request->fl_flags & FL_ACCESS) &&
+           (request->fl_type != F_UNLCK ||
+            request->fl_start != 0 || request->fl_end != OFFSET_MAX)) {
+               new_fl = locks_alloc_lock();
+               new_fl->fl_xid = xid;
+               vx_locks_inc(new_fl);
+               new_fl2 = locks_alloc_lock();
+               new_fl2->fl_xid = xid;
+               vx_locks_inc(new_fl2);
+       }
 
        lock_kernel();
        if (request->fl_type != F_UNLCK) {
@@ -821,6 +859,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid
                                continue;
                        if (!posix_locks_conflict(request, fl))
                                continue;
+                       if (conflock)
+                               locks_copy_lock(conflock, fl);
                        error = -EAGAIN;
                        if (!(request->fl_flags & FL_SLEEP))
                                goto out;
@@ -838,14 +878,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid
        if (request->fl_flags & FL_ACCESS)
                goto out;
 
-       error = -ENOLCK; /* "no luck" */
-       if (!(new_fl && new_fl2))
-               goto out;
-
        /*
-        * We've allocated the new locks in advance, so there are no
-        * errors possible (and no blocking operations) from here on.
-        * 
         * Find the first old lock with the same owner as the new lock.
         */
        
@@ -930,7 +963,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid
                                fl->fl_start = request->fl_start;
                                fl->fl_end = request->fl_end;
                                fl->fl_type = request->fl_type;
-                               fl->fl_u = request->fl_u;
+                               locks_release_private(fl);
+                               locks_copy_private(fl, request);
                                request = fl;
                                added = 1;
                        }
@@ -941,10 +975,28 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid
                before = &fl->fl_next;
        }
 
+       /*
+        * The above code only modifies existing locks in case of
+        * merging or replacing.  If new lock(s) need to be inserted
+        * all modifications are done bellow this, so it's safe yet to
+        * bail out.
+        */
+       error = -ENOLCK; /* "no luck" */
+       if (right && left == right && !new_fl2)
+               goto out;
+
        error = 0;
        if (!added) {
-               if (request->fl_type == F_UNLCK)
+               if (request->fl_type == F_UNLCK) {
+                       if (request->fl_flags & FL_EXISTS)
+                               error = -ENOENT;
                        goto out;
+               }
+
+               if (!new_fl) {
+                       error = -ENOLCK;
+                       goto out;
+               }
                locks_copy_lock(new_fl, request);
                locks_insert_lock(before, new_fl);
                new_fl = NULL;
@@ -986,11 +1038,33 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid
  * Add a POSIX style lock to a file.
  * We merge adjacent & overlapping locks whenever possible.
  * POSIX locks are sorted by owner task, then by starting address
+ *
+ * Note that if called with an FL_EXISTS argument, the caller may determine
+ * whether or not a lock was successfully freed by testing the return
+ * value for -ENOENT.
  */
 int posix_lock_file(struct file *filp, struct file_lock *fl)
 {
-       return __posix_lock_file(filp->f_dentry->d_inode, fl, filp->f_xid);
+       return __posix_lock_file_conf(filp->f_path.dentry->d_inode,
+               fl, NULL, filp->f_xid);
+}
+EXPORT_SYMBOL(posix_lock_file);
+
+/**
+ * posix_lock_file_conf - Apply a POSIX-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ * @conflock: Place to return a copy of the conflicting lock, if found.
+ *
+ * Except for the conflock parameter, acts just like posix_lock_file.
+ */
+int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
+                       struct file_lock *conflock)
+{
+       return __posix_lock_file_conf(filp->f_path.dentry->d_inode,
+               fl, conflock, filp->f_xid);
 }
+EXPORT_SYMBOL(posix_lock_file_conf);
 
 /**
  * posix_lock_file_wait - Apply a POSIX-style lock to a file
@@ -1006,8 +1080,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
        int error;
        might_sleep ();
        for (;;) {
-               error = __posix_lock_file(filp->f_dentry->d_inode,
-                       fl, filp->f_xid);
+               error = posix_lock_file(filp, fl);
                if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
                        break;
                error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1079,7 +1152,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
        fl.fl_end = offset + count - 1;
 
        for (;;) {
-               error = __posix_lock_file(inode, &fl, filp->f_xid);
+               error = __posix_lock_file_conf(inode, &fl, NULL, filp->f_xid);
                if (error != -EAGAIN)
                        break;
                if (!(fl.fl_flags & FL_SLEEP))
@@ -1289,8 +1362,8 @@ int fcntl_getlease(struct file *filp)
        int type = F_UNLCK;
 
        lock_kernel();
-       time_out_leases(filp->f_dentry->d_inode);
-       for (fl = filp->f_dentry->d_inode->i_flock; fl && IS_LEASE(fl);
+       time_out_leases(filp->f_path.dentry->d_inode);
+       for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
                        fl = fl->fl_next) {
                if (fl->fl_file == filp) {
                        type = fl->fl_type & ~F_INPROGRESS;
@@ -1315,7 +1388,7 @@ int fcntl_getlease(struct file *filp)
 static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 {
        struct file_lock *fl, **before, **my_before = NULL, *lease;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error, rdlease_count = 0, wrlease_count = 0;
 
@@ -1383,8 +1456,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
                goto out;
 
        locks_copy_lock(fl, lease);
-
        locks_insert_lock(before, fl);
+       vx_locks_inc(fl);
 
        *flp = fl;
        error = 0;
@@ -1404,7 +1477,7 @@ out:
 
 int setlease(struct file *filp, long arg, struct file_lock **lease)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error;
 
@@ -1438,7 +1511,7 @@ EXPORT_SYMBOL(setlease);
 int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
 {
        struct file_lock fl, *flp = &fl;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error;
 
@@ -1470,7 +1543,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
                goto out_unlock;
        }
 
-       error = f_setown(filp, current->pid, 0);
+       error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
 out_unlock:
        unlock_kernel();
        return error;
@@ -1572,7 +1645,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
  */
 int fcntl_getlk(struct file *filp, struct flock __user *l)
 {
-       struct file_lock *fl, file_lock;
+       struct file_lock *fl, cfl, file_lock;
        struct flock flock;
        int error;
 
@@ -1596,7 +1669,7 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
                else
                  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
        } else {
-               fl = posix_test_lock(filp, &file_lock);
+               fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
        }
  
        flock.l_type = F_UNLCK;
@@ -1641,6 +1714,8 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
        if (file_lock == NULL)
                return -ENOLCK;
 
+       vxd_assert(filp->f_xid == vx_current_xid(),
+               "f_xid(%d) == current(%d)", filp->f_xid, vx_current_xid());
        file_lock->fl_xid = filp->f_xid;
        vx_locks_inc(file_lock);
 
@@ -1651,7 +1726,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
        if (copy_from_user(&flock, l, sizeof(flock)))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        /* Don't allow mandatory locks on files that may be memory mapped
         * and shared.
@@ -1696,8 +1771,7 @@ again:
                error = filp->f_op->lock(filp, cmd, file_lock);
        else {
                for (;;) {
-                       error = __posix_lock_file(inode, file_lock,
-                               filp->f_xid);
+                       error = posix_lock_file(filp, file_lock);
                        if ((error != -EAGAIN) || (cmd == F_SETLK))
                                break;
                        error = wait_event_interruptible(file_lock->fl_wait,
@@ -1730,7 +1804,7 @@ out:
  */
 int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
 {
-       struct file_lock *fl, file_lock;
+       struct file_lock *fl, cfl, file_lock;
        struct flock64 flock;
        int error;
 
@@ -1754,7 +1828,7 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
                else
                  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
        } else {
-               fl = posix_test_lock(filp, &file_lock);
+               fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
        }
  
        flock.l_type = F_UNLCK;
@@ -1788,6 +1862,8 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
        if (file_lock == NULL)
                return -ENOLCK;
 
+       vxd_assert(filp->f_xid == vx_current_xid(),
+               "f_xid(%d) == current(%d)", filp->f_xid, vx_current_xid());
        file_lock->fl_xid = filp->f_xid;
        vx_locks_inc(file_lock);
 
@@ -1798,7 +1874,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
        if (copy_from_user(&flock, l, sizeof(flock)))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        /* Don't allow mandatory locks on files that may be memory mapped
         * and shared.
@@ -1843,8 +1919,7 @@ again:
                error = filp->f_op->lock(filp, cmd, file_lock);
        else {
                for (;;) {
-                       error = __posix_lock_file(inode, file_lock,
-                               filp->f_xid);
+                       error = posix_lock_file(filp, file_lock);
                        if ((error != -EAGAIN) || (cmd == F_SETLK64))
                                break;
                        error = wait_event_interruptible(file_lock->fl_wait,
@@ -1879,19 +1954,18 @@ out:
  */
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
-       struct file_lock lock, **before;
+       struct file_lock lock;
 
        /*
         * If there are no locks held on this file, we don't need to call
         * posix_lock_file().  Another process could be setting a lock on this
         * file at the same time, but we wouldn't remove that lock anyway.
         */
-       before = &filp->f_dentry->d_inode->i_flock;
-       if (*before == NULL)
+       if (!filp->f_path.dentry->d_inode->i_flock)
                return;
 
        lock.fl_type = F_UNLCK;
-       lock.fl_flags = FL_POSIX;
+       lock.fl_flags = FL_POSIX | FL_CLOSE;
        lock.fl_start = 0;
        lock.fl_end = OFFSET_MAX;
        lock.fl_owner = owner;
@@ -1900,25 +1974,11 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
        lock.fl_ops = NULL;
        lock.fl_lmops = NULL;
 
-       if (filp->f_op && filp->f_op->lock != NULL) {
+       if (filp->f_op && filp->f_op->lock != NULL)
                filp->f_op->lock(filp, F_SETLK, &lock);
-               goto out;
-       }
+       else
+               posix_lock_file(filp, &lock);
 
-       /* Can't use posix_lock_file here; we need to remove it no matter
-        * which pid we have.
-        */
-       lock_kernel();
-       while (*before != NULL) {
-               struct file_lock *fl = *before;
-               if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) {
-                       locks_delete_lock(before);
-                       continue;
-               }
-               before = &fl->fl_next;
-       }
-       unlock_kernel();
-out:
        if (lock.fl_ops && lock.fl_ops->fl_release_private)
                lock.fl_ops->fl_release_private(&lock);
 }
@@ -1930,7 +1990,7 @@ EXPORT_SYMBOL(locks_remove_posix);
  */
 void locks_remove_flock(struct file *filp)
 {
-       struct inode * inode = filp->f_dentry->d_inode; 
+       struct inode * inode = filp->f_path.dentry->d_inode;
        struct file_lock *fl;
        struct file_lock **before;
 
@@ -1971,21 +2031,6 @@ void locks_remove_flock(struct file *filp)
        unlock_kernel();
 }
 
-/**
- *     posix_block_lock - blocks waiting for a file lock
- *     @blocker: the lock which is blocking
- *     @waiter: the lock which conflicts and has to wait
- *
- * lockd needs to block waiting for locks.
- */
-void
-posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
-{
-       locks_insert_block(blocker, waiter);
-}
-
-EXPORT_SYMBOL(posix_block_lock);
-
 /**
  *     posix_unblock_lock - stop waiting for a file lock
  *      @filp:   how the file was opened
@@ -2014,7 +2059,7 @@ static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
        struct inode *inode = NULL;
 
        if (fl->fl_file != NULL)
-               inode = fl->fl_file->f_dentry->d_inode;
+               inode = fl->fl_file->f_path.dentry->d_inode;
 
        out += sprintf(out, "%d:%s ", id, pfx);
        if (IS_POSIX(fl)) {
@@ -2118,7 +2163,7 @@ int get_locks_status(char *buffer, char **start, off_t offset, int length)
                struct list_head *btmp;
                struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
 
-               if (!vx_check(fl->fl_xid, VX_IDENT|VX_WATCH))
+               if (!vx_check(fl->fl_xid, VS_WATCH_P|VS_IDENT))
                        continue;
 
                lock_get_status(q, fl, ++i, "");
@@ -2223,63 +2268,6 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len)
 
 EXPORT_SYMBOL(lock_may_write);
 
-static inline void __steal_locks(struct file *file, fl_owner_t from)
-{
-       struct inode *inode = file->f_dentry->d_inode;
-       struct file_lock *fl = inode->i_flock;
-
-       while (fl) {
-               if (fl->fl_file == file && fl->fl_owner == from)
-                       fl->fl_owner = current->files;
-               fl = fl->fl_next;
-       }
-}
-
-/* When getting ready for executing a binary, we make sure that current
- * has a files_struct on its own. Before dropping the old files_struct,
- * we take over ownership of all locks for all file descriptors we own.
- * Note that we may accidentally steal a lock for a file that a sibling
- * has created since the unshare_files() call.
- */
-void steal_locks(fl_owner_t from)
-{
-       struct files_struct *files = current->files;
-       int i, j;
-       struct fdtable *fdt;
-
-       if (from == files)
-               return;
-
-       lock_kernel();
-       j = 0;
-
-       /*
-        * We are not taking a ref to the file structures, so
-        * we need to acquire ->file_lock.
-        */
-       spin_lock(&files->file_lock);
-       fdt = files_fdtable(files);
-       for (;;) {
-               unsigned long set;
-               i = j * __NFDBITS;
-               if (i >= fdt->max_fdset || i >= fdt->max_fds)
-                       break;
-               set = fdt->open_fds->fds_bits[j++];
-               while (set) {
-                       if (set & 1) {
-                               struct file *file = fdt->fd[i];
-                               if (file)
-                                       __steal_locks(file, from);
-                       }
-                       i++;
-                       set >>= 1;
-               }
-       }
-       spin_unlock(&files->file_lock);
-       unlock_kernel();
-}
-EXPORT_SYMBOL(steal_locks);
-
 static int __init filelock_init(void)
 {
        filelock_cache = kmem_cache_create("file_lock_cache",