forked from Minki/linux
File locking related changes for v4.2 (pile #1)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVo5PmAAoJEAAOaEEZVoIVQkAP/iU8i/atra0YVACMckwLH0rV OlMs66V1Ur/+3PNwnBAPAITIQTIokRcCUe+ChwlM5I0/N6sHb8b+qKqsc1cesSn4 rBIBXigjMTeBS4MZXYhCeo9oMPPRtTpKdZMGlh499wQcc39BkmRtYPeONQCaYovW uDq4Mydbt3m92wJK3s2VNsAeNgGKsS7VNZkjQKFxsKSreFKz7NhDBab18lvqAC/9 1z4bqdM4I82uaDdecHiZu8EgTKzDN8wqxYwXJ6RmAtHDXn9r2aXOIwH9+nMGxXQF DDBgiFb49moK1owJ9UUO3n6GR5HPmmlhshS426uJiODTbI5KlX+68kYQsTpcuRch CjNBPtUxeDvqK+FRb1jCftA43tcRtqhLYrQ3lr+V4/UqWNZzH0xkrCozg1aP7yg2 XBhw+OWqLm7GyH51IdpRDKQi1hgX9QVp9s6XLhXf7R/o2Lsbyfehe31pJcgcjMbc 2QJiurbSK9+a89bwAn2xozMDOcIXyYAQyS2IBUMuNtCVo6vtsqmtYU+UEKJzoKph BlwlMqIQyuT0P+jPjy4lxHmskz6I8ToykRS39RVtflS8JPrSAcJ3VVJHnabQcwA7 L1qrDbvaQ+nhLLoX7+zi0yqbLbdD5L+6WXJDaFQsK4XtF0c+hxxvoKCPg3vWOqt3 vAHDSy5Q8s94lsOvzcXC =aj6S -----END PGP SIGNATURE----- Merge tag 'locks-v4.2-1' of git://git.samba.org/jlayton/linux Pull file locking updates from Jeff Layton: "I had thought that I was going to get away without a pull request this cycle. There was a NFSv4 file locking problem that cropped up that I tried to fix in the NFSv4 code alone, but that fix has turned out to be problematic. These patches fix this in the correct way. Note that this touches some NFSv4 code as well. Ordinarily I'd wait for Trond to ACK this, but he's on holiday right now and the bug is rather nasty. So I suggest we merge this and if he raises issues with it we can sort it out when he gets back" Acked-by: Bruce Fields <bfields@fieldses.org> Acked-by: Dan Williams <dan.j.williams@intel.com> [ +1 to this series fixing a 100% reproducible slab corruption + general protection fault in my nfs-root test environment. - Dan ] Acked-by: Anna Schumaker <Anna.Schumaker@Netapp.com> * tag 'locks-v4.2-1' of git://git.samba.org/jlayton/linux: locks: inline posix_lock_file_wait and flock_lock_file_wait nfs4: have do_vfs_lock take an inode pointer locks: new helpers - flock_lock_inode_wait and posix_lock_inode_wait locks: have flock_lock_file take an inode pointer instead of a filp Revert "nfs: take extra reference to fl->fl_file when running a LOCKU operation"
This commit is contained in:
commit
16ff49a08b
38
fs/locks.c
38
fs/locks.c
@ -862,12 +862,11 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
|
||||
* whether or not a lock was successfully freed by testing the return
|
||||
* value for -ENOENT.
|
||||
*/
|
||||
static int flock_lock_file(struct file *filp, struct file_lock *request)
|
||||
static int flock_lock_inode(struct inode *inode, struct file_lock *request)
|
||||
{
|
||||
struct file_lock *new_fl = NULL;
|
||||
struct file_lock *fl;
|
||||
struct file_lock_context *ctx;
|
||||
struct inode *inode = file_inode(filp);
|
||||
int error = 0;
|
||||
bool found = false;
|
||||
LIST_HEAD(dispose);
|
||||
@ -890,7 +889,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
|
||||
goto find_conflict;
|
||||
|
||||
list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
|
||||
if (filp != fl->fl_file)
|
||||
if (request->fl_file != fl->fl_file)
|
||||
continue;
|
||||
if (request->fl_type == fl->fl_type)
|
||||
goto out;
|
||||
@ -1164,20 +1163,19 @@ int posix_lock_file(struct file *filp, struct file_lock *fl,
|
||||
EXPORT_SYMBOL(posix_lock_file);
|
||||
|
||||
/**
|
||||
* posix_lock_file_wait - Apply a POSIX-style lock to a file
|
||||
* @filp: The file to apply the lock to
|
||||
* posix_lock_inode_wait - Apply a POSIX-style lock to a file
|
||||
* @inode: inode of file to which lock request should be applied
|
||||
* @fl: The lock to be applied
|
||||
*
|
||||
* Add a POSIX style lock to a file.
|
||||
* We merge adjacent & overlapping locks whenever possible.
|
||||
* POSIX locks are sorted by owner task, then by starting address
|
||||
* Variant of posix_lock_file_wait that does not take a filp, and so can be
|
||||
* used after the filp has already been torn down.
|
||||
*/
|
||||
int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
|
||||
{
|
||||
int error;
|
||||
might_sleep ();
|
||||
for (;;) {
|
||||
error = posix_lock_file(filp, fl, NULL);
|
||||
error = __posix_lock_file(inode, fl, NULL);
|
||||
if (error != FILE_LOCK_DEFERRED)
|
||||
break;
|
||||
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
|
||||
@ -1189,7 +1187,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
}
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(posix_lock_file_wait);
|
||||
EXPORT_SYMBOL(posix_lock_inode_wait);
|
||||
|
||||
/**
|
||||
* locks_mandatory_locked - Check for an active lock
|
||||
@ -1851,18 +1849,18 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
|
||||
}
|
||||
|
||||
/**
|
||||
* flock_lock_file_wait - Apply a FLOCK-style lock to a file
|
||||
* @filp: The file to apply the lock to
|
||||
* flock_lock_inode_wait - Apply a FLOCK-style lock to a file
|
||||
* @inode: inode of the file to apply to
|
||||
* @fl: The lock to be applied
|
||||
*
|
||||
* Add a FLOCK style lock to a file.
|
||||
* Apply a FLOCK style lock request to an inode.
|
||||
*/
|
||||
int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)
|
||||
{
|
||||
int error;
|
||||
might_sleep();
|
||||
for (;;) {
|
||||
error = flock_lock_file(filp, fl);
|
||||
error = flock_lock_inode(inode, fl);
|
||||
if (error != FILE_LOCK_DEFERRED)
|
||||
break;
|
||||
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
|
||||
@ -1874,8 +1872,7 @@ int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(flock_lock_file_wait);
|
||||
EXPORT_SYMBOL(flock_lock_inode_wait);
|
||||
|
||||
/**
|
||||
* sys_flock: - flock() system call.
|
||||
@ -2401,7 +2398,8 @@ locks_remove_flock(struct file *filp)
|
||||
.fl_type = F_UNLCK,
|
||||
.fl_end = OFFSET_MAX,
|
||||
};
|
||||
struct file_lock_context *flctx = file_inode(filp)->i_flctx;
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
|
||||
if (list_empty(&flctx->flc_flock))
|
||||
return;
|
||||
@ -2409,7 +2407,7 @@ locks_remove_flock(struct file *filp)
|
||||
if (filp->f_op->flock)
|
||||
filp->f_op->flock(filp, F_SETLKW, &fl);
|
||||
else
|
||||
flock_lock_file(filp, &fl);
|
||||
flock_lock_inode(inode, &fl);
|
||||
|
||||
if (fl.fl_ops && fl.fl_ops->fl_release_private)
|
||||
fl.fl_ops->fl_release_private(&fl);
|
||||
|
@ -5439,15 +5439,15 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *
|
||||
return err;
|
||||
}
|
||||
|
||||
static int do_vfs_lock(struct file *file, struct file_lock *fl)
|
||||
static int do_vfs_lock(struct inode *inode, struct file_lock *fl)
|
||||
{
|
||||
int res = 0;
|
||||
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
|
||||
case FL_POSIX:
|
||||
res = posix_lock_file_wait(file, fl);
|
||||
res = posix_lock_inode_wait(inode, fl);
|
||||
break;
|
||||
case FL_FLOCK:
|
||||
res = flock_lock_file_wait(file, fl);
|
||||
res = flock_lock_inode_wait(inode, fl);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
@ -5484,7 +5484,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
|
||||
atomic_inc(&lsp->ls_count);
|
||||
/* Ensure we don't close file until we're done freeing locks! */
|
||||
p->ctx = get_nfs_open_context(ctx);
|
||||
get_file(fl->fl_file);
|
||||
memcpy(&p->fl, fl, sizeof(p->fl));
|
||||
p->server = NFS_SERVER(inode);
|
||||
return p;
|
||||
@ -5496,7 +5495,6 @@ static void nfs4_locku_release_calldata(void *data)
|
||||
nfs_free_seqid(calldata->arg.seqid);
|
||||
nfs4_put_lock_state(calldata->lsp);
|
||||
put_nfs_open_context(calldata->ctx);
|
||||
fput(calldata->fl.fl_file);
|
||||
kfree(calldata);
|
||||
}
|
||||
|
||||
@ -5509,7 +5507,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
|
||||
switch (task->tk_status) {
|
||||
case 0:
|
||||
renew_lease(calldata->server, calldata->timestamp);
|
||||
do_vfs_lock(calldata->fl.fl_file, &calldata->fl);
|
||||
do_vfs_lock(calldata->lsp->ls_state->inode, &calldata->fl);
|
||||
if (nfs4_update_lock_stateid(calldata->lsp,
|
||||
&calldata->res.stateid))
|
||||
break;
|
||||
@ -5617,7 +5615,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
|
||||
mutex_lock(&sp->so_delegreturn_mutex);
|
||||
/* Exclude nfs4_reclaim_open_stateid() - note nesting! */
|
||||
down_read(&nfsi->rwsem);
|
||||
if (do_vfs_lock(request->fl_file, request) == -ENOENT) {
|
||||
if (do_vfs_lock(inode, request) == -ENOENT) {
|
||||
up_read(&nfsi->rwsem);
|
||||
mutex_unlock(&sp->so_delegreturn_mutex);
|
||||
goto out;
|
||||
@ -5758,7 +5756,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
|
||||
data->timestamp);
|
||||
if (data->arg.new_lock) {
|
||||
data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
|
||||
if (do_vfs_lock(data->fl.fl_file, &data->fl) < 0) {
|
||||
if (do_vfs_lock(lsp->ls_state->inode, &data->fl) < 0) {
|
||||
rpc_restart_call_prepare(task);
|
||||
break;
|
||||
}
|
||||
@ -6000,7 +5998,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
|
||||
if (status != 0)
|
||||
goto out;
|
||||
request->fl_flags |= FL_ACCESS;
|
||||
status = do_vfs_lock(request->fl_file, request);
|
||||
status = do_vfs_lock(state->inode, request);
|
||||
if (status < 0)
|
||||
goto out;
|
||||
down_read(&nfsi->rwsem);
|
||||
@ -6008,7 +6006,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
|
||||
/* Yes: cache locks! */
|
||||
/* ...but avoid races with delegation recall... */
|
||||
request->fl_flags = fl_flags & ~FL_SLEEP;
|
||||
status = do_vfs_lock(request->fl_file, request);
|
||||
status = do_vfs_lock(state->inode, request);
|
||||
up_read(&nfsi->rwsem);
|
||||
goto out;
|
||||
}
|
||||
|
@ -1046,12 +1046,12 @@ extern void locks_remove_file(struct file *);
|
||||
extern void locks_release_private(struct file_lock *);
|
||||
extern void posix_test_lock(struct file *, struct file_lock *);
|
||||
extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
|
||||
extern int posix_lock_file_wait(struct file *, struct file_lock *);
|
||||
extern int posix_lock_inode_wait(struct inode *, struct file_lock *);
|
||||
extern int posix_unblock_lock(struct file_lock *);
|
||||
extern int vfs_test_lock(struct file *, struct file_lock *);
|
||||
extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
|
||||
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
|
||||
extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
|
||||
extern int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl);
|
||||
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
|
||||
extern void lease_get_mtime(struct inode *, struct timespec *time);
|
||||
extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
|
||||
@ -1137,7 +1137,8 @@ static inline int posix_lock_file(struct file *filp, struct file_lock *fl,
|
||||
return -ENOLCK;
|
||||
}
|
||||
|
||||
static inline int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
static inline int posix_lock_inode_wait(struct inode *inode,
|
||||
struct file_lock *fl)
|
||||
{
|
||||
return -ENOLCK;
|
||||
}
|
||||
@ -1163,8 +1164,8 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int flock_lock_file_wait(struct file *filp,
|
||||
struct file_lock *request)
|
||||
static inline int flock_lock_inode_wait(struct inode *inode,
|
||||
struct file_lock *request)
|
||||
{
|
||||
return -ENOLCK;
|
||||
}
|
||||
@ -1202,6 +1203,20 @@ static inline void show_fd_locks(struct seq_file *f,
|
||||
struct file *filp, struct files_struct *files) {}
|
||||
#endif /* !CONFIG_FILE_LOCKING */
|
||||
|
||||
static inline struct inode *file_inode(const struct file *f)
|
||||
{
|
||||
return f->f_inode;
|
||||
}
|
||||
|
||||
static inline int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
{
|
||||
return posix_lock_inode_wait(file_inode(filp), fl);
|
||||
}
|
||||
|
||||
static inline int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
{
|
||||
return flock_lock_inode_wait(file_inode(filp), fl);
|
||||
}
|
||||
|
||||
struct fasync_struct {
|
||||
spinlock_t fa_lock;
|
||||
@ -2011,11 +2026,6 @@ extern void ihold(struct inode * inode);
|
||||
extern void iput(struct inode *);
|
||||
extern int generic_update_time(struct inode *, struct timespec *, int);
|
||||
|
||||
static inline struct inode *file_inode(const struct file *f)
|
||||
{
|
||||
return f->f_inode;
|
||||
}
|
||||
|
||||
/* /sys/fs */
|
||||
extern struct kobject *fs_kobj;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user