upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / fs / locks.c
index fd6e88b..5cfa965 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/time.h>
+#include <linux/vs_limit.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -149,12 +150,16 @@ static kmem_cache_t *filelock_cache;
 /* 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);
 }
 
 /* Free a lock which is not in use. */
 static inline void locks_free_lock(struct file_lock *fl)
 {
+       vx_locks_dec(fl);
+
        if (fl == NULL) {
                BUG();
                return;
@@ -198,6 +203,7 @@ void locks_init_lock(struct file_lock *fl)
        fl->fl_start = fl->fl_end = 0;
        fl->fl_ops = NULL;
        fl->fl_lmops = NULL;
+       fl->fl_xid = -1;
 }
 
 EXPORT_SYMBOL(locks_init_lock);
@@ -235,6 +241,8 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
                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;
 }
 
 EXPORT_SYMBOL(locks_copy_lock);
@@ -271,6 +279,10 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
        fl->fl_flags = FL_FLOCK;
        fl->fl_type = type;
        fl->fl_end = OFFSET_MAX;
+
+       /* check against file xid maybe ? */
+       fl->fl_xid = vx_current_xid();
+       vx_locks_inc(fl);
        
        *lock = fl;
        return 0;
@@ -406,9 +418,16 @@ static void lease_release_private_callback(struct file_lock *fl)
        fl->fl_file->f_owner.signum = 0;
 }
 
-struct lock_manager_operations lease_manager_ops = {
+static int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
+{
+       return fl->fl_file == try->fl_file;
+}
+
+static struct lock_manager_operations lease_manager_ops = {
        .fl_break = lease_break_callback,
        .fl_release_private = lease_release_private_callback,
+       .fl_mylease = lease_mylease_callback,
+       .fl_change = lease_modify,
 };
 
 /*
@@ -441,6 +460,8 @@ static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
        if (fl == NULL)
                return -ENOMEM;
 
+       fl->fl_xid = vx_current_xid();
+       vx_locks_inc(fl);
        error = lease_init(filp, type, fl);
        if (error)
                return error;
@@ -770,7 +791,11 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
         * so we get them in advance to avoid races.
         */
        new_fl = locks_alloc_lock();
+       new_fl->fl_xid = vx_current_xid();
+       vx_locks_inc(new_fl);
        new_fl2 = locks_alloc_lock();
+       new_fl2->fl_xid = vx_current_xid();
+       vx_locks_inc(new_fl2);
 
        lock_kernel();
        if (request->fl_type != F_UNLCK) {
@@ -1011,7 +1036,7 @@ int locks_mandatory_locked(struct inode *inode)
  * @count:      length of area to check
  *
  * Searches the inode's list of locks to find any POSIX locks which conflict.
- * This function is called from locks_verify_area() and
+ * This function is called from rw_verify_area() and
  * locks_verify_truncate().
  */
 int locks_mandatory_area(int read_write, struct inode *inode,
@@ -1058,7 +1083,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
 EXPORT_SYMBOL(locks_mandatory_area);
 
 /* We already had a lease on this file; just change its type */
-static int lease_modify(struct file_lock **before, int arg)
+int lease_modify(struct file_lock **before, int arg)
 {
        struct file_lock *fl = *before;
        int error = assign_type(fl, arg);
@@ -1071,6 +1096,8 @@ static int lease_modify(struct file_lock **before, int arg)
        return 0;
 }
 
+EXPORT_SYMBOL(lease_modify);
+
 static void time_out_leases(struct inode *inode)
 {
        struct file_lock **before;
@@ -1090,26 +1117,6 @@ static void time_out_leases(struct inode *inode)
        }
 }
 
- /**
-*      remove_lease - let time_out_leases remove the lease.
-*      @@file_lock: the lease to remove
-*/
-void remove_lease(struct file_lock *fl)
-{
-       if (!IS_LEASE(fl))
-               return;
-
-       lock_kernel();
-
-       fl->fl_type = F_UNLCK | F_INPROGRESS;
-       fl->fl_break_time = jiffies - 10;
-       time_out_leases(fl->fl_file->f_dentry->d_inode);
-
-       unlock_kernel();
-}
-
-EXPORT_SYMBOL(remove_lease);
-
 /**
  *     __break_lease   -       revoke all outstanding leases on file
  *     @inode: the inode of the file to return
@@ -1174,10 +1181,8 @@ int __break_lease(struct inode *inode, unsigned int mode)
                if (fl->fl_type != future) {
                        fl->fl_type = future;
                        fl->fl_break_time = break_time;
-                       if (fl->fl_lmops && fl->fl_lmops->fl_break)
-                               fl->fl_lmops->fl_break(fl);
-                       else    /* lease must have lmops break callback */
-                               BUG();
+                       /* lease must have lmops break callback */
+                       fl->fl_lmops->fl_break(fl);
                }
        }
 
@@ -1228,7 +1233,7 @@ void lease_get_mtime(struct inode *inode, struct timespec *time)
 {
        struct file_lock *flock = inode->i_flock;
        if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK))
-               *time = CURRENT_TIME;
+               *time = current_fs_time(inode->i_sb);
        else
                *time = inode->i_mtime;
 }
@@ -1287,7 +1292,7 @@ int fcntl_getlease(struct file *filp)
  *
  *     Called with kernel lock held.
  */
-int __setlease(struct file *filp, long arg, struct file_lock **flp)
+static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 {
        struct file_lock *fl, **before, **my_before = NULL, *lease = *flp;
        struct dentry *dentry = filp->f_dentry;
@@ -1319,7 +1324,7 @@ int __setlease(struct file *filp, long arg, struct file_lock **flp)
        for (before = &inode->i_flock;
                        ((fl = *before) != NULL) && IS_LEASE(fl);
                        before = &fl->fl_next) {
-               if (fl->fl_file == filp)
+               if (lease->fl_lmops->fl_mylease(fl, lease))
                        my_before = before;
                else if (fl->fl_type == (F_INPROGRESS | F_UNLCK))
                        /*
@@ -1337,7 +1342,7 @@ int __setlease(struct file *filp, long arg, struct file_lock **flp)
                goto out;
 
        if (my_before != NULL) {
-               error = lease_modify(my_before, arg);
+               error = lease->fl_lmops->fl_change(my_before, arg);
                goto out;
        }
 
@@ -1563,9 +1568,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
                error = filp->f_op->lock(filp, F_GETLK, &file_lock);
                if (error < 0)
                        goto out;
-               else if (error == LOCK_USE_CLNT)
-                 /* Bypass for NFS with no locking - 2.0.36 compat */
-                 fl = posix_test_lock(filp, &file_lock);
                else
                  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
        } else {
@@ -1613,6 +1615,9 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l)
        if (file_lock == NULL)
                return -ENOLCK;
 
+       file_lock->fl_xid = vx_current_xid();
+       vx_locks_inc(file_lock);
+
        /*
         * This might block, so we do it before checking the inode.
         */
@@ -1708,9 +1713,6 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
                error = filp->f_op->lock(filp, F_GETLK, &file_lock);
                if (error < 0)
                        goto out;
-               else if (error == LOCK_USE_CLNT)
-                 /* Bypass for NFS with no locking - 2.0.36 compat */
-                 fl = posix_test_lock(filp, &file_lock);
                else
                  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
        } else {
@@ -1747,6 +1749,9 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
        if (file_lock == NULL)
                return -ENOLCK;
 
+       file_lock->fl_xid = vx_current_xid();
+       vx_locks_inc(file_lock);
+
        /*
         * This might block, so we do it before checking the inode.
         */
@@ -1884,8 +1889,13 @@ void locks_remove_flock(struct file *filp)
                return;
 
        if (filp->f_op && filp->f_op->flock) {
-               struct file_lock fl = { .fl_flags = FL_FLOCK,
-                                       .fl_type = F_UNLCK };
+               struct file_lock fl = {
+                       .fl_pid = current->tgid,
+                       .fl_file = filp,
+                       .fl_flags = FL_FLOCK,
+                       .fl_type = F_UNLCK,
+                       .fl_end = OFFSET_MAX,
+               };
                filp->f_op->flock(filp, F_SETLKW, &fl);
        }