lkml.org 
[lkml]   [2012]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 7/8] fs, notify: Add procfs fdinfo helper v3
    This allow us to print out fsnotify details such as
    watchee inode, device, mask and file handle.

    For example for inotify objects the output is

    | pos: 0
    | flags: 02000000
    | inotify wd: 3 ino: 9e7e sdev: 800013 mask: 800afce ignored_mask: 0 fhandle-bytes: 8 fhandle-type: 1 f_handle: 7e9e0000640d1b6d
    | inotify wd: 2 ino: a111 sdev: 800013 mask: 800afce ignored_mask: 0 fhandle-bytes: 8 fhandle-type: 1 f_handle: 11a1000020542153
    | inotify wd: 1 ino: 6b149 sdev: 800013 mask: 800afce ignored_mask: 0 fhandle-bytes: 8 fhandle-type: 1 f_handle: 49b1060023552153

    For fanotify it is like

    | pos: 0
    | flags: 02
    | fanotify ino: 68f71 sdev: 800013 mask: 1 ignored_mask: 40000000 fhandle-bytes: 8 fhandle-type: 1 f_handle: 718f0600b9f42053
    | fanotify mnt_id: 13 mask: 1 ignored_mask: 40000000

    This feature is CONFIG_CHECKPOINT_RESTORE only. To minimize
    impact on general fsnotify code the new functionality is gathered
    in fs/notify/fdinfo.c file mostly.

    v2:
    - append missing colons to terms
    v3:
    - continue from pervious position in list on ->next

    Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
    CC: Al Viro <viro@ZenIV.linux.org.uk>
    CC: Alexey Dobriyan <adobriyan@gmail.com>
    CC: Andrew Morton <akpm@linux-foundation.org>
    CC: Pavel Emelyanov <xemul@parallels.com>
    CC: James Bottomley <jbottomley@parallels.com>
    ---
    fs/notify/Makefile | 2
    fs/notify/fanotify/fanotify_user.c | 17 ++
    fs/notify/fdinfo.c | 216 +++++++++++++++++++++++++++++++++++++
    fs/notify/fdinfo.h | 19 +++
    fs/notify/inotify/inotify_user.c | 32 +++++
    5 files changed, 284 insertions(+), 2 deletions(-)

    Index: linux-2.6.git/fs/notify/Makefile
    ===================================================================
    --- linux-2.6.git.orig/fs/notify/Makefile
    +++ linux-2.6.git/fs/notify/Makefile
    @@ -1,5 +1,5 @@
    obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o \
    - mark.o vfsmount_mark.o
    + mark.o vfsmount_mark.o fdinfo.o

    obj-y += dnotify/
    obj-y += inotify/
    Index: linux-2.6.git/fs/notify/fanotify/fanotify_user.c
    ===================================================================
    --- linux-2.6.git.orig/fs/notify/fanotify/fanotify_user.c
    +++ linux-2.6.git/fs/notify/fanotify/fanotify_user.c
    @@ -17,6 +17,7 @@
    #include <asm/ioctls.h>

    #include "../../mount.h"
    +#include "../fdinfo.h"

    #define FANOTIFY_DEFAULT_MAX_EVENTS 16384
    #define FANOTIFY_DEFAULT_MAX_MARKS 8192
    @@ -873,6 +874,20 @@ asmlinkage long SyS_fanotify_mark(long f
    SYSCALL_ALIAS(sys_fanotify_mark, SyS_fanotify_mark);
    #endif

    +#if defined(CONFIG_PROC_FS) && defined(CONFIG_CHECKPOINT_RESTORE)
    +int is_file_fanotify(struct file *file)
    +{
    + return file->f_op == &fanotify_fops;
    +}
    +
    +static int __init fanotify_register_fdinfo_driver(void)
    +{
    + return proc_register_fdinfo_driver(&fanotify_fdinfo);
    +}
    +#else
    +void fanotify_register_fdinfo_driver(void) { }
    +#endif /* CONFIG_PROC_FS && CONFIG_CHECKPOINT_RESTORE */
    +
    /*
    * fanotify_user_setup - Our initialization function. Note that we cannot return
    * error because we have compiled-in VFS hooks. So an (unlikely) failure here
    @@ -883,7 +898,7 @@ static int __init fanotify_user_setup(vo
    fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, SLAB_PANIC);
    fanotify_response_event_cache = KMEM_CACHE(fanotify_response_event,
    SLAB_PANIC);
    -
    + fanotify_register_fdinfo_driver();
    return 0;
    }
    device_initcall(fanotify_user_setup);
    Index: linux-2.6.git/fs/notify/fdinfo.c
    ===================================================================
    --- /dev/null
    +++ linux-2.6.git/fs/notify/fdinfo.c
    @@ -0,0 +1,216 @@
    +#include <linux/file.h>
    +#include <linux/fs.h>
    +#include <linux/fsnotify_backend.h>
    +#include <linux/idr.h>
    +#include <linux/init.h>
    +#include <linux/inotify.h>
    +#include <linux/kernel.h>
    +#include <linux/namei.h>
    +#include <linux/sched.h>
    +#include <linux/types.h>
    +#include <linux/seq_file.h>
    +#include <linux/exportfs.h>
    +#include <linux/proc_fs.h>
    +
    +#include "inotify/inotify.h"
    +#include "../fs/mount.h"
    +
    +struct inode_file_handle {
    + struct file_handle h;
    + struct fid fid;
    +} __packed;
    +
    +#if defined(CONFIG_PROC_FS) && defined(CONFIG_CHECKPOINT_RESTORE)
    +
    +#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
    +
    +#ifdef CONFIG_EXPORTFS
    +static int inotify_encode_target(struct inode *inode, struct inode_file_handle *fhandle)
    +{
    + int ret, size;
    +
    + size = sizeof(fhandle->fid) >> 2;
    + ret = export_encode_inode_fh(inode, &fhandle->fid, &size);
    + BUG_ON(ret != FILEID_INO32_GEN);
    +
    + fhandle->h.handle_type = FILEID_INO32_GEN;
    + fhandle->h.handle_bytes = size * sizeof(u32);
    +
    + return 0;
    +}
    +#else
    +static int inotify_encode_target(struct inode *inode, struct inode_file_handle *fhandle)
    +{
    + fhandle->h.handle_type = FILEID_ROOT;
    + fhandle->h.handle_bytes = 0;
    + return 0;
    +}
    +#endif /* CONFIG_EXPORTFS */
    +
    +static inline bool mark_match(struct fsnotify_mark *mark)
    +{
    + return (mark->flags & FSNOTIFY_MARK_FLAG_ALIVE) &&
    + (mark->flags & (FSNOTIFY_MARK_FLAG_INODE | FSNOTIFY_MARK_FLAG_VFSMOUNT));
    +}
    +
    +static void *seq_start(struct seq_file *m, loff_t *pos)
    +{
    + struct proc_fdinfo_extra *extra = m->private;
    + struct fsnotify_group *group = extra->f_file->private_data;
    + struct fsnotify_mark *mark;
    + loff_t num = *pos;
    +
    + spin_lock(&group->mark_lock);
    +
    + list_for_each_entry(mark, &group->marks_list, g_list) {
    + if (!mark_match(mark))
    + continue;
    + if (num-- == 0)
    + return (void *)mark;
    + }
    +
    + return NULL;
    +}
    +
    +static void seq_stop(struct seq_file *m, void *v)
    +{
    + struct proc_fdinfo_extra *extra = m->private;
    + struct fsnotify_group *group = extra->f_file->private_data;
    +
    + spin_unlock(&group->mark_lock);
    +}
    +
    +static void *seq_next(struct seq_file *m, void *p, loff_t *pos)
    +{
    + struct proc_fdinfo_extra *extra = m->private;
    + struct fsnotify_group *group = extra->f_file->private_data;
    + struct fsnotify_mark *mark = p;
    +
    + ++*pos;
    +
    + list_for_each_entry_continue(mark, &group->marks_list, g_list) {
    + if (mark_match(mark))
    + return mark;
    + }
    +
    + return NULL;
    +}
    +
    +#ifdef CONFIG_INOTIFY_USER
    +
    +extern int is_file_inotify(struct file *file);
    +
    +static int seq_show_inotify(struct seq_file *m, void *v)
    +{
    + struct inotify_inode_mark *inode_mark;
    + struct fsnotify_mark *mark = v;
    + struct inode *inode;
    +
    + if (unlikely(!(mark->flags & FSNOTIFY_MARK_FLAG_INODE)))
    + goto out;
    +
    + inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
    + inode = igrab(mark->i.inode);
    + if (inode) {
    + struct inode_file_handle fhandle;
    + int i;
    +
    + inotify_encode_target(inode, &fhandle);
    +
    + seq_printf(m, "inotify wd: %8d ino: %16lx sdev: %8x "
    + "mask: %8x ignored_mask: %8x "
    + "fhandle-bytes: %8x fhandle-type: %8x f_handle: ",
    + inode_mark->wd, inode->i_ino,
    + inode->i_sb->s_dev,
    + mark->mask,
    + mark->ignored_mask,
    + fhandle.h.handle_bytes,
    + fhandle.h.handle_type);
    +
    + for (i = 0; i < fhandle.h.handle_bytes; i++) {
    + seq_printf(m, "%02x",
    + (int)(unsigned char)fhandle.h.f_handle[i]);
    + }
    + seq_putc(m, '\n');
    + iput(inode);
    + }
    +out:
    + return 0;
    +}
    +
    +static const struct seq_operations inotify_fdinfo_ops = {
    + .start = seq_start,
    + .next = seq_next,
    + .stop = seq_stop,
    + .show = seq_show_inotify,
    +};
    +
    +struct proc_fdinfo_driver inotify_fdinfo = {
    + .name = "inotify",
    + .ops = &inotify_fdinfo_ops,
    + .probe = is_file_inotify,
    +};
    +
    +#endif /* CONFIG_INOTIFY_USER */
    +
    +#ifdef CONFIG_FANOTIFY
    +
    +extern int is_file_fanotify(struct file *file);
    +
    +static int seq_show_fanotify(struct seq_file *m, void *v)
    +{
    + struct fsnotify_mark *mark = v;
    + struct inode *inode;
    +
    + if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
    + struct inode_file_handle fhandle;
    + int i;
    +
    + inode = igrab(mark->i.inode);
    + if (!inode)
    + goto out;
    + inotify_encode_target(inode, &fhandle);
    +
    + seq_printf(m, "fanotify ino: %16lx sdev: %8x "
    + "mask: %8x ignored_mask: %8x "
    + "fhandle-bytes: %8x fhandle-type: %8x f_handle: ",
    + inode->i_ino,
    + inode->i_sb->s_dev,
    + mark->mask,
    + mark->ignored_mask,
    + fhandle.h.handle_bytes,
    + fhandle.h.handle_type);
    +
    + for (i = 0; i < fhandle.h.handle_bytes; i++)
    + seq_printf(m, "%02x",
    + (int)(unsigned char)fhandle.h.f_handle[i]);
    + seq_putc(m, '\n');
    + iput(inode);
    + } else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) {
    + struct mount *mnt = real_mount(mark->m.mnt);
    +
    + seq_printf(m, "fanotify mnt_id: %8x mask: %8x ignored_mask: %8x\n",
    + mnt->mnt_id, mark->mask, mark->ignored_mask);
    + }
    +out:
    + return 0;
    +}
    +
    +static const struct seq_operations fanotify_fdinfo_ops = {
    + .start = seq_start,
    + .next = seq_next,
    + .stop = seq_stop,
    + .show = seq_show_fanotify,
    +};
    +
    +struct proc_fdinfo_driver fanotify_fdinfo = {
    + .name = "fanotify",
    + .ops = &fanotify_fdinfo_ops,
    + .probe = is_file_fanotify,
    +};
    +
    +#endif /* CONFIG_FANOTIFY */
    +
    +#endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */
    +
    +#endif /* CONFIG_PROC_FS && CONFIG_CHECKPOINT_RESTORE */
    Index: linux-2.6.git/fs/notify/fdinfo.h
    ===================================================================
    --- /dev/null
    +++ linux-2.6.git/fs/notify/fdinfo.h
    @@ -0,0 +1,19 @@
    +#ifndef __FSNOTIFY_FDINFO_H__
    +#define __FSNOTIFY_FDINFO_H__
    +
    +#include <linux/errno.h>
    +#include <linux/proc_fs.h>
    +
    +#if defined(CONFIG_PROC_FS) && defined(CONFIG_CHECKPOINT_RESTORE)
    +
    +#ifdef CONFIG_INOTIFY_USER
    +extern struct proc_fdinfo_driver inotify_fdinfo;
    +#endif
    +
    +#ifdef CONFIG_FANOTIFY
    +extern struct proc_fdinfo_driver fanotify_fdinfo;
    +#endif
    +
    +#endif
    +
    +#endif /* __FSNOTIFY_FDINFO_H__ */
    Index: linux-2.6.git/fs/notify/inotify/inotify_user.c
    ===================================================================
    --- linux-2.6.git.orig/fs/notify/inotify/inotify_user.c
    +++ linux-2.6.git/fs/notify/inotify/inotify_user.c
    @@ -38,8 +38,12 @@
    #include <linux/uaccess.h>
    #include <linux/poll.h>
    #include <linux/wait.h>
    +#include <linux/seq_file.h>
    +#include <linux/exportfs.h>
    +#include <linux/proc_fs.h>

    #include "inotify.h"
    +#include "../fdinfo.h"

    #include <asm/ioctls.h>

    @@ -827,6 +831,26 @@ out:
    return ret;
    }

    +#if defined(CONFIG_PROC_FS) && defined(CONFIG_CHECKPOINT_RESTORE)
    +int is_file_inotify(struct file *file)
    +{
    + return file->f_op == &inotify_fops;
    +}
    +
    +static int __init inotify_register_fdinfo_driver(void)
    +{
    + return proc_register_fdinfo_driver(&inotify_fdinfo);
    +}
    +
    +static void __exit inotify_unregister_fdinfo_driver(void)
    +{
    + proc_unregister_fdinfo_driver(&inotify_fdinfo);
    +}
    +#else
    +static int __init inotify_register_fdinfo_driver(void) { return 0; }
    +static void __exit inotify_unregister_fdinfo_driver(void) { }
    +#endif /* CONFIG_PROC_FS && CONFIG_CHECKPOINT_RESTORE */
    +
    /*
    * inotify_user_setup - Our initialization function. Note that we cannot return
    * error because we have compiled-in VFS hooks. So an (unlikely) failure here
    @@ -862,6 +886,14 @@ static int __init inotify_user_setup(voi
    inotify_max_user_instances = 128;
    inotify_max_user_watches = 8192;

    + inotify_register_fdinfo_driver();
    +
    return 0;
    }
    module_init(inotify_user_setup);
    +
    +static void __exit inotify_user_exit(void)
    +{
    + inotify_unregister_fdinfo_driver();
    +}
    +module_exit(inotify_user_exit);


    \
     
     \ /
      Last update: 2012-08-14 16:43    [W:4.228 / U:0.288 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site