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:
J. Bruce Fields 2011-09-21 08:34:32 -04:00
Родитель c856694e3d
Коммит 8335ebd94b
1 изменённых файлов: 62 добавлений и 36 удалений

Просмотреть файл

@ -1352,18 +1352,7 @@ int fcntl_getlease(struct file *filp)
return type;
}
/**
* 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)
int generic_add_lease(struct file *filp, long arg, struct file_lock **flp)
{
struct file_lock *fl, **before, **my_before = NULL, *lease;
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;
error = -EACCES;
if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
error = -EAGAIN;
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
goto out;
error = -EINVAL;
if (!S_ISREG(inode->i_mode))
if ((arg == F_WRLCK)
&& ((dentry->d_count > 1)
|| (atomic_read(&inode->i_count) > 1)))
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
@ -1433,9 +1406,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
goto out;
}
if (arg == F_UNLCK)
goto out;
error = -EINVAL;
if (!leases_enable)
goto out;
@ -1446,6 +1416,62 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
out:
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);
static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)