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 CC: Al Viro CC: Alexey Dobriyan CC: Andrew Morton CC: Pavel Emelyanov CC: James Bottomley --- 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 #include "../../mount.h" +#include "../fdinfo.h" #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 #define FANOTIFY_DEFAULT_MAX_MARKS 8192 @@ -877,6 +878,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 @@ -887,7 +902,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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +#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 #include #include +#include +#include +#include #include "inotify.h" +#include "../fdinfo.h" #include @@ -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); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/