#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>
/* 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;
fl->fl_start = fl->fl_end = 0;
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
+ fl->fl_xid = -1;
}
EXPORT_SYMBOL(locks_init_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;
}
EXPORT_SYMBOL(locks_copy_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;
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,
};
/*
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;
* 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) {
* @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,
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);
return 0;
}
+EXPORT_SYMBOL(lease_modify);
+
static void time_out_leases(struct inode *inode)
{
struct file_lock **before;
}
}
- /**
-* 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
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);
}
}
{
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;
}
*
* 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;
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))
/*
goto out;
if (my_before != NULL) {
- error = lease_modify(my_before, arg);
+ error = lease->fl_lmops->fl_change(my_before, arg);
goto out;
}
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 {
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.
*/
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 {
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.
*/
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);
}