Commit 74efa045 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'locks-v3.16' of git://git.samba.org/jlayton/linux into next

Pull file locking changes from Jeff Layton:
 "Pretty quiet on the file-locking related front this cycle.  Just some
  small cleanups and the addition of some tracepoints in the lease
  handling code"

* tag 'locks-v3.16' of git://git.samba.org/jlayton/linux:
  locks: add some tracepoints in the lease handling code
  fs/locks.c: replace seq_printf by seq_puts
  locks: ensure that fl_owner is always initialized properly in flock and lease codepaths
parents 1b363609 62af4f1f
...@@ -2706,20 +2706,15 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) ...@@ -2706,20 +2706,15 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FLOCK, 1); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FLOCK, 1);
if (file_lock->fl_flags & FL_FLOCK) { if (file_lock->fl_flags & FL_FLOCK)
LASSERT((cmd == F_SETLKW) || (cmd == F_SETLK)); LASSERT((cmd == F_SETLKW) || (cmd == F_SETLK));
/* flocks are whole-file locks */ else if (!(file_lock->fl_flags & FL_POSIX))
flock.l_flock.end = OFFSET_MAX;
/* For flocks owner is determined by the local file descriptor*/
flock.l_flock.owner = (unsigned long)file_lock->fl_file;
} else if (file_lock->fl_flags & FL_POSIX) {
flock.l_flock.owner = (unsigned long)file_lock->fl_owner;
flock.l_flock.start = file_lock->fl_start;
flock.l_flock.end = file_lock->fl_end;
} else {
return -EINVAL; return -EINVAL;
}
flock.l_flock.owner = (unsigned long)file_lock->fl_owner;
flock.l_flock.pid = file_lock->fl_pid; flock.l_flock.pid = file_lock->fl_pid;
flock.l_flock.start = file_lock->fl_start;
flock.l_flock.end = file_lock->fl_end;
/* Somewhat ugly workaround for svc lockd. /* Somewhat ugly workaround for svc lockd.
* lockd installs custom fl_lmops->lm_compare_owner that checks * lockd installs custom fl_lmops->lm_compare_owner that checks
......
...@@ -352,9 +352,6 @@ static int v9fs_file_flock_dotl(struct file *filp, int cmd, ...@@ -352,9 +352,6 @@ static int v9fs_file_flock_dotl(struct file *filp, int cmd,
invalidate_mapping_pages(&inode->i_data, 0, -1); invalidate_mapping_pages(&inode->i_data, 0, -1);
} }
/* Convert flock to posix lock */ /* Convert flock to posix lock */
fl->fl_owner = (fl_owner_t)filp;
fl->fl_start = 0;
fl->fl_end = OFFSET_MAX;
fl->fl_flags |= FL_POSIX; fl->fl_flags |= FL_POSIX;
fl->fl_flags ^= FL_FLOCK; fl->fl_flags ^= FL_FLOCK;
......
...@@ -555,10 +555,6 @@ int afs_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -555,10 +555,6 @@ int afs_flock(struct file *file, int cmd, struct file_lock *fl)
return -ENOLCK; return -ENOLCK;
/* we're simulating flock() locks using posix locks on the server */ /* we're simulating flock() locks using posix locks on the server */
fl->fl_owner = (fl_owner_t) file;
fl->fl_start = 0;
fl->fl_end = OFFSET_MAX;
if (fl->fl_type == F_UNLCK) if (fl->fl_type == F_UNLCK)
return afs_do_unlk(file, fl); return afs_do_unlk(file, fl);
return afs_do_setlk(file, fl); return afs_do_setlk(file, fl);
......
...@@ -53,10 +53,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, ...@@ -53,10 +53,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
else else
length = fl->fl_end - fl->fl_start + 1; length = fl->fl_end - fl->fl_start + 1;
if (lock_type == CEPH_LOCK_FCNTL) owner = secure_addr(fl->fl_owner);
owner = secure_addr(fl->fl_owner);
else
owner = secure_addr(fl->fl_file);
dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, " dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, "
"start: %llu, length: %llu, wait: %d, type: %d", (int)lock_type, "start: %llu, length: %llu, wait: %d, type: %d", (int)lock_type,
...@@ -314,10 +311,7 @@ int lock_to_ceph_filelock(struct file_lock *lock, ...@@ -314,10 +311,7 @@ int lock_to_ceph_filelock(struct file_lock *lock,
cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1); cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1);
cephlock->client = cpu_to_le64(0); cephlock->client = cpu_to_le64(0);
cephlock->pid = cpu_to_le64((u64)lock->fl_pid); cephlock->pid = cpu_to_le64((u64)lock->fl_pid);
if (lock->fl_flags & FL_POSIX) cephlock->owner = cpu_to_le64(secure_addr(lock->fl_owner));
cephlock->owner = cpu_to_le64(secure_addr(lock->fl_owner));
else
cephlock->owner = cpu_to_le64(secure_addr(lock->fl_file));
switch (lock->fl_type) { switch (lock->fl_type) {
case F_RDLCK: case F_RDLCK:
......
...@@ -2304,7 +2304,6 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -2304,7 +2304,6 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
struct fuse_file *ff = file->private_data; struct fuse_file *ff = file->private_data;
/* emulate flock with POSIX locks */ /* emulate flock with POSIX locks */
fl->fl_owner = (fl_owner_t) file;
ff->flock = true; ff->flock = true;
err = fuse_setlk(file, fl, 1); err = fuse_setlk(file, fl, 1);
} }
......
...@@ -130,6 +130,9 @@ ...@@ -130,6 +130,9 @@
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/lglock.h> #include <linux/lglock.h>
#define CREATE_TRACE_POINTS
#include <trace/events/filelock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX)
...@@ -322,6 +325,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock, ...@@ -322,6 +325,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
return -ENOMEM; return -ENOMEM;
fl->fl_file = filp; fl->fl_file = filp;
fl->fl_owner = (fl_owner_t)filp;
fl->fl_pid = current->tgid; fl->fl_pid = current->tgid;
fl->fl_flags = FL_FLOCK; fl->fl_flags = FL_FLOCK;
fl->fl_type = type; fl->fl_type = type;
...@@ -427,7 +431,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl) ...@@ -427,7 +431,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl)
if (assign_type(fl, type) != 0) if (assign_type(fl, type) != 0)
return -EINVAL; return -EINVAL;
fl->fl_owner = current->files; fl->fl_owner = (fl_owner_t)filp;
fl->fl_pid = current->tgid; fl->fl_pid = current->tgid;
fl->fl_file = filp; fl->fl_file = filp;
...@@ -1286,6 +1290,7 @@ static void time_out_leases(struct inode *inode) ...@@ -1286,6 +1290,7 @@ static void time_out_leases(struct inode *inode)
before = &inode->i_flock; before = &inode->i_flock;
while ((fl = *before) && IS_LEASE(fl) && lease_breaking(fl)) { while ((fl = *before) && IS_LEASE(fl) && lease_breaking(fl)) {
trace_time_out_leases(inode, fl);
if (past_time(fl->fl_downgrade_time)) if (past_time(fl->fl_downgrade_time))
lease_modify(before, F_RDLCK); lease_modify(before, F_RDLCK);
if (past_time(fl->fl_break_time)) if (past_time(fl->fl_break_time))
...@@ -1373,6 +1378,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) ...@@ -1373,6 +1378,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
} }
if (i_have_this_lease || (mode & O_NONBLOCK)) { if (i_have_this_lease || (mode & O_NONBLOCK)) {
trace_break_lease_noblock(inode, new_fl);
error = -EWOULDBLOCK; error = -EWOULDBLOCK;
goto out; goto out;
} }
...@@ -1384,10 +1390,12 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) ...@@ -1384,10 +1390,12 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
if (break_time == 0) if (break_time == 0)
break_time++; break_time++;
locks_insert_block(flock, new_fl); locks_insert_block(flock, new_fl);
trace_break_lease_block(inode, new_fl);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
error = wait_event_interruptible_timeout(new_fl->fl_wait, error = wait_event_interruptible_timeout(new_fl->fl_wait,
!new_fl->fl_next, break_time); !new_fl->fl_next, break_time);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
trace_break_lease_unblock(inode, new_fl);
locks_delete_block(new_fl); locks_delete_block(new_fl);
if (error >= 0) { if (error >= 0) {
if (error == 0) if (error == 0)
...@@ -1509,6 +1517,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp ...@@ -1509,6 +1517,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
int error; int error;
lease = *flp; lease = *flp;
trace_generic_add_lease(inode, lease);
/* /*
* In the delegation case we need mutual exclusion with * In the delegation case we need mutual exclusion with
* a number of operations that take the i_mutex. We trylock * a number of operations that take the i_mutex. We trylock
...@@ -1598,6 +1608,8 @@ static int generic_delete_lease(struct file *filp, struct file_lock **flp) ...@@ -1598,6 +1608,8 @@ static int generic_delete_lease(struct file *filp, struct file_lock **flp)
struct dentry *dentry = filp->f_path.dentry; struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
trace_generic_delete_lease(inode, *flp);
for (before = &inode->i_flock; for (before = &inode->i_flock;
((fl = *before) != NULL) && IS_LEASE(fl); ((fl = *before) != NULL) && IS_LEASE(fl);
before = &fl->fl_next) { before = &fl->fl_next) {
...@@ -2316,6 +2328,7 @@ void locks_remove_file(struct file *filp) ...@@ -2316,6 +2328,7 @@ void locks_remove_file(struct file *filp)
if (filp->f_op->flock) { if (filp->f_op->flock) {
struct file_lock fl = { struct file_lock fl = {
.fl_owner = (fl_owner_t)filp,
.fl_pid = current->tgid, .fl_pid = current->tgid,
.fl_file = filp, .fl_file = filp,
.fl_flags = FL_FLOCK, .fl_flags = FL_FLOCK,
...@@ -2423,31 +2436,31 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, ...@@ -2423,31 +2436,31 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
seq_printf(f, "%lld:%s ", id, pfx); seq_printf(f, "%lld:%s ", id, pfx);
if (IS_POSIX(fl)) { if (IS_POSIX(fl)) {
if (fl->fl_flags & FL_ACCESS) if (fl->fl_flags & FL_ACCESS)
seq_printf(f, "ACCESS"); seq_puts(f, "ACCESS");
else if (IS_OFDLCK(fl)) else if (IS_OFDLCK(fl))
seq_printf(f, "OFDLCK"); seq_puts(f, "OFDLCK");
else else
seq_printf(f, "POSIX "); seq_puts(f, "POSIX ");
seq_printf(f, " %s ", seq_printf(f, " %s ",
(inode == NULL) ? "*NOINODE*" : (inode == NULL) ? "*NOINODE*" :
mandatory_lock(inode) ? "MANDATORY" : "ADVISORY "); mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
} else if (IS_FLOCK(fl)) { } else if (IS_FLOCK(fl)) {
if (fl->fl_type & LOCK_MAND) { if (fl->fl_type & LOCK_MAND) {
seq_printf(f, "FLOCK MSNFS "); seq_puts(f, "FLOCK MSNFS ");
} else { } else {
seq_printf(f, "FLOCK ADVISORY "); seq_puts(f, "FLOCK ADVISORY ");
} }
} else if (IS_LEASE(fl)) { } else if (IS_LEASE(fl)) {
seq_printf(f, "LEASE "); seq_puts(f, "LEASE ");
if (lease_breaking(fl)) if (lease_breaking(fl))
seq_printf(f, "BREAKING "); seq_puts(f, "BREAKING ");
else if (fl->fl_file) else if (fl->fl_file)
seq_printf(f, "ACTIVE "); seq_puts(f, "ACTIVE ");
else else
seq_printf(f, "BREAKER "); seq_puts(f, "BREAKER ");
} else { } else {
seq_printf(f, "UNKNOWN UNKNOWN "); seq_puts(f, "UNKNOWN UNKNOWN ");
} }
if (fl->fl_type & LOCK_MAND) { if (fl->fl_type & LOCK_MAND) {
seq_printf(f, "%s ", seq_printf(f, "%s ",
...@@ -2479,7 +2492,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, ...@@ -2479,7 +2492,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
else else
seq_printf(f, "%Ld %Ld\n", fl->fl_start, fl->fl_end); seq_printf(f, "%Ld %Ld\n", fl->fl_start, fl->fl_end);
} else { } else {
seq_printf(f, "0 EOF\n"); seq_puts(f, "0 EOF\n");
} }
} }
......
...@@ -916,10 +916,6 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) ...@@ -916,10 +916,6 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
is_local = 1; is_local = 1;
/* We're simulating flock() locks using posix locks on the server */ /* We're simulating flock() locks using posix locks on the server */
fl->fl_owner = (fl_owner_t)filp;
fl->fl_start = 0;
fl->fl_end = OFFSET_MAX;
if (fl->fl_type == F_UNLCK) if (fl->fl_type == F_UNLCK)
return do_unlk(filp, cmd, fl, is_local); return do_unlk(filp, cmd, fl, is_local);
return do_setlk(filp, cmd, fl, is_local); return do_setlk(filp, cmd, fl, is_local);
......
/*
* Events for filesystem locks
*
* Copyright 2013 Jeff Layton <jlayton@poochiereds.net>
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM filelock
#if !defined(_TRACE_FILELOCK_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_FILELOCK_H
#include <linux/tracepoint.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#define show_fl_flags(val) \
__print_flags(val, "|", \
{ FL_POSIX, "FL_POSIX" }, \
{ FL_FLOCK, "FL_FLOCK" }, \
{ FL_DELEG, "FL_DELEG" }, \
{ FL_ACCESS, "FL_ACCESS" }, \
{ FL_EXISTS, "FL_EXISTS" }, \
{ FL_LEASE, "FL_LEASE" }, \
{ FL_CLOSE, "FL_CLOSE" }, \
{ FL_SLEEP, "FL_SLEEP" }, \
{ FL_DOWNGRADE_PENDING, "FL_DOWNGRADE_PENDING" }, \
{ FL_UNLOCK_PENDING, "FL_UNLOCK_PENDING" }, \
{ FL_OFDLCK, "FL_OFDLCK" })
#define show_fl_type(val) \
__print_symbolic(val, \
{ F_RDLCK, "F_RDLCK" }, \
{ F_WRLCK, "F_WRLCK" }, \
{ F_UNLCK, "F_UNLCK" })
DECLARE_EVENT_CLASS(filelock_lease,
TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl),
TP_STRUCT__entry(
__field(struct file_lock *, fl)
__field(unsigned long, i_ino)
__field(dev_t, s_dev)
__field(struct file_lock *, fl_next)
__field(fl_owner_t, fl_owner)
__field(unsigned int, fl_flags)
__field(unsigned char, fl_type)
__field(unsigned long, fl_break_time)
__field(unsigned long, fl_downgrade_time)
),
TP_fast_assign(
__entry->fl = fl;
__entry->s_dev = inode->i_sb->s_dev;
__entry->i_ino = inode->i_ino;
__entry->fl_next = fl->fl_next;
__entry->fl_owner = fl->fl_owner;
__entry->fl_flags = fl->fl_flags;
__entry->fl_type = fl->fl_type;
__entry->fl_break_time = fl->fl_break_time;
__entry->fl_downgrade_time = fl->fl_downgrade_time;
),
TP_printk("fl=0x%p dev=0x%x:0x%x ino=0x%lx fl_next=0x%p fl_owner=0x%p fl_flags=%s fl_type=%s fl_break_time=%lu fl_downgrade_time=%lu",
__entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
__entry->i_ino, __entry->fl_next, __entry->fl_owner,
show_fl_flags(__entry->fl_flags),
show_fl_type(__entry->fl_type),
__entry->fl_break_time, __entry->fl_downgrade_time)
);
DEFINE_EVENT(filelock_lease, break_lease_noblock, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl));
DEFINE_EVENT(filelock_lease, break_lease_block, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl));
DEFINE_EVENT(filelock_lease, break_lease_unblock, TP_PROTO(struct inode *inode, struct file_lock *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),
TP_ARGS(inode, fl));
DEFINE_EVENT(filelock_lease, time_out_leases, TP_PROTO(struct inode *inode, struct file_lock *fl),
TP_ARGS(inode, fl));
#endif /* _TRACE_FILELOCK_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
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