- 论坛徽章:
- 4
|
先贴一个fcntl_setlease的代码吧,这个我最搞不明白。
int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
{
struct file_lock *fl, **before, **my_before = NULL;
struct dentry *dentry;
struct inode *inode;
int error, rdlease_count = 0, wrlease_count = 0;
dentry = filp->f_dentry;
inode = dentry->d_inode;
if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
return -EACCES;
if (!S_ISREG(inode->i_mode))
return -EINVAL;
lock_kernel();
time_out_leases(inode);
/*
* FIXME: What about F_RDLCK and files open for writing?
*/
error = -EAGAIN;
if ((arg == F_WRLCK)
&& ((atomic_read(&dentry->d_count) > 1)
|| (atomic_read(&inode->i_count) > 1)))
goto out_unlock;
/*
* At this point, we know that if there is an exclusive
* lease on this file, then we hold it on this filp
* (otherwise our open of this file would have blocked).
* And if we are trying to acquire an exclusive lease,
* then the file is not open by anyone (including us)
* except for this filp.
*/
for (before = &inode->i_flock;
((fl = *before) != NULL) && (fl->fl_flags & FL_LEASE);
before = &fl->fl_next) {
if (fl->fl_file == filp)
my_before = before;
else if (fl->fl_type == (F_INPROGRESS | F_UNLCK))
/*
* Someone is in the process of opening this
* file for writing so we may not take an
* exclusive lease on it.
*/
wrlease_count++;
else
rdlease_count++;
}
if ((arg == F_RDLCK && (wrlease_count > 0)) ||
(arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
goto out_unlock;
if (my_before != NULL) {
error = lease_modify(my_before, arg);
goto out_unlock;
}
error = 0;
if (arg == F_UNLCK)
goto out_unlock;
error = -EINVAL;
if (!leases_enable)
goto out_unlock;
error = lease_alloc(filp, arg, &fl);
if (error)
goto out_unlock;
error = fasync_helper(fd, filp, 1, &fl->fl_fasync);
if (error < 0) {
locks_free_lock(fl);
goto out_unlock;
}
fl->fl_next = *before;
*before = fl;
list_add(&fl->fl_link, &file_lock_list);
filp->f_owner.pid = current->pid;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
out_unlock:
unlock_kernel();
return error;
} |
|