Commit 9576c2f2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'locks-v4.4-1' of git://git.samba.org/jlayton/linux

Pull file locking updates from Jeff Layton:
 "The largest series of changes is from Ben who offered up a set to add
  a new helper function for setting locks based on the type set in
  fl_flags.  Dmitry also send in a fix for a potential race that he
  found with KTSAN"

* tag 'locks-v4.4-1' of git://git.samba.org/jlayton/linux:
  locks: cleanup posix_lock_inode_wait and flock_lock_inode_wait
  Move locks API users to locks_lock_inode_wait()
  locks: introduce locks_lock_inode_wait()
  locks: Use more file_inode and fix a comment
  fs: fix data races on inode->i_flctx
  locks: change tracepoint for generic_add_lease
parents 8e483ed1 616fb38f
...@@ -2750,13 +2750,9 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) ...@@ -2750,13 +2750,9 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL,
op_data, &lockh, &flock, 0, NULL /* req */, flags); op_data, &lockh, &flock, 0, NULL /* req */, flags);
if ((file_lock->fl_flags & FL_FLOCK) && if ((rc == 0 || file_lock->fl_type == F_UNLCK) &&
(rc == 0 || file_lock->fl_type == F_UNLCK))
rc2 = flock_lock_file_wait(file, file_lock);
if ((file_lock->fl_flags & FL_POSIX) &&
(rc == 0 || file_lock->fl_type == F_UNLCK) &&
!(flags & LDLM_FL_TEST_LOCK)) !(flags & LDLM_FL_TEST_LOCK))
rc2 = posix_lock_file_wait(file, file_lock); rc2 = locks_lock_file_wait(file, file_lock);
if (rc2 && file_lock->fl_type != F_UNLCK) { if (rc2 && file_lock->fl_type != F_UNLCK) {
einfo.ei_mode = LCK_NL; einfo.ei_mode = LCK_NL;
......
...@@ -161,7 +161,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) ...@@ -161,7 +161,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
if ((fl->fl_flags & FL_POSIX) != FL_POSIX) if ((fl->fl_flags & FL_POSIX) != FL_POSIX)
BUG(); BUG();
res = posix_lock_file_wait(filp, fl); res = locks_lock_file_wait(filp, fl);
if (res < 0) if (res < 0)
goto out; goto out;
...@@ -231,7 +231,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) ...@@ -231,7 +231,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
if (res < 0 && fl->fl_type != F_UNLCK) { if (res < 0 && fl->fl_type != F_UNLCK) {
fl_type = fl->fl_type; fl_type = fl->fl_type;
fl->fl_type = F_UNLCK; fl->fl_type = F_UNLCK;
res = posix_lock_file_wait(filp, fl); res = locks_lock_file_wait(filp, fl);
fl->fl_type = fl_type; fl->fl_type = fl_type;
} }
out: out:
......
...@@ -228,12 +228,12 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -228,12 +228,12 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
file, lock_cmd, wait, fl); file, lock_cmd, wait, fl);
if (!err) { if (!err) {
err = flock_lock_file_wait(file, fl); err = locks_lock_file_wait(file, fl);
if (err) { if (err) {
ceph_lock_message(CEPH_LOCK_FLOCK, ceph_lock_message(CEPH_LOCK_FLOCK,
CEPH_MDS_OP_SETFILELOCK, CEPH_MDS_OP_SETFILELOCK,
file, CEPH_LOCK_UNLOCK, 0, fl); file, CEPH_LOCK_UNLOCK, 0, fl);
dout("got %d on flock_lock_file_wait, undid lock", err); dout("got %d on locks_lock_file_wait, undid lock", err);
} }
} }
return err; return err;
......
...@@ -1553,7 +1553,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, ...@@ -1553,7 +1553,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
out: out:
if (flock->fl_flags & FL_POSIX && !rc) if (flock->fl_flags & FL_POSIX && !rc)
rc = posix_lock_file_wait(file, flock); rc = locks_lock_file_wait(file, flock);
return rc; return rc;
} }
......
...@@ -172,7 +172,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, ...@@ -172,7 +172,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
rv = op->info.rv; rv = op->info.rv;
if (!rv) { if (!rv) {
if (posix_lock_file_wait(file, fl) < 0) if (locks_lock_file_wait(file, fl) < 0)
log_error(ls, "dlm_posix_lock: vfs lock error %llx", log_error(ls, "dlm_posix_lock: vfs lock error %llx",
(unsigned long long)number); (unsigned long long)number);
} }
...@@ -262,7 +262,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, ...@@ -262,7 +262,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
/* cause the vfs unlock to return ENOENT if lock is not found */ /* cause the vfs unlock to return ENOENT if lock is not found */
fl->fl_flags |= FL_EXISTS; fl->fl_flags |= FL_EXISTS;
rv = posix_lock_file_wait(file, fl); rv = locks_lock_file_wait(file, fl);
if (rv == -ENOENT) { if (rv == -ENOENT) {
rv = 0; rv = 0;
goto out_free; goto out_free;
......
...@@ -2189,7 +2189,7 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -2189,7 +2189,7 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
int err; int err;
if (fc->no_flock) { if (fc->no_flock) {
err = flock_lock_file_wait(file, fl); err = locks_lock_file_wait(file, fl);
} else { } else {
struct fuse_file *ff = file->private_data; struct fuse_file *ff = file->private_data;
......
...@@ -1000,7 +1000,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) ...@@ -1000,7 +1000,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
} }
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) { if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
if (fl->fl_type == F_UNLCK) if (fl->fl_type == F_UNLCK)
posix_lock_file_wait(file, fl); locks_lock_file_wait(file, fl);
return -EIO; return -EIO;
} }
if (IS_GETLK(cmd)) if (IS_GETLK(cmd))
...@@ -1031,7 +1031,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -1031,7 +1031,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
if (gl) { if (gl) {
if (fl_gh->gh_state == state) if (fl_gh->gh_state == state)
goto out; goto out;
flock_lock_file_wait(file, locks_lock_file_wait(file,
&(struct file_lock){.fl_type = F_UNLCK}); &(struct file_lock){.fl_type = F_UNLCK});
gfs2_glock_dq(fl_gh); gfs2_glock_dq(fl_gh);
gfs2_holder_reinit(state, flags, fl_gh); gfs2_holder_reinit(state, flags, fl_gh);
...@@ -1056,7 +1056,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -1056,7 +1056,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
if (error == GLR_TRYFAILED) if (error == GLR_TRYFAILED)
error = -EAGAIN; error = -EAGAIN;
} else { } else {
error = flock_lock_file_wait(file, fl); error = locks_lock_file_wait(file, fl);
gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
} }
...@@ -1071,7 +1071,7 @@ static void do_unflock(struct file *file, struct file_lock *fl) ...@@ -1071,7 +1071,7 @@ static void do_unflock(struct file *file, struct file_lock *fl)
struct gfs2_holder *fl_gh = &fp->f_fl_gh; struct gfs2_holder *fl_gh = &fp->f_fl_gh;
mutex_lock(&fp->f_fl_mutex); mutex_lock(&fp->f_fl_mutex);
flock_lock_file_wait(file, fl); locks_lock_file_wait(file, fl);
if (fl_gh->gh_gl) { if (fl_gh->gh_gl) {
gfs2_glock_dq(fl_gh); gfs2_glock_dq(fl_gh);
gfs2_holder_uninit(fl_gh); gfs2_holder_uninit(fl_gh);
......
...@@ -474,18 +474,7 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho ...@@ -474,18 +474,7 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
static int do_vfs_lock(struct file_lock *fl) static int do_vfs_lock(struct file_lock *fl)
{ {
int res = 0; return locks_lock_file_wait(fl->fl_file, fl);
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
case FL_POSIX:
res = posix_lock_file_wait(fl->fl_file, fl);
break;
case FL_FLOCK:
res = flock_lock_file_wait(fl->fl_file, fl);
break;
default:
BUG();
}
return res;
} }
/* /*
......
...@@ -205,28 +205,32 @@ static struct kmem_cache *filelock_cache __read_mostly; ...@@ -205,28 +205,32 @@ static struct kmem_cache *filelock_cache __read_mostly;
static struct file_lock_context * static struct file_lock_context *
locks_get_lock_context(struct inode *inode, int type) locks_get_lock_context(struct inode *inode, int type)
{ {
struct file_lock_context *new; struct file_lock_context *ctx;
if (likely(inode->i_flctx) || type == F_UNLCK) /* paired with cmpxchg() below */
ctx = smp_load_acquire(&inode->i_flctx);
if (likely(ctx) || type == F_UNLCK)
goto out; goto out;
new = kmem_cache_alloc(flctx_cache, GFP_KERNEL); ctx = kmem_cache_alloc(flctx_cache, GFP_KERNEL);
if (!new) if (!ctx)
goto out; goto out;
spin_lock_init(&new->flc_lock); spin_lock_init(&ctx->flc_lock);
INIT_LIST_HEAD(&new->flc_flock); INIT_LIST_HEAD(&ctx->flc_flock);
INIT_LIST_HEAD(&new->flc_posix); INIT_LIST_HEAD(&ctx->flc_posix);
INIT_LIST_HEAD(&new->flc_lease); INIT_LIST_HEAD(&ctx->flc_lease);
/* /*
* Assign the pointer if it's not already assigned. If it is, then * Assign the pointer if it's not already assigned. If it is, then
* free the context we just allocated. * free the context we just allocated.
*/ */
if (cmpxchg(&inode->i_flctx, NULL, new)) if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
kmem_cache_free(flctx_cache, new); kmem_cache_free(flctx_cache, ctx);
ctx = smp_load_acquire(&inode->i_flctx);
}
out: out:
return inode->i_flctx; return ctx;
} }
void void
...@@ -762,7 +766,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl) ...@@ -762,7 +766,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
struct file_lock_context *ctx; struct file_lock_context *ctx;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
ctx = inode->i_flctx; ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx || list_empty_careful(&ctx->flc_posix)) { if (!ctx || list_empty_careful(&ctx->flc_posix)) {
fl->fl_type = F_UNLCK; fl->fl_type = F_UNLCK;
return; return;
...@@ -1167,10 +1171,9 @@ EXPORT_SYMBOL(posix_lock_file); ...@@ -1167,10 +1171,9 @@ EXPORT_SYMBOL(posix_lock_file);
* @inode: inode of file to which lock request should be applied * @inode: inode of file to which lock request should be applied
* @fl: The lock to be applied * @fl: The lock to be applied
* *
* Variant of posix_lock_file_wait that does not take a filp, and so can be * Apply a POSIX style lock request to an inode.
* used after the filp has already been torn down.
*/ */
int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl) static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
{ {
int error; int error;
might_sleep (); might_sleep ();
...@@ -1187,7 +1190,6 @@ int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl) ...@@ -1187,7 +1190,6 @@ int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
} }
return error; return error;
} }
EXPORT_SYMBOL(posix_lock_inode_wait);
/** /**
* locks_mandatory_locked - Check for an active lock * locks_mandatory_locked - Check for an active lock
...@@ -1203,7 +1205,7 @@ int locks_mandatory_locked(struct file *file) ...@@ -1203,7 +1205,7 @@ int locks_mandatory_locked(struct file *file)
struct file_lock_context *ctx; struct file_lock_context *ctx;
struct file_lock *fl; struct file_lock *fl;
ctx = inode->i_flctx; ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx || list_empty_careful(&ctx->flc_posix)) if (!ctx || list_empty_careful(&ctx->flc_posix))
return 0; return 0;
...@@ -1388,7 +1390,7 @@ any_leases_conflict(struct inode *inode, struct file_lock *breaker) ...@@ -1388,7 +1390,7 @@ any_leases_conflict(struct inode *inode, struct file_lock *breaker)
int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
{ {
int error = 0; int error = 0;
struct file_lock_context *ctx = inode->i_flctx; struct file_lock_context *ctx;
struct file_lock *new_fl, *fl, *tmp; struct file_lock *new_fl, *fl, *tmp;
unsigned long break_time; unsigned long break_time;
int want_write = (mode & O_ACCMODE) != O_RDONLY; int want_write = (mode & O_ACCMODE) != O_RDONLY;
...@@ -1400,6 +1402,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) ...@@ -1400,6 +1402,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
new_fl->fl_flags = type; new_fl->fl_flags = type;
/* typically we will check that ctx is non-NULL before calling */ /* typically we will check that ctx is non-NULL before calling */
ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx) { if (!ctx) {
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return error; return error;
...@@ -1494,9 +1497,10 @@ EXPORT_SYMBOL(__break_lease); ...@@ -1494,9 +1497,10 @@ EXPORT_SYMBOL(__break_lease);
void lease_get_mtime(struct inode *inode, struct timespec *time) void lease_get_mtime(struct inode *inode, struct timespec *time)
{ {
bool has_lease = false; bool has_lease = false;
struct file_lock_context *ctx = inode->i_flctx; struct file_lock_context *ctx;
struct file_lock *fl; struct file_lock *fl;
ctx = smp_load_acquire(&inode->i_flctx);
if (ctx && !list_empty_careful(&ctx->flc_lease)) { if (ctx && !list_empty_careful(&ctx->flc_lease)) {
spin_lock(&ctx->flc_lock); spin_lock(&ctx->flc_lock);
if (!list_empty(&ctx->flc_lease)) { if (!list_empty(&ctx->flc_lease)) {
...@@ -1543,10 +1547,11 @@ int fcntl_getlease(struct file *filp) ...@@ -1543,10 +1547,11 @@ int fcntl_getlease(struct file *filp)
{ {
struct file_lock *fl; struct file_lock *fl;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
struct file_lock_context *ctx = inode->i_flctx; struct file_lock_context *ctx;
int type = F_UNLCK; int type = F_UNLCK;
LIST_HEAD(dispose); LIST_HEAD(dispose);
ctx = smp_load_acquire(&inode->i_flctx);
if (ctx && !list_empty_careful(&ctx->flc_lease)) { if (ctx && !list_empty_careful(&ctx->flc_lease)) {
spin_lock(&ctx->flc_lock); spin_lock(&ctx->flc_lock);
time_out_leases(file_inode(filp), &dispose); time_out_leases(file_inode(filp), &dispose);
...@@ -1711,11 +1716,11 @@ static int generic_delete_lease(struct file *filp, void *owner) ...@@ -1711,11 +1716,11 @@ static int generic_delete_lease(struct file *filp, void *owner)
{ {
int error = -EAGAIN; int error = -EAGAIN;
struct file_lock *fl, *victim = NULL; struct file_lock *fl, *victim = NULL;
struct dentry *dentry = filp->f_path.dentry; struct inode *inode = file_inode(filp);
struct inode *inode = dentry->d_inode; struct file_lock_context *ctx;
struct file_lock_context *ctx = inode->i_flctx;
LIST_HEAD(dispose); LIST_HEAD(dispose);
ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx) { if (!ctx) {
trace_generic_delete_lease(inode, NULL); trace_generic_delete_lease(inode, NULL);
return error; return error;
...@@ -1751,8 +1756,7 @@ static int generic_delete_lease(struct file *filp, void *owner) ...@@ -1751,8 +1756,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
int generic_setlease(struct file *filp, long arg, struct file_lock **flp, int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
void **priv) void **priv)
{ {
struct dentry *dentry = filp->f_path.dentry; struct inode *inode = file_inode(filp);
struct inode *inode = dentry->d_inode;
int error; int error;
if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE)) if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
...@@ -1856,7 +1860,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) ...@@ -1856,7 +1860,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
* *
* Apply a FLOCK style lock request to an inode. * Apply a FLOCK style lock request to an inode.
*/ */
int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl) static int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)
{ {
int error; int error;
might_sleep(); might_sleep();
...@@ -1873,7 +1877,30 @@ int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl) ...@@ -1873,7 +1877,30 @@ int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)
} }
return error; return error;
} }
EXPORT_SYMBOL(flock_lock_inode_wait);
/**
* locks_lock_inode_wait - Apply a lock to an inode
* @inode: inode of the file to apply to
* @fl: The lock to be applied
*
* Apply a POSIX or FLOCK style lock request to an inode.
*/
int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
{
int res = 0;
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
case FL_POSIX:
res = posix_lock_inode_wait(inode, fl);
break;
case FL_FLOCK:
res = flock_lock_inode_wait(inode, fl);
break;
default:
BUG();
}
return res;
}
EXPORT_SYMBOL(locks_lock_inode_wait);
/** /**
* sys_flock: - flock() system call. * sys_flock: - flock() system call.
...@@ -1931,7 +1958,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) ...@@ -1931,7 +1958,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
(can_sleep) ? F_SETLKW : F_SETLK, (can_sleep) ? F_SETLKW : F_SETLK,
lock); lock);
else else
error = flock_lock_file_wait(f.file, lock); error = locks_lock_file_wait(f.file, lock);
out_free: out_free:
locks_free_lock(lock); locks_free_lock(lock);
...@@ -2107,7 +2134,7 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd, ...@@ -2107,7 +2134,7 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd,
return error; return error;
} }
/* Ensure that fl->fl_filp has compatible f_mode for F_SETLK calls */ /* Ensure that fl->fl_file has compatible f_mode for F_SETLK calls */
static int static int
check_fmode_for_setlk(struct file_lock *fl) check_fmode_for_setlk(struct file_lock *fl)
{ {
...@@ -2359,13 +2386,14 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, ...@@ -2359,13 +2386,14 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
void locks_remove_posix(struct file *filp, fl_owner_t owner) void locks_remove_posix(struct file *filp, fl_owner_t owner)
{ {
struct file_lock lock; struct file_lock lock;
struct file_lock_context *ctx = file_inode(filp)->i_flctx; struct file_lock_context *ctx;
/* /*
* If there are no locks held on this file, we don't need to call * If there are no locks held on this file, we don't need to call
* posix_lock_file(). Another process could be setting a lock on this * posix_lock_file(). Another process could be setting a lock on this
* file at the same time, but we wouldn't remove that lock anyway. * file at the same time, but we wouldn't remove that lock anyway.
*/ */
ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
if (!ctx || list_empty(&ctx->flc_posix)) if (!ctx || list_empty(&ctx->flc_posix))
return; return;
...@@ -2389,7 +2417,7 @@ EXPORT_SYMBOL(locks_remove_posix); ...@@ -2389,7 +2417,7 @@ EXPORT_SYMBOL(locks_remove_posix);
/* The i_flctx must be valid when calling into here */ /* The i_flctx must be valid when calling into here */
static void static void
locks_remove_flock(struct file *filp) locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
{ {
struct file_lock fl = { struct file_lock fl = {
.fl_owner = filp, .fl_owner = filp,
...@@ -2400,7 +2428,6 @@ locks_remove_flock(struct file *filp) ...@@ -2400,7 +2428,6 @@ locks_remove_flock(struct file *filp)
.fl_end = OFFSET_MAX, .fl_end = OFFSET_MAX,
}; };
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
struct file_lock_context *flctx = inode->i_flctx;
if (list_empty(&flctx->flc_flock)) if (list_empty(&flctx->flc_flock))
return; return;
...@@ -2416,10 +2443,8 @@ locks_remove_flock(struct file *filp) ...@@ -2416,10 +2443,8 @@ locks_remove_flock(struct file *filp)
/* The i_flctx must be valid when calling into here */ /* The i_flctx must be valid when calling into here */
static void static void
locks_remove_lease(struct file *filp) locks_remove_lease(struct file *filp, struct file_lock_context *ctx)
{ {
struct inode *inode = file_inode(filp);
struct file_lock_context *ctx = inode->i_flctx;
struct file_lock *fl, *tmp; struct file_lock *fl, *tmp;
LIST_HEAD(dispose); LIST_HEAD(dispose);
...@@ -2439,17 +2464,20 @@ locks_remove_lease(struct file *filp) ...@@ -2439,17 +2464,20 @@ locks_remove_lease(struct file *filp)
*/ */
void locks_remove_file(struct file *filp) void locks_remove_file(struct file *filp)
{ {
if (!file_inode(filp)->i_flctx) struct file_lock_context *ctx;
ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
if (!ctx)
return; return;
/* remove any OFD locks */ /* remove any OFD locks */
locks_remove_posix(filp, filp); locks_remove_posix(filp, filp);
/* remove flock locks */ /* remove flock locks */
locks_remove_flock(filp); locks_remove_flock(filp, ctx);
/* remove any leases */ /* remove any leases */
locks_remove_lease(filp); locks_remove_lease(filp, ctx);
} }
/** /**
...@@ -2616,7 +2644,7 @@ void show_fd_locks(struct seq_file *f, ...@@ -2616,7 +2644,7 @@ void show_fd_locks(struct seq_file *f,
struct file_lock_context *ctx; struct file_lock_context *ctx;
int id = 0; int id = 0;
ctx = inode->i_flctx; ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx) if (!ctx)
return; return;
......
...@@ -738,18 +738,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) ...@@ -738,18 +738,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
static int do_vfs_lock(struct file *file, struct file_lock *fl) static int do_vfs_lock(struct file *file, struct file_lock *fl)
{ {
int res = 0; return locks_lock_file_wait(file, fl);
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
case FL_POSIX:
res = posix_lock_file_wait(file, fl);
break;
case FL_FLOCK:
res = flock_lock_file_wait(file, fl);
break;
default:
BUG();
}
return res;
} }
static int static int
......
...@@ -5513,18 +5513,7 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock * ...@@ -5513,18 +5513,7 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *
static int do_vfs_lock(struct inode *inode, struct file_lock *fl) static int do_vfs_lock(struct inode *inode, struct file_lock *fl)
{ {
int res = 0; return locks_lock_inode_wait(inode, fl);
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
case FL_POSIX:
res = posix_lock_inode_wait(inode, fl);
break;
case FL_FLOCK:
res = flock_lock_inode_wait(inode, fl);
break;
default:
BUG();
}
return res;
} }
struct nfs4_unlockdata { struct nfs4_unlockdata {
......
...@@ -66,7 +66,7 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode, ...@@ -66,7 +66,7 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode,
* level. * level.
*/ */
flock_lock_file_wait(file, locks_lock_file_wait(file,
&(struct file_lock){.fl_type = F_UNLCK}); &(struct file_lock){.fl_type = F_UNLCK});
ocfs2_file_unlock(file); ocfs2_file_unlock(file);
...@@ -81,7 +81,7 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode, ...@@ -81,7 +81,7 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode,
goto out; goto out;
} }
ret = flock_lock_file_wait(file, fl); ret = locks_lock_file_wait(file, fl);
if (ret) if (ret)
ocfs2_file_unlock(file); ocfs2_file_unlock(file);
...@@ -98,7 +98,7 @@ static int ocfs2_do_funlock(struct file *file, int cmd, struct file_lock *fl) ...@@ -98,7 +98,7 @@ static int ocfs2_do_funlock(struct file *file, int cmd, struct file_lock *fl)
mutex_lock(&fp->fp_mutex); mutex_lock(&fp->fp_mutex);
ocfs2_file_unlock(file); ocfs2_file_unlock(file);
ret = flock_lock_file_wait(file, fl); ret = locks_lock_file_wait(file, fl);
mutex_unlock(&fp->fp_mutex); mutex_unlock(&fp->fp_mutex);
return ret; return ret;
...@@ -119,7 +119,7 @@ int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -119,7 +119,7 @@ int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl)
if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) || if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
ocfs2_mount_local(osb)) ocfs2_mount_local(osb))
return flock_lock_file_wait(file, fl); return locks_lock_file_wait(file, fl);
if (fl->fl_type == F_UNLCK) if (fl->fl_type == F_UNLCK)
return ocfs2_do_funlock(file, cmd, fl); return ocfs2_do_funlock(file, cmd, fl);
......
...@@ -1053,12 +1053,11 @@ extern void locks_remove_file(struct file *); ...@@ -1053,12 +1053,11 @@ extern void locks_remove_file(struct file *);
extern void locks_release_private(struct file_lock *); extern void locks_release_private(struct file_lock *);
extern void posix_test_lock(struct file *, 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(struct file *, struct file_lock *, struct file_lock *);
extern int posix_lock_inode_wait(struct inode *, struct file_lock *);
extern int posix_unblock_lock(struct file_lock *); extern int posix_unblock_lock(struct file_lock *);
extern int vfs_test_lock(struct file *, 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_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 vfs_cancel_lock(struct file *filp, struct file_lock *fl);
extern int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl); extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type); extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
extern void lease_get_mtime(struct inode *, struct timespec *time); extern void lease_get_mtime(struct inode *, struct timespec *time);
extern int generic_setlease(struct file *, long, struct file_lock **, void **priv); extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
...@@ -1144,12 +1143,6 @@ static inline int posix_lock_file(struct file *filp, struct file_lock *fl, ...@@ -1144,12 +1143,6 @@ static inline int posix_lock_file(struct file *filp, struct file_lock *fl,
return -ENOLCK; return -ENOLCK;
} }
static inline int posix_lock_inode_wait(struct inode *inode,
struct file_lock *fl)
{
return -ENOLCK;
}
static inline int posix_unblock_lock(struct file_lock *waiter) static inline int posix_unblock_lock(struct file_lock *waiter)
{ {
return -ENOENT; return -ENOENT;
...@@ -1171,8 +1164,7 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl) ...@@ -1171,8 +1164,7 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
return 0; return 0;
} }
static inline int flock_lock_inode_wait(struct inode *inode, static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
struct file_lock *request)
{ {
return -ENOLCK; return -ENOLCK;
} }
...@@ -1215,14 +1207,9 @@ static inline struct inode *file_inode(const struct file *f) ...@@ -1215,14 +1207,9 @@ static inline struct inode *file_inode(const struct file *f)
return f->f_inode; return f->f_inode;
} }
static inline int posix_lock_file_wait(struct file *filp, struct file_lock *fl) static inline int locks_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); return locks_lock_inode_wait(file_inode(filp), fl);
} }
struct fasync_struct { struct fasync_struct {
......
...@@ -81,15 +81,47 @@ DEFINE_EVENT(filelock_lease, break_lease_block, TP_PROTO(struct inode *inode, st ...@@ -81,15 +81,47 @@ DEFINE_EVENT(filelock_lease, break_lease_block, TP_PROTO(struct inode *inode, st
DEFINE_EVENT(filelock_lease, break_lease_unblock, TP_PROTO(struct inode *inode, struct file_lock *fl), DEFINE_EVENT(filelock_lease, break_lease_unblock, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl)); TP_ARGS(inode, fl));
DEFINE_EVENT(filelock_lease, generic_add_lease, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl));
DEFINE_EVENT(filelock_lease, generic_delete_lease, TP_PROTO(struct inode *inode, struct file_lock *fl), DEFINE_EVENT(filelock_lease, generic_delete_lease, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl)); TP_ARGS(inode, fl));
DEFINE_EVENT(filelock_lease, time_out_leases, TP_PROTO(struct inode *inode, struct file_lock *fl), DEFINE_EVENT(filelock_lease, time_out_leases, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl)); TP_ARGS(inode, fl));
TRACE_EVENT(generic_add_lease,
TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl),
TP_STRUCT__entry(
__field(unsigned long, i_ino)
__field(int, wcount)
__field(int, dcount)
__field(int, icount)
__field(dev_t, s_dev)
__field(fl_owner_t, fl_owner)
__field(unsigned int, fl_flags)
__field(unsigned char, fl_type)
),
TP_fast_assign(
__entry->s_dev = inode->i_sb->s_dev;
__entry->i_ino = inode->i_ino;
__entry->wcount = atomic_read(&inode->i_writecount);
__entry->dcount = d_count(fl->fl_file->f_path.dentry);
__entry->icount = atomic_read(&inode->i_count);
__entry->fl_owner = fl ? fl->fl_owner : NULL;
__entry->fl_flags = fl ? fl->fl_flags : 0;
__entry->fl_type = fl ? fl->fl_type : 0;
),
TP_printk("dev=0x%x:0x%x ino=0x%lx wcount=%d dcount=%d icount=%d fl_owner=0x%p fl_flags=%s fl_type=%s",
MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
__entry->i_ino, __entry->wcount, __entry->dcount,
__entry->icount, __entry->fl_owner,
show_fl_flags(__entry->fl_flags),
show_fl_type(__entry->fl_type))
);
#endif /* _TRACE_FILELOCK_H */ #endif /* _TRACE_FILELOCK_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment