leases: split up generic_setlease into lock/unlock cases
Eventually we should probably do the same thing to the file operations as well. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
c856694e3d
commit
8335ebd94b
98
fs/locks.c
98
fs/locks.c
|
@ -1352,18 +1352,7 @@ int fcntl_getlease(struct file *filp)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int generic_add_lease(struct file *filp, long arg, struct file_lock **flp)
|
||||||
* generic_setlease - sets a lease on an open file
|
|
||||||
* @filp: file pointer
|
|
||||||
* @arg: type of lease to obtain
|
|
||||||
* @flp: input - file_lock to use, output - file_lock inserted
|
|
||||||
*
|
|
||||||
* The (input) flp->fl_lmops->lm_break function is required
|
|
||||||
* by break_lease().
|
|
||||||
*
|
|
||||||
* Called with file_lock_lock held.
|
|
||||||
*/
|
|
||||||
int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|
|
||||||
{
|
{
|
||||||
struct file_lock *fl, **before, **my_before = NULL, *lease;
|
struct file_lock *fl, **before, **my_before = NULL, *lease;
|
||||||
struct dentry *dentry = filp->f_path.dentry;
|
struct dentry *dentry = filp->f_path.dentry;
|
||||||
|
@ -1372,29 +1361,13 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|
||||||
|
|
||||||
lease = *flp;
|
lease = *flp;
|
||||||
|
|
||||||
error = -EACCES;
|
error = -EAGAIN;
|
||||||
if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
|
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
|
||||||
goto out;
|
goto out;
|
||||||
error = -EINVAL;
|
if ((arg == F_WRLCK)
|
||||||
if (!S_ISREG(inode->i_mode))
|
&& ((dentry->d_count > 1)
|
||||||
|
|| (atomic_read(&inode->i_count) > 1)))
|
||||||
goto out;
|
goto out;
|
||||||
error = security_file_lock(filp, arg);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
time_out_leases(inode);
|
|
||||||
|
|
||||||
BUG_ON(!(*flp)->fl_lmops->lm_break);
|
|
||||||
|
|
||||||
if (arg != F_UNLCK) {
|
|
||||||
error = -EAGAIN;
|
|
||||||
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
|
|
||||||
goto out;
|
|
||||||
if ((arg == F_WRLCK)
|
|
||||||
&& ((dentry->d_count > 1)
|
|
||||||
|| (atomic_read(&inode->i_count) > 1)))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point, we know that if there is an exclusive
|
* At this point, we know that if there is an exclusive
|
||||||
|
@ -1433,9 +1406,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg == F_UNLCK)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
if (!leases_enable)
|
if (!leases_enable)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1446,6 +1416,62 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generic_delete_lease(struct file *filp, struct file_lock **flp)
|
||||||
|
{
|
||||||
|
struct file_lock *fl, **before;
|
||||||
|
struct dentry *dentry = filp->f_path.dentry;
|
||||||
|
struct inode *inode = dentry->d_inode;
|
||||||
|
|
||||||
|
for (before = &inode->i_flock;
|
||||||
|
((fl = *before) != NULL) && IS_LEASE(fl);
|
||||||
|
before = &fl->fl_next) {
|
||||||
|
if (fl->fl_file != filp)
|
||||||
|
continue;
|
||||||
|
return (*flp)->fl_lmops->lm_change(before, F_UNLCK);
|
||||||
|
}
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generic_setlease - sets a lease on an open file
|
||||||
|
* @filp: file pointer
|
||||||
|
* @arg: type of lease to obtain
|
||||||
|
* @flp: input - file_lock to use, output - file_lock inserted
|
||||||
|
*
|
||||||
|
* The (input) flp->fl_lmops->lm_break function is required
|
||||||
|
* by break_lease().
|
||||||
|
*
|
||||||
|
* Called with file_lock_lock held.
|
||||||
|
*/
|
||||||
|
int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|
||||||
|
{
|
||||||
|
struct dentry *dentry = filp->f_path.dentry;
|
||||||
|
struct inode *inode = dentry->d_inode;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
|
||||||
|
return -EACCES;
|
||||||
|
if (!S_ISREG(inode->i_mode))
|
||||||
|
return -EINVAL;
|
||||||
|
error = security_file_lock(filp, arg);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
time_out_leases(inode);
|
||||||
|
|
||||||
|
BUG_ON(!(*flp)->fl_lmops->lm_break);
|
||||||
|
|
||||||
|
switch (arg) {
|
||||||
|
case F_UNLCK:
|
||||||
|
return generic_delete_lease(filp, flp);
|
||||||
|
case F_RDLCK:
|
||||||
|
case F_WRLCK:
|
||||||
|
return generic_add_lease(filp, arg, flp);
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
EXPORT_SYMBOL(generic_setlease);
|
EXPORT_SYMBOL(generic_setlease);
|
||||||
|
|
||||||
static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
|
static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
|
||||||
|
|
Loading…
Reference in a new issue