* [PATCH] proc: show locks in /proc/pid/fdinfo/X
@ 2015-03-05 15:37 Andrey Vagin
2015-03-05 19:11 ` Jeff Layton
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Andrey Vagin @ 2015-03-05 15:37 UTC (permalink / raw)
To: linux-kernel
Cc: linux-fsdevel, linux-doc, Andrey Vagin, Jonathan Corbet,
Alexander Viro, Jeff Layton, J. Bruce Fields, Andrew Morton,
Cyrill Gorcunov, Pavel Emelyanov
Let's show locks which are associated with a file descriptor in
its fdinfo file.
Currently we don't have a reliable way to determine who holds a lock.
We can find some information in /proc/locks, but PID which is reported
there can be wrong. For example, a process takes a lock, then forks a
child and dies. In this case /proc/locks contains the parent pid, which
can be reused by another process.
$ cat /proc/locks
...
6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
...
$ ps -C rpcbind
PID TTY TIME CMD
332 ? 00:00:00 rpcbind
$ cat /proc/332/fdinfo/4
pos: 0
flags: 0100000
mnt_id: 22
lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
$ ls -l /proc/332/fd/4
lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
$ ls -l /proc/324/fd/
total 0
lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
You can see that the process with the 324 pid doesn't hold the lock.
This information is required for proper dumping and restoring file
locks.
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Jeff Layton <jlayton@poochiereds.net>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
Documentation/filesystems/proc.txt | 4 ++++
fs/locks.c | 38 ++++++++++++++++++++++++++++++++++++++
fs/proc/fd.c | 27 ++++++++++++++++++---------
include/linux/fs.h | 7 +++++++
4 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index a07ba61..6331623 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1704,6 +1704,10 @@ A typical output is
flags: 0100002
mnt_id: 19
+All locks associated with a file descriptor are shown in its fdinfo too.
+
+lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF
+
The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
pair provide additional information particular to the objects they represent.
diff --git a/fs/locks.c b/fs/locks.c
index 365c82e..815f832 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2592,6 +2592,44 @@ static int locks_show(struct seq_file *f, void *v)
return 0;
}
+static void __show_fd_locks(struct seq_file *f,
+ struct list_head *head, int *id,
+ struct file *filp, struct files_struct *files)
+{
+ struct file_lock *fl;
+
+ list_for_each_entry(fl, head, fl_list) {
+
+ if (filp != fl->fl_file)
+ continue;
+ if (fl->fl_owner != files &&
+ fl->fl_owner != filp)
+ continue;
+
+ (*id)++;
+ seq_puts(f, "lock:\t");
+ lock_get_status(f, fl, *id, "");
+ }
+}
+
+void show_fd_locks(struct seq_file *f,
+ struct file *filp, struct files_struct *files)
+{
+ struct inode *inode = file_inode(filp);
+ struct file_lock_context *ctx;
+ int id = 0;
+
+ ctx = inode->i_flctx;
+ if (!ctx)
+ return;
+
+ spin_lock(&ctx->flc_lock);
+ __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
+ __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
+ __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
+ spin_unlock(&ctx->flc_lock);
+}
+
static void *locks_start(struct seq_file *f, loff_t *pos)
__acquires(&blocked_lock_lock)
{
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 8e5ad83..f04e13d 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -8,6 +8,7 @@
#include <linux/security.h>
#include <linux/file.h>
#include <linux/seq_file.h>
+#include <linux/fs.h>
#include <linux/proc_fs.h>
@@ -48,16 +49,24 @@ static int seq_show(struct seq_file *m, void *v)
put_files_struct(files);
}
- if (!ret) {
- seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
- (long long)file->f_pos, f_flags,
- real_mount(file->f_path.mnt)->mnt_id);
- if (file->f_op->show_fdinfo)
- file->f_op->show_fdinfo(m, file);
- ret = seq_has_overflowed(m);
- fput(file);
- }
+ if (ret)
+ return ret;
+
+ seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
+ (long long)file->f_pos, f_flags,
+ real_mount(file->f_path.mnt)->mnt_id);
+
+ show_fd_locks(m, file, files);
+ ret = seq_has_overflowed(m);
+ if (ret)
+ goto out;
+
+ if (file->f_op->show_fdinfo)
+ file->f_op->show_fdinfo(m, file);
+ ret = seq_has_overflowed(m);
+out:
+ fput(file);
return ret;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b4d71b5..ba0bd2a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1018,6 +1018,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time);
extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
extern int lease_modify(struct file_lock *, int, struct list_head *);
+struct files_struct;
+extern void show_fd_locks(struct seq_file *f,
+ struct file *filp, struct files_struct *files);
#else /* !CONFIG_FILE_LOCKING */
static inline int fcntl_getlk(struct file *file, unsigned int cmd,
struct flock __user *user)
@@ -1154,6 +1157,10 @@ static inline int lease_modify(struct file_lock *fl, int arg,
{
return -EINVAL;
}
+
+struct files_struct;
+static inline void show_fd_locks(struct seq_file *f,
+ struct file *filp, struct files_struct *files) {}
#endif /* !CONFIG_FILE_LOCKING */
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-05 15:37 [PATCH] proc: show locks in /proc/pid/fdinfo/X Andrey Vagin
@ 2015-03-05 19:11 ` Jeff Layton
2015-03-06 14:19 ` Andrew Vagin
2015-03-06 8:38 ` Cyrill Gorcunov
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Jeff Layton @ 2015-03-05 19:11 UTC (permalink / raw)
To: Andrey Vagin
Cc: linux-kernel, linux-fsdevel, linux-doc, Jonathan Corbet,
Alexander Viro, J. Bruce Fields, Andrew Morton, Cyrill Gorcunov,
Pavel Emelyanov
On Thu, 5 Mar 2015 18:37:18 +0300
Andrey Vagin <avagin@openvz.org> wrote:
> Let's show locks which are associated with a file descriptor in
> its fdinfo file.
>
> Currently we don't have a reliable way to determine who holds a lock.
> We can find some information in /proc/locks, but PID which is reported
> there can be wrong. For example, a process takes a lock, then forks a
> child and dies. In this case /proc/locks contains the parent pid, which
> can be reused by another process.
>
> $ cat /proc/locks
> ...
> 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> ...
>
> $ ps -C rpcbind
> PID TTY TIME CMD
> 332 ? 00:00:00 rpcbind
>
> $ cat /proc/332/fdinfo/4
> pos: 0
> flags: 0100000
> mnt_id: 22
> lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
>
> $ ls -l /proc/332/fd/4
> lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
>
> $ ls -l /proc/324/fd/
> total 0
> lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
> lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
> lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
>
> You can see that the process with the 324 pid doesn't hold the lock.
>
> This information is required for proper dumping and restoring file
> locks.
>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> Cc: Jeff Layton <jlayton@poochiereds.net>
> Cc: "J. Bruce Fields" <bfields@fieldses.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Cyrill Gorcunov <gorcunov@openvz.org>
> Cc: Pavel Emelyanov <xemul@parallels.com>
> Signed-off-by: Andrey Vagin <avagin@openvz.org>
> ---
> Documentation/filesystems/proc.txt | 4 ++++
> fs/locks.c | 38 ++++++++++++++++++++++++++++++++++++++
> fs/proc/fd.c | 27 ++++++++++++++++++---------
> include/linux/fs.h | 7 +++++++
> 4 files changed, 67 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
> index a07ba61..6331623 100644
> --- a/Documentation/filesystems/proc.txt
> +++ b/Documentation/filesystems/proc.txt
> @@ -1704,6 +1704,10 @@ A typical output is
> flags: 0100002
> mnt_id: 19
>
> +All locks associated with a file descriptor are shown in its fdinfo too.
> +
> +lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF
> +
> The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
> pair provide additional information particular to the objects they represent.
>
> diff --git a/fs/locks.c b/fs/locks.c
> index 365c82e..815f832 100644
> --- a/fs/locks.c
> +++ b/fs/locks.c
> @@ -2592,6 +2592,44 @@ static int locks_show(struct seq_file *f, void *v)
> return 0;
> }
>
> +static void __show_fd_locks(struct seq_file *f,
> + struct list_head *head, int *id,
> + struct file *filp, struct files_struct *files)
> +{
> + struct file_lock *fl;
> +
> + list_for_each_entry(fl, head, fl_list) {
> +
> + if (filp != fl->fl_file)
> + continue;
> + if (fl->fl_owner != files &&
> + fl->fl_owner != filp)
> + continue;
> +
> + (*id)++;
> + seq_puts(f, "lock:\t");
> + lock_get_status(f, fl, *id, "");
> + }
> +}
> +
> +void show_fd_locks(struct seq_file *f,
> + struct file *filp, struct files_struct *files)
> +{
> + struct inode *inode = file_inode(filp);
> + struct file_lock_context *ctx;
> + int id = 0;
> +
> + ctx = inode->i_flctx;
> + if (!ctx)
> + return;
> +
> + spin_lock(&ctx->flc_lock);
> + __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
> + __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
> + __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
> + spin_unlock(&ctx->flc_lock);
> +}
> +
> static void *locks_start(struct seq_file *f, loff_t *pos)
> __acquires(&blocked_lock_lock)
> {
> diff --git a/fs/proc/fd.c b/fs/proc/fd.c
> index 8e5ad83..f04e13d 100644
> --- a/fs/proc/fd.c
> +++ b/fs/proc/fd.c
> @@ -8,6 +8,7 @@
> #include <linux/security.h>
> #include <linux/file.h>
> #include <linux/seq_file.h>
> +#include <linux/fs.h>
>
> #include <linux/proc_fs.h>
>
> @@ -48,16 +49,24 @@ static int seq_show(struct seq_file *m, void *v)
> put_files_struct(files);
> }
>
> - if (!ret) {
> - seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> - (long long)file->f_pos, f_flags,
> - real_mount(file->f_path.mnt)->mnt_id);
> - if (file->f_op->show_fdinfo)
> - file->f_op->show_fdinfo(m, file);
> - ret = seq_has_overflowed(m);
> - fput(file);
> - }
> + if (ret)
> + return ret;
> +
> + seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> + (long long)file->f_pos, f_flags,
> + real_mount(file->f_path.mnt)->mnt_id);
> +
> + show_fd_locks(m, file, files);
> + ret = seq_has_overflowed(m);
> + if (ret)
> + goto out;
> +
> + if (file->f_op->show_fdinfo)
> + file->f_op->show_fdinfo(m, file);
> + ret = seq_has_overflowed(m);
>
> +out:
> + fput(file);
> return ret;
> }
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index b4d71b5..ba0bd2a 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1018,6 +1018,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time);
> extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
> extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
> extern int lease_modify(struct file_lock *, int, struct list_head *);
> +struct files_struct;
> +extern void show_fd_locks(struct seq_file *f,
> + struct file *filp, struct files_struct *files);
> #else /* !CONFIG_FILE_LOCKING */
> static inline int fcntl_getlk(struct file *file, unsigned int cmd,
> struct flock __user *user)
> @@ -1154,6 +1157,10 @@ static inline int lease_modify(struct file_lock *fl, int arg,
> {
> return -EINVAL;
> }
> +
> +struct files_struct;
> +static inline void show_fd_locks(struct seq_file *f,
> + struct file *filp, struct files_struct *files) {}
> #endif /* !CONFIG_FILE_LOCKING */
>
>
Looks reasonably sane to me. Via what tree should this go in?
Acked-by: Jeff Layton <jlayton@poochiereds.net>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-05 15:37 [PATCH] proc: show locks in /proc/pid/fdinfo/X Andrey Vagin
2015-03-05 19:11 ` Jeff Layton
@ 2015-03-06 8:38 ` Cyrill Gorcunov
2015-03-06 14:41 ` J. Bruce Fields
2015-03-11 22:08 ` Andrew Morton
3 siblings, 0 replies; 10+ messages in thread
From: Cyrill Gorcunov @ 2015-03-06 8:38 UTC (permalink / raw)
To: Andrey Vagin
Cc: linux-kernel, linux-fsdevel, linux-doc, Jonathan Corbet,
Alexander Viro, Jeff Layton, J. Bruce Fields, Andrew Morton,
Pavel Emelyanov
On Thu, Mar 05, 2015 at 06:37:18PM +0300, Andrey Vagin wrote:
> Let's show locks which are associated with a file descriptor in
> its fdinfo file.
>
> Currently we don't have a reliable way to determine who holds a lock.
> We can find some information in /proc/locks, but PID which is reported
> there can be wrong. For example, a process takes a lock, then forks a
> child and dies. In this case /proc/locks contains the parent pid, which
> can be reused by another process.
>
> $ cat /proc/locks
> ...
> 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> ...
>
> $ ps -C rpcbind
> PID TTY TIME CMD
> 332 ? 00:00:00 rpcbind
>
...
Looks reasonable to me, thanks!
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-05 19:11 ` Jeff Layton
@ 2015-03-06 14:19 ` Andrew Vagin
0 siblings, 0 replies; 10+ messages in thread
From: Andrew Vagin @ 2015-03-06 14:19 UTC (permalink / raw)
To: Jeff Layton, Andrew Morton
Cc: Andrey Vagin, linux-kernel, linux-fsdevel, linux-doc,
Jonathan Corbet, Alexander Viro, J. Bruce Fields, Cyrill Gorcunov,
Pavel Emelyanov
On Thu, Mar 05, 2015 at 02:11:40PM -0500, Jeff Layton wrote:
> On Thu, 5 Mar 2015 18:37:18 +0300
> Andrey Vagin <avagin@openvz.org> wrote:
>
> > Let's show locks which are associated with a file descriptor in
> > its fdinfo file.
> >
> > Currently we don't have a reliable way to determine who holds a lock.
> > We can find some information in /proc/locks, but PID which is reported
> > there can be wrong. For example, a process takes a lock, then forks a
> > child and dies. In this case /proc/locks contains the parent pid, which
> > can be reused by another process.
> >
> > $ cat /proc/locks
> > ...
> > 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> > ...
> >
> > $ ps -C rpcbind
> > PID TTY TIME CMD
> > 332 ? 00:00:00 rpcbind
> >
> > $ cat /proc/332/fdinfo/4
> > pos: 0
> > flags: 0100000
> > mnt_id: 22
> > lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> >
> > $ ls -l /proc/332/fd/4
> > lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
> >
> > $ ls -l /proc/324/fd/
> > total 0
> > lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
> > lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
> > lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
> >
> > You can see that the process with the 324 pid doesn't hold the lock.
> >
> > This information is required for proper dumping and restoring file
> > locks.
> >
> > Cc: Jonathan Corbet <corbet@lwn.net>
> > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> > Cc: Jeff Layton <jlayton@poochiereds.net>
> > Cc: "J. Bruce Fields" <bfields@fieldses.org>
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Cc: Cyrill Gorcunov <gorcunov@openvz.org>
> > Cc: Pavel Emelyanov <xemul@parallels.com>
> > Signed-off-by: Andrey Vagin <avagin@openvz.org>
> > ---
> > Documentation/filesystems/proc.txt | 4 ++++
> > fs/locks.c | 38 ++++++++++++++++++++++++++++++++++++++
> > fs/proc/fd.c | 27 ++++++++++++++++++---------
> > include/linux/fs.h | 7 +++++++
> > 4 files changed, 67 insertions(+), 9 deletions(-)
> >
...
> > +struct files_struct;
> > +static inline void show_fd_locks(struct seq_file *f,
> > + struct file *filp, struct files_struct *files) {}
> > #endif /* !CONFIG_FILE_LOCKING */
> >
> >
>
> Looks reasonably sane to me. Via what tree should this go in?
I don't know. I think all previous patches about fdinfo went through
linux-mm. Andrew, what do you think?
>
> Acked-by: Jeff Layton <jlayton@poochiereds.net>
Thanks,
Andrey
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-05 15:37 [PATCH] proc: show locks in /proc/pid/fdinfo/X Andrey Vagin
2015-03-05 19:11 ` Jeff Layton
2015-03-06 8:38 ` Cyrill Gorcunov
@ 2015-03-06 14:41 ` J. Bruce Fields
2015-03-07 13:00 ` Jeff Layton
2015-03-11 22:08 ` Andrew Morton
3 siblings, 1 reply; 10+ messages in thread
From: J. Bruce Fields @ 2015-03-06 14:41 UTC (permalink / raw)
To: Andrey Vagin
Cc: linux-kernel, linux-fsdevel, linux-doc, Jonathan Corbet,
Alexander Viro, Jeff Layton, Andrew Morton, Cyrill Gorcunov,
Pavel Emelyanov
On Thu, Mar 05, 2015 at 06:37:18PM +0300, Andrey Vagin wrote:
> Let's show locks which are associated with a file descriptor in
> its fdinfo file.
>
> Currently we don't have a reliable way to determine who holds a lock.
> We can find some information in /proc/locks, but PID which is reported
> there can be wrong. For example, a process takes a lock, then forks a
> child and dies. In this case /proc/locks contains the parent pid, which
> can be reused by another process.
>
> $ cat /proc/locks
> ...
> 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> ...
>
> $ ps -C rpcbind
> PID TTY TIME CMD
> 332 ? 00:00:00 rpcbind
>
> $ cat /proc/332/fdinfo/4
> pos: 0
> flags: 0100000
> mnt_id: 22
> lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
The major:minor part is redundant as long as you have the mnt_id, right?
But I think it makes sense to leave it as you have it, with the same
format as /proc/locks. We get to share the kernel code, maybe userland
gets to reuse a little code too.
And we should really remove that "ifdef WE_CAN_BREAK_LSLK_NOW" from
fs/locks.c, clearly that's not going to happen. (And add a comment that
the better solution may be to get the mntid from fdinfo, if that's
true?)
Anyway, that's a digression, ACK to the patch.
--b.
>
> $ ls -l /proc/332/fd/4
> lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
>
> $ ls -l /proc/324/fd/
> total 0
> lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
> lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
> lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
>
> You can see that the process with the 324 pid doesn't hold the lock.
>
> This information is required for proper dumping and restoring file
> locks.
>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> Cc: Jeff Layton <jlayton@poochiereds.net>
> Cc: "J. Bruce Fields" <bfields@fieldses.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Cyrill Gorcunov <gorcunov@openvz.org>
> Cc: Pavel Emelyanov <xemul@parallels.com>
> Signed-off-by: Andrey Vagin <avagin@openvz.org>
> ---
> Documentation/filesystems/proc.txt | 4 ++++
> fs/locks.c | 38 ++++++++++++++++++++++++++++++++++++++
> fs/proc/fd.c | 27 ++++++++++++++++++---------
> include/linux/fs.h | 7 +++++++
> 4 files changed, 67 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
> index a07ba61..6331623 100644
> --- a/Documentation/filesystems/proc.txt
> +++ b/Documentation/filesystems/proc.txt
> @@ -1704,6 +1704,10 @@ A typical output is
> flags: 0100002
> mnt_id: 19
>
> +All locks associated with a file descriptor are shown in its fdinfo too.
> +
> +lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF
> +
> The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
> pair provide additional information particular to the objects they represent.
>
> diff --git a/fs/locks.c b/fs/locks.c
> index 365c82e..815f832 100644
> --- a/fs/locks.c
> +++ b/fs/locks.c
> @@ -2592,6 +2592,44 @@ static int locks_show(struct seq_file *f, void *v)
> return 0;
> }
>
> +static void __show_fd_locks(struct seq_file *f,
> + struct list_head *head, int *id,
> + struct file *filp, struct files_struct *files)
> +{
> + struct file_lock *fl;
> +
> + list_for_each_entry(fl, head, fl_list) {
> +
> + if (filp != fl->fl_file)
> + continue;
> + if (fl->fl_owner != files &&
> + fl->fl_owner != filp)
> + continue;
> +
> + (*id)++;
> + seq_puts(f, "lock:\t");
> + lock_get_status(f, fl, *id, "");
> + }
> +}
> +
> +void show_fd_locks(struct seq_file *f,
> + struct file *filp, struct files_struct *files)
> +{
> + struct inode *inode = file_inode(filp);
> + struct file_lock_context *ctx;
> + int id = 0;
> +
> + ctx = inode->i_flctx;
> + if (!ctx)
> + return;
> +
> + spin_lock(&ctx->flc_lock);
> + __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
> + __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
> + __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
> + spin_unlock(&ctx->flc_lock);
> +}
> +
> static void *locks_start(struct seq_file *f, loff_t *pos)
> __acquires(&blocked_lock_lock)
> {
> diff --git a/fs/proc/fd.c b/fs/proc/fd.c
> index 8e5ad83..f04e13d 100644
> --- a/fs/proc/fd.c
> +++ b/fs/proc/fd.c
> @@ -8,6 +8,7 @@
> #include <linux/security.h>
> #include <linux/file.h>
> #include <linux/seq_file.h>
> +#include <linux/fs.h>
>
> #include <linux/proc_fs.h>
>
> @@ -48,16 +49,24 @@ static int seq_show(struct seq_file *m, void *v)
> put_files_struct(files);
> }
>
> - if (!ret) {
> - seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> - (long long)file->f_pos, f_flags,
> - real_mount(file->f_path.mnt)->mnt_id);
> - if (file->f_op->show_fdinfo)
> - file->f_op->show_fdinfo(m, file);
> - ret = seq_has_overflowed(m);
> - fput(file);
> - }
> + if (ret)
> + return ret;
> +
> + seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> + (long long)file->f_pos, f_flags,
> + real_mount(file->f_path.mnt)->mnt_id);
> +
> + show_fd_locks(m, file, files);
> + ret = seq_has_overflowed(m);
> + if (ret)
> + goto out;
> +
> + if (file->f_op->show_fdinfo)
> + file->f_op->show_fdinfo(m, file);
> + ret = seq_has_overflowed(m);
>
> +out:
> + fput(file);
> return ret;
> }
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index b4d71b5..ba0bd2a 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1018,6 +1018,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time);
> extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
> extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
> extern int lease_modify(struct file_lock *, int, struct list_head *);
> +struct files_struct;
> +extern void show_fd_locks(struct seq_file *f,
> + struct file *filp, struct files_struct *files);
> #else /* !CONFIG_FILE_LOCKING */
> static inline int fcntl_getlk(struct file *file, unsigned int cmd,
> struct flock __user *user)
> @@ -1154,6 +1157,10 @@ static inline int lease_modify(struct file_lock *fl, int arg,
> {
> return -EINVAL;
> }
> +
> +struct files_struct;
> +static inline void show_fd_locks(struct seq_file *f,
> + struct file *filp, struct files_struct *files) {}
> #endif /* !CONFIG_FILE_LOCKING */
>
>
> --
> 2.1.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-06 14:41 ` J. Bruce Fields
@ 2015-03-07 13:00 ` Jeff Layton
0 siblings, 0 replies; 10+ messages in thread
From: Jeff Layton @ 2015-03-07 13:00 UTC (permalink / raw)
To: J. Bruce Fields
Cc: Andrey Vagin, linux-kernel, linux-fsdevel, linux-doc,
Jonathan Corbet, Alexander Viro, Andrew Morton, Cyrill Gorcunov,
Pavel Emelyanov
On Fri, 6 Mar 2015 09:41:00 -0500
"J. Bruce Fields" <bfields@fieldses.org> wrote:
> On Thu, Mar 05, 2015 at 06:37:18PM +0300, Andrey Vagin wrote:
> > Let's show locks which are associated with a file descriptor in
> > its fdinfo file.
> >
> > Currently we don't have a reliable way to determine who holds a lock.
> > We can find some information in /proc/locks, but PID which is reported
> > there can be wrong. For example, a process takes a lock, then forks a
> > child and dies. In this case /proc/locks contains the parent pid, which
> > can be reused by another process.
> >
> > $ cat /proc/locks
> > ...
> > 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> > ...
> >
> > $ ps -C rpcbind
> > PID TTY TIME CMD
> > 332 ? 00:00:00 rpcbind
> >
> > $ cat /proc/332/fdinfo/4
> > pos: 0
> > flags: 0100000
> > mnt_id: 22
> > lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
>
> The major:minor part is redundant as long as you have the mnt_id, right?
>
> But I think it makes sense to leave it as you have it, with the same
> format as /proc/locks. We get to share the kernel code, maybe userland
> gets to reuse a little code too.
>
> And we should really remove that "ifdef WE_CAN_BREAK_LSLK_NOW" from
> fs/locks.c, clearly that's not going to happen. (And add a comment that
> the better solution may be to get the mntid from fdinfo, if that's
> true?)
>
Yeah, I don't see a good reason to keep that in place either. It's been
there since the git history started. I'll queue up a patch to remove it
in v4.1.
Thanks!
> Anyway, that's a digression, ACK to the patch.
>
> --b.
>
> >
> > $ ls -l /proc/332/fd/4
> > lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
> >
> > $ ls -l /proc/324/fd/
> > total 0
> > lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
> > lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
> > lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
> >
> > You can see that the process with the 324 pid doesn't hold the lock.
> >
> > This information is required for proper dumping and restoring file
> > locks.
> >
> > Cc: Jonathan Corbet <corbet@lwn.net>
> > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> > Cc: Jeff Layton <jlayton@poochiereds.net>
> > Cc: "J. Bruce Fields" <bfields@fieldses.org>
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Cc: Cyrill Gorcunov <gorcunov@openvz.org>
> > Cc: Pavel Emelyanov <xemul@parallels.com>
> > Signed-off-by: Andrey Vagin <avagin@openvz.org>
> > ---
> > Documentation/filesystems/proc.txt | 4 ++++
> > fs/locks.c | 38 ++++++++++++++++++++++++++++++++++++++
> > fs/proc/fd.c | 27 ++++++++++++++++++---------
> > include/linux/fs.h | 7 +++++++
> > 4 files changed, 67 insertions(+), 9 deletions(-)
> >
> > diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
> > index a07ba61..6331623 100644
> > --- a/Documentation/filesystems/proc.txt
> > +++ b/Documentation/filesystems/proc.txt
> > @@ -1704,6 +1704,10 @@ A typical output is
> > flags: 0100002
> > mnt_id: 19
> >
> > +All locks associated with a file descriptor are shown in its fdinfo too.
> > +
> > +lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF
> > +
> > The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
> > pair provide additional information particular to the objects they represent.
> >
> > diff --git a/fs/locks.c b/fs/locks.c
> > index 365c82e..815f832 100644
> > --- a/fs/locks.c
> > +++ b/fs/locks.c
> > @@ -2592,6 +2592,44 @@ static int locks_show(struct seq_file *f, void *v)
> > return 0;
> > }
> >
> > +static void __show_fd_locks(struct seq_file *f,
> > + struct list_head *head, int *id,
> > + struct file *filp, struct files_struct *files)
> > +{
> > + struct file_lock *fl;
> > +
> > + list_for_each_entry(fl, head, fl_list) {
> > +
> > + if (filp != fl->fl_file)
> > + continue;
> > + if (fl->fl_owner != files &&
> > + fl->fl_owner != filp)
> > + continue;
> > +
> > + (*id)++;
> > + seq_puts(f, "lock:\t");
> > + lock_get_status(f, fl, *id, "");
> > + }
> > +}
> > +
> > +void show_fd_locks(struct seq_file *f,
> > + struct file *filp, struct files_struct *files)
> > +{
> > + struct inode *inode = file_inode(filp);
> > + struct file_lock_context *ctx;
> > + int id = 0;
> > +
> > + ctx = inode->i_flctx;
> > + if (!ctx)
> > + return;
> > +
> > + spin_lock(&ctx->flc_lock);
> > + __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
> > + __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
> > + __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
> > + spin_unlock(&ctx->flc_lock);
> > +}
> > +
> > static void *locks_start(struct seq_file *f, loff_t *pos)
> > __acquires(&blocked_lock_lock)
> > {
> > diff --git a/fs/proc/fd.c b/fs/proc/fd.c
> > index 8e5ad83..f04e13d 100644
> > --- a/fs/proc/fd.c
> > +++ b/fs/proc/fd.c
> > @@ -8,6 +8,7 @@
> > #include <linux/security.h>
> > #include <linux/file.h>
> > #include <linux/seq_file.h>
> > +#include <linux/fs.h>
> >
> > #include <linux/proc_fs.h>
> >
> > @@ -48,16 +49,24 @@ static int seq_show(struct seq_file *m, void *v)
> > put_files_struct(files);
> > }
> >
> > - if (!ret) {
> > - seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> > - (long long)file->f_pos, f_flags,
> > - real_mount(file->f_path.mnt)->mnt_id);
> > - if (file->f_op->show_fdinfo)
> > - file->f_op->show_fdinfo(m, file);
> > - ret = seq_has_overflowed(m);
> > - fput(file);
> > - }
> > + if (ret)
> > + return ret;
> > +
> > + seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> > + (long long)file->f_pos, f_flags,
> > + real_mount(file->f_path.mnt)->mnt_id);
> > +
> > + show_fd_locks(m, file, files);
> > + ret = seq_has_overflowed(m);
> > + if (ret)
> > + goto out;
> > +
> > + if (file->f_op->show_fdinfo)
> > + file->f_op->show_fdinfo(m, file);
> > + ret = seq_has_overflowed(m);
> >
> > +out:
> > + fput(file);
> > return ret;
> > }
> >
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> > index b4d71b5..ba0bd2a 100644
> > --- a/include/linux/fs.h
> > +++ b/include/linux/fs.h
> > @@ -1018,6 +1018,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time);
> > extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
> > extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
> > extern int lease_modify(struct file_lock *, int, struct list_head *);
> > +struct files_struct;
> > +extern void show_fd_locks(struct seq_file *f,
> > + struct file *filp, struct files_struct *files);
> > #else /* !CONFIG_FILE_LOCKING */
> > static inline int fcntl_getlk(struct file *file, unsigned int cmd,
> > struct flock __user *user)
> > @@ -1154,6 +1157,10 @@ static inline int lease_modify(struct file_lock *fl, int arg,
> > {
> > return -EINVAL;
> > }
> > +
> > +struct files_struct;
> > +static inline void show_fd_locks(struct seq_file *f,
> > + struct file *filp, struct files_struct *files) {}
> > #endif /* !CONFIG_FILE_LOCKING */
> >
> >
> > --
> > 2.1.0
--
Jeff Layton <jlayton@poochiereds.net>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-05 15:37 [PATCH] proc: show locks in /proc/pid/fdinfo/X Andrey Vagin
` (2 preceding siblings ...)
2015-03-06 14:41 ` J. Bruce Fields
@ 2015-03-11 22:08 ` Andrew Morton
2015-03-12 15:54 ` Andrew Vagin
3 siblings, 1 reply; 10+ messages in thread
From: Andrew Morton @ 2015-03-11 22:08 UTC (permalink / raw)
To: Andrey Vagin
Cc: linux-kernel, linux-fsdevel, linux-doc, Jonathan Corbet,
Alexander Viro, Jeff Layton, J. Bruce Fields, Cyrill Gorcunov,
Pavel Emelyanov, Joe Perches
On Thu, 5 Mar 2015 18:37:18 +0300 Andrey Vagin <avagin@openvz.org> wrote:
> Let's show locks which are associated with a file descriptor in
> its fdinfo file.
>
> Currently we don't have a reliable way to determine who holds a lock.
> We can find some information in /proc/locks, but PID which is reported
> there can be wrong. For example, a process takes a lock, then forks a
> child and dies. In this case /proc/locks contains the parent pid, which
> can be reused by another process.
>
> $ cat /proc/locks
> ...
> 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> ...
>
> $ ps -C rpcbind
> PID TTY TIME CMD
> 332 ? 00:00:00 rpcbind
>
> $ cat /proc/332/fdinfo/4
> pos: 0
> flags: 0100000
> mnt_id: 22
> lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
>
> $ ls -l /proc/332/fd/4
> lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
>
> $ ls -l /proc/324/fd/
> total 0
> lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
> lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
> lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
>
> You can see that the process with the 324 pid doesn't hold the lock.
>
> This information is required for proper dumping and restoring file
> locks.
>
> ...
>
> --- a/fs/proc/fd.c
> +++ b/fs/proc/fd.c
> @@ -8,6 +8,7 @@
> #include <linux/security.h>
> #include <linux/file.h>
> #include <linux/seq_file.h>
> +#include <linux/fs.h>
>
> #include <linux/proc_fs.h>
>
> @@ -48,16 +49,24 @@ static int seq_show(struct seq_file *m, void *v)
> put_files_struct(files);
> }
>
> - if (!ret) {
> - seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> - (long long)file->f_pos, f_flags,
> - real_mount(file->f_path.mnt)->mnt_id);
> - if (file->f_op->show_fdinfo)
> - file->f_op->show_fdinfo(m, file);
> - ret = seq_has_overflowed(m);
> - fput(file);
> - }
> + if (ret)
> + return ret;
> +
> + seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> + (long long)file->f_pos, f_flags,
> + real_mount(file->f_path.mnt)->mnt_id);
> +
> + show_fd_locks(m, file, files);
> + ret = seq_has_overflowed(m);
> + if (ret)
> + goto out;
seq_has_overflowed() returns a boolean, but fs/seq_file.c:traverse() is
looking for a -ve errno from ->show().
Documentation/filesystems/seq_file.txt says
If all is well, the show() function should return zero. A negative error
code in the usual manner indicates that something went wrong; it will be
passed back to user space. This function can also return SEQ_SKIP, which
causes the current item to be skipped; if the show() function has already
generated output before returning SEQ_SKIP, that output will be dropped.
> + if (file->f_op->show_fdinfo)
> + file->f_op->show_fdinfo(m, file);
> + ret = seq_has_overflowed(m);
>
> +out:
> + fput(file);
> return ret;
> }
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-11 22:08 ` Andrew Morton
@ 2015-03-12 15:54 ` Andrew Vagin
2015-03-12 19:23 ` Andrew Morton
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Vagin @ 2015-03-12 15:54 UTC (permalink / raw)
To: Andrew Morton
Cc: Andrey Vagin, linux-kernel, linux-fsdevel, linux-doc,
Jonathan Corbet, Alexander Viro, Jeff Layton, J. Bruce Fields,
Cyrill Gorcunov, Pavel Emelyanov, Joe Perches
[-- Attachment #1: Type: text/plain, Size: 3200 bytes --]
On Wed, Mar 11, 2015 at 03:08:53PM -0700, Andrew Morton wrote:
> On Thu, 5 Mar 2015 18:37:18 +0300 Andrey Vagin <avagin@openvz.org> wrote:
>
> > Let's show locks which are associated with a file descriptor in
> > its fdinfo file.
> >
> > Currently we don't have a reliable way to determine who holds a lock.
> > We can find some information in /proc/locks, but PID which is reported
> > there can be wrong. For example, a process takes a lock, then forks a
> > child and dies. In this case /proc/locks contains the parent pid, which
> > can be reused by another process.
> >
> > $ cat /proc/locks
> > ...
> > 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> > ...
> >
> > $ ps -C rpcbind
> > PID TTY TIME CMD
> > 332 ? 00:00:00 rpcbind
> >
> > $ cat /proc/332/fdinfo/4
> > pos: 0
> > flags: 0100000
> > mnt_id: 22
> > lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
> >
> > $ ls -l /proc/332/fd/4
> > lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
> >
> > $ ls -l /proc/324/fd/
> > total 0
> > lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
> > lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
> > lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
> >
> > You can see that the process with the 324 pid doesn't hold the lock.
> >
> > This information is required for proper dumping and restoring file
> > locks.
> >
> > ...
> >
> > --- a/fs/proc/fd.c
> > +++ b/fs/proc/fd.c
> > @@ -8,6 +8,7 @@
> > #include <linux/security.h>
> > #include <linux/file.h>
> > #include <linux/seq_file.h>
> > +#include <linux/fs.h>
> >
> > #include <linux/proc_fs.h>
> >
> > @@ -48,16 +49,24 @@ static int seq_show(struct seq_file *m, void *v)
> > put_files_struct(files);
> > }
> >
> > - if (!ret) {
> > - seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> > - (long long)file->f_pos, f_flags,
> > - real_mount(file->f_path.mnt)->mnt_id);
> > - if (file->f_op->show_fdinfo)
> > - file->f_op->show_fdinfo(m, file);
> > - ret = seq_has_overflowed(m);
> > - fput(file);
> > - }
> > + if (ret)
> > + return ret;
> > +
> > + seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
> > + (long long)file->f_pos, f_flags,
> > + real_mount(file->f_path.mnt)->mnt_id);
> > +
> > + show_fd_locks(m, file, files);
> > + ret = seq_has_overflowed(m);
> > + if (ret)
> > + goto out;
>
> seq_has_overflowed() returns a boolean, but fs/seq_file.c:traverse() is
> looking for a -ve errno from ->show().
>
> Documentation/filesystems/seq_file.txt says
>
> If all is well, the show() function should return zero. A negative error
> code in the usual manner indicates that something went wrong; it will be
> passed back to user space. This function can also return SEQ_SKIP, which
> causes the current item to be skipped; if the show() function has already
> generated output before returning SEQ_SKIP, that output will be dropped.
You are right. The updated version of this patch is attached. Thank you
for the review.
>
>
> > + if (file->f_op->show_fdinfo)
> > + file->f_op->show_fdinfo(m, file);
> > + ret = seq_has_overflowed(m);
> >
> > +out:
> > + fput(file);
> > return ret;
> > }
>
[-- Attachment #2: 0001-proc-show-locks-in-proc-pid-fdinfo-X-v2.patch --]
[-- Type: text/plain, Size: 5864 bytes --]
>From 29fcabc8a9d9c8bea4a7ec6202a7c0f6e98a518e Mon Sep 17 00:00:00 2001
From: Andrey Vagin <avagin@openvz.org>
Date: Thu, 26 Feb 2015 15:46:02 +0300
Subject: [PATCH] proc: show locks in /proc/pid/fdinfo/X (v2)
Let's show locks which are associated with a file descriptor in
its fdinfo file.
Currently we don't have a reliable way to determine who holds a lock.
We can find some information in /proc/locks, but PID which is reported
there can be wrong. For example, a process takes a lock, then forks a
child and dies. In this case /proc/locks contains the parent pid, which
can be reused by another process.
$ cat /proc/locks
...
6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
...
$ ps -C rpcbind
PID TTY TIME CMD
332 ? 00:00:00 rpcbind
$ cat /proc/332/fdinfo/4
pos: 0
flags: 0100000
mnt_id: 22
lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF
$ ls -l /proc/332/fd/4
lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock
$ ls -l /proc/324/fd/
total 0
lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0
lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0
lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0
You can see that the process with the 324 pid doesn't hold the lock.
This information is required for proper dumping and restoring file
locks.
v1:
Acked-by: Jeff Layton <jlayton@poochiereds.net>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: "J. Bruce Fields" <bfields@fieldses.org>
v2: use seq_has_overflowed() properly
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
Documentation/filesystems/proc.txt | 4 ++++
fs/locks.c | 38 ++++++++++++++++++++++++++++++++++++++
fs/proc/fd.c | 27 +++++++++++++++++----------
include/linux/fs.h | 7 +++++++
4 files changed, 66 insertions(+), 10 deletions(-)
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index a07ba61..6331623 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1704,6 +1704,10 @@ A typical output is
flags: 0100002
mnt_id: 19
+All locks associated with a file descriptor are shown in its fdinfo too.
+
+lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF
+
The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
pair provide additional information particular to the objects they represent.
diff --git a/fs/locks.c b/fs/locks.c
index f1bad68..89a0540 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2593,6 +2593,44 @@ static int locks_show(struct seq_file *f, void *v)
return 0;
}
+static void __show_fd_locks(struct seq_file *f,
+ struct list_head *head, int *id,
+ struct file *filp, struct files_struct *files)
+{
+ struct file_lock *fl;
+
+ list_for_each_entry(fl, head, fl_list) {
+
+ if (filp != fl->fl_file)
+ continue;
+ if (fl->fl_owner != files &&
+ fl->fl_owner != filp)
+ continue;
+
+ (*id)++;
+ seq_puts(f, "lock:\t");
+ lock_get_status(f, fl, *id, "");
+ }
+}
+
+void show_fd_locks(struct seq_file *f,
+ struct file *filp, struct files_struct *files)
+{
+ struct inode *inode = file_inode(filp);
+ struct file_lock_context *ctx;
+ int id = 0;
+
+ ctx = inode->i_flctx;
+ if (!ctx)
+ return;
+
+ spin_lock(&ctx->flc_lock);
+ __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
+ __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
+ __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
+ spin_unlock(&ctx->flc_lock);
+}
+
static void *locks_start(struct seq_file *f, loff_t *pos)
__acquires(&blocked_lock_lock)
{
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 8e5ad83..af84ad0 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -8,6 +8,7 @@
#include <linux/security.h>
#include <linux/file.h>
#include <linux/seq_file.h>
+#include <linux/fs.h>
#include <linux/proc_fs.h>
@@ -48,17 +49,23 @@ static int seq_show(struct seq_file *m, void *v)
put_files_struct(files);
}
- if (!ret) {
- seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
- (long long)file->f_pos, f_flags,
- real_mount(file->f_path.mnt)->mnt_id);
- if (file->f_op->show_fdinfo)
- file->f_op->show_fdinfo(m, file);
- ret = seq_has_overflowed(m);
- fput(file);
- }
+ if (ret)
+ return ret;
- return ret;
+ seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
+ (long long)file->f_pos, f_flags,
+ real_mount(file->f_path.mnt)->mnt_id);
+
+ show_fd_locks(m, file, files);
+ if (seq_has_overflowed(m))
+ goto out;
+
+ if (file->f_op->show_fdinfo)
+ file->f_op->show_fdinfo(m, file);
+
+out:
+ fput(file);
+ return 0;
}
static int seq_fdinfo_open(struct inode *inode, struct file *file)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b4d71b5..ba0bd2a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1018,6 +1018,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time);
extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
extern int lease_modify(struct file_lock *, int, struct list_head *);
+struct files_struct;
+extern void show_fd_locks(struct seq_file *f,
+ struct file *filp, struct files_struct *files);
#else /* !CONFIG_FILE_LOCKING */
static inline int fcntl_getlk(struct file *file, unsigned int cmd,
struct flock __user *user)
@@ -1154,6 +1157,10 @@ static inline int lease_modify(struct file_lock *fl, int arg,
{
return -EINVAL;
}
+
+struct files_struct;
+static inline void show_fd_locks(struct seq_file *f,
+ struct file *filp, struct files_struct *files) {}
#endif /* !CONFIG_FILE_LOCKING */
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-12 15:54 ` Andrew Vagin
@ 2015-03-12 19:23 ` Andrew Morton
2015-03-12 21:31 ` Andrey Wagin
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Morton @ 2015-03-12 19:23 UTC (permalink / raw)
To: Andrew Vagin
Cc: Andrey Vagin, linux-kernel, linux-fsdevel, linux-doc,
Jonathan Corbet, Alexander Viro, Jeff Layton, J. Bruce Fields,
Cyrill Gorcunov, Pavel Emelyanov, Joe Perches
On Thu, 12 Mar 2015 18:54:42 +0300 Andrew Vagin <avagin@parallels.com> wrote:
> v2: use seq_has_overflowed() properly
--- a/fs/proc/fd.c~proc-show-locks-in-proc-pid-fdinfo-x-v2
+++ a/fs/proc/fd.c
@@ -57,17 +57,15 @@ static int seq_show(struct seq_file *m,
real_mount(file->f_path.mnt)->mnt_id);
show_fd_locks(m, file, files);
- ret = seq_has_overflowed(m);
- if (ret)
+ if (seq_has_overflowed(m))
goto out;
if (file->f_op->show_fdinfo)
file->f_op->show_fdinfo(m, file);
- ret = seq_has_overflowed(m);
out:
fput(file);
- return ret;
+ return 0;
}
static int seq_fdinfo_open(struct inode *inode, struct file *file)
So it returns "success" when the output has overflowed? Why this,
rather than returning an error?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] proc: show locks in /proc/pid/fdinfo/X
2015-03-12 19:23 ` Andrew Morton
@ 2015-03-12 21:31 ` Andrey Wagin
0 siblings, 0 replies; 10+ messages in thread
From: Andrey Wagin @ 2015-03-12 21:31 UTC (permalink / raw)
To: Andrew Morton
Cc: Andrew Vagin, LKML, linux-fsdevel, linux-doc, Jonathan Corbet,
Alexander Viro, Jeff Layton, J. Bruce Fields, Cyrill Gorcunov,
Pavel Emelyanov, Joe Perches
2015-03-12 22:23 GMT+03:00 Andrew Morton <akpm@linux-foundation.org>:
> On Thu, 12 Mar 2015 18:54:42 +0300 Andrew Vagin <avagin@parallels.com> wrote:
>
>> v2: use seq_has_overflowed() properly
>
> --- a/fs/proc/fd.c~proc-show-locks-in-proc-pid-fdinfo-x-v2
> +++ a/fs/proc/fd.c
> @@ -57,17 +57,15 @@ static int seq_show(struct seq_file *m,
> real_mount(file->f_path.mnt)->mnt_id);
>
> show_fd_locks(m, file, files);
> - ret = seq_has_overflowed(m);
> - if (ret)
> + if (seq_has_overflowed(m))
> goto out;
>
> if (file->f_op->show_fdinfo)
> file->f_op->show_fdinfo(m, file);
> - ret = seq_has_overflowed(m);
>
> out:
> fput(file);
> - return ret;
> + return 0;
> }
>
> static int seq_fdinfo_open(struct inode *inode, struct file *file)
>
>
> So it returns "success" when the output has overflowed? Why this,
> rather than returning an error?
I have read fs/seq_file.c and looks like it's the right way.
seq_has_overflowed() is used to avoid useless work. If we call it or
don't call it, the result must be the same in both cases. So from this
point of view it looks logically correct too.
There are two interesting places from seq_file.c
error = m->op->show(m, p);
if (error < 0)
break;
if (unlikely(error)) {
error = 0;
m->count = 0;
}
if (seq_has_overflowed(m))
goto Eoverflow;
...
err = m->op->show(m, p);
if (err < 0)
break;
if (unlikely(err))
m->count = 0;
if (unlikely(!m->count)) {
p = m->op->next(m, p, &pos);
m->index = pos;
continue;
}
if (m->count < m->size)
goto Fill;
m->op->stop(m, p);
kvfree(m->buf);
m->count = 0;
m->buf = seq_buf_alloc(m->size <<= 1);
Thanks,
Andrey
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-03-12 21:31 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-05 15:37 [PATCH] proc: show locks in /proc/pid/fdinfo/X Andrey Vagin
2015-03-05 19:11 ` Jeff Layton
2015-03-06 14:19 ` Andrew Vagin
2015-03-06 8:38 ` Cyrill Gorcunov
2015-03-06 14:41 ` J. Bruce Fields
2015-03-07 13:00 ` Jeff Layton
2015-03-11 22:08 ` Andrew Morton
2015-03-12 15:54 ` Andrew Vagin
2015-03-12 19:23 ` Andrew Morton
2015-03-12 21:31 ` Andrey Wagin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).