Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs, notify: add procfs fdinfo helper

This allow us to print out fsnotify details such as watchee inode, device,
mask and optionally a file handle.

For inotify objects if kernel compiled with exportfs support the output
will be

| 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

If kernel compiled without exportfs support, the file handle
won't be provided but inode and device only.

| pos: 0
| flags: 02000000
| inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0
| inotify wd:2 ino:a111 sdev:800013 mask:800afce ignored_mask:0
| inotify wd:1 ino:6b149 sdev:800013 mask:800afce ignored_mask:0

For fanotify the output is like

| pos: 0
| flags: 04002
| fanotify flags:10 event-flags:0
| fanotify mnt_id:12 mask:3b ignored_mask:0
| fanotify ino:50205 sdev:800013 mask:3b ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:05020500fb1d47e7

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

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andrey Vagin <avagin@openvz.org>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: James Bottomley <jbottomley@parallels.com>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Matthew Helsley <matt.helsley@gmail.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Cyrill Gorcunov and committed by
Linus Torvalds
be77196b 711c7bf9

+207 -1
+1 -1
fs/notify/Makefile
··· 1 1 obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o \ 2 - mark.o vfsmount_mark.o 2 + mark.o vfsmount_mark.o fdinfo.o 3 3 4 4 obj-y += dnotify/ 5 5 obj-y += inotify/
+2
fs/notify/fanotify/fanotify_user.c
··· 17 17 #include <asm/ioctls.h> 18 18 19 19 #include "../../mount.h" 20 + #include "../fdinfo.h" 20 21 21 22 #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 22 23 #define FANOTIFY_DEFAULT_MAX_MARKS 8192 ··· 429 428 } 430 429 431 430 static const struct file_operations fanotify_fops = { 431 + .show_fdinfo = fanotify_show_fdinfo, 432 432 .poll = fanotify_poll, 433 433 .read = fanotify_read, 434 434 .write = fanotify_write,
+175
fs/notify/fdinfo.c
··· 1 + #include <linux/file.h> 2 + #include <linux/fs.h> 3 + #include <linux/fsnotify_backend.h> 4 + #include <linux/idr.h> 5 + #include <linux/init.h> 6 + #include <linux/inotify.h> 7 + #include <linux/fanotify.h> 8 + #include <linux/kernel.h> 9 + #include <linux/namei.h> 10 + #include <linux/sched.h> 11 + #include <linux/types.h> 12 + #include <linux/seq_file.h> 13 + #include <linux/proc_fs.h> 14 + #include <linux/exportfs.h> 15 + 16 + #include "inotify/inotify.h" 17 + #include "../fs/mount.h" 18 + 19 + #if defined(CONFIG_PROC_FS) 20 + 21 + #if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY) 22 + 23 + static int show_fdinfo(struct seq_file *m, struct file *f, 24 + int (*show)(struct seq_file *m, struct fsnotify_mark *mark)) 25 + { 26 + struct fsnotify_group *group = f->private_data; 27 + struct fsnotify_mark *mark; 28 + int ret = 0; 29 + 30 + spin_lock(&group->mark_lock); 31 + list_for_each_entry(mark, &group->marks_list, g_list) { 32 + ret = show(m, mark); 33 + if (ret) 34 + break; 35 + } 36 + spin_unlock(&group->mark_lock); 37 + return ret; 38 + } 39 + 40 + #if defined(CONFIG_EXPORTFS) 41 + static int show_mark_fhandle(struct seq_file *m, struct inode *inode) 42 + { 43 + struct { 44 + struct file_handle handle; 45 + u8 pad[64]; 46 + } f; 47 + int size, ret, i; 48 + 49 + f.handle.handle_bytes = sizeof(f.pad); 50 + size = f.handle.handle_bytes >> 2; 51 + 52 + ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); 53 + if ((ret == 255) || (ret == -ENOSPC)) { 54 + WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); 55 + return 0; 56 + } 57 + 58 + f.handle.handle_type = ret; 59 + f.handle.handle_bytes = size * sizeof(u32); 60 + 61 + ret = seq_printf(m, "fhandle-bytes:%x fhandle-type:%x f_handle:", 62 + f.handle.handle_bytes, f.handle.handle_type); 63 + 64 + for (i = 0; i < f.handle.handle_bytes; i++) 65 + ret |= seq_printf(m, "%02x", (int)f.handle.f_handle[i]); 66 + 67 + return ret; 68 + } 69 + #else 70 + static int show_mark_fhandle(struct seq_file *m, struct inode *inode) 71 + { 72 + return 0; 73 + } 74 + #endif 75 + 76 + #ifdef CONFIG_INOTIFY_USER 77 + 78 + static int inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) 79 + { 80 + struct inotify_inode_mark *inode_mark; 81 + struct inode *inode; 82 + int ret = 0; 83 + 84 + if (!(mark->flags & (FSNOTIFY_MARK_FLAG_ALIVE | FSNOTIFY_MARK_FLAG_INODE))) 85 + return 0; 86 + 87 + inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); 88 + inode = igrab(mark->i.inode); 89 + if (inode) { 90 + ret = seq_printf(m, "inotify wd:%x ino:%lx sdev:%x " 91 + "mask:%x ignored_mask:%x ", 92 + inode_mark->wd, inode->i_ino, 93 + inode->i_sb->s_dev, 94 + mark->mask, mark->ignored_mask); 95 + ret |= show_mark_fhandle(m, inode); 96 + ret |= seq_putc(m, '\n'); 97 + iput(inode); 98 + } 99 + 100 + return ret; 101 + } 102 + 103 + int inotify_show_fdinfo(struct seq_file *m, struct file *f) 104 + { 105 + return show_fdinfo(m, f, inotify_fdinfo); 106 + } 107 + 108 + #endif /* CONFIG_INOTIFY_USER */ 109 + 110 + #ifdef CONFIG_FANOTIFY 111 + 112 + static int fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) 113 + { 114 + struct inode *inode; 115 + int ret = 0; 116 + 117 + if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) 118 + return 0; 119 + 120 + if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { 121 + inode = igrab(mark->i.inode); 122 + if (!inode) 123 + goto out; 124 + ret = seq_printf(m, "fanotify ino:%lx sdev:%x " 125 + "mask:%x ignored_mask:%x ", 126 + inode->i_ino, inode->i_sb->s_dev, 127 + mark->mask, mark->ignored_mask); 128 + ret |= show_mark_fhandle(m, inode); 129 + ret |= seq_putc(m, '\n'); 130 + iput(inode); 131 + } else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) { 132 + struct mount *mnt = real_mount(mark->m.mnt); 133 + 134 + ret = seq_printf(m, "fanotify mnt_id:%x mask:%x " 135 + "ignored_mask:%x\n", 136 + mnt->mnt_id, mark->mask, mark->ignored_mask); 137 + } 138 + out: 139 + return ret; 140 + } 141 + 142 + int fanotify_show_fdinfo(struct seq_file *m, struct file *f) 143 + { 144 + struct fsnotify_group *group = f->private_data; 145 + unsigned int flags = 0; 146 + 147 + switch (group->priority) { 148 + case FS_PRIO_0: 149 + flags |= FAN_CLASS_NOTIF; 150 + break; 151 + case FS_PRIO_1: 152 + flags |= FAN_CLASS_CONTENT; 153 + break; 154 + case FS_PRIO_2: 155 + flags |= FAN_CLASS_PRE_CONTENT; 156 + break; 157 + } 158 + 159 + if (group->max_events == UINT_MAX) 160 + flags |= FAN_UNLIMITED_QUEUE; 161 + 162 + if (group->fanotify_data.max_marks == UINT_MAX) 163 + flags |= FAN_UNLIMITED_MARKS; 164 + 165 + seq_printf(m, "fanotify flags:%x event-flags:%x\n", 166 + flags, group->fanotify_data.f_flags); 167 + 168 + return show_fdinfo(m, f, fanotify_fdinfo); 169 + } 170 + 171 + #endif /* CONFIG_FANOTIFY */ 172 + 173 + #endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */ 174 + 175 + #endif /* CONFIG_PROC_FS */
+27
fs/notify/fdinfo.h
··· 1 + #ifndef __FSNOTIFY_FDINFO_H__ 2 + #define __FSNOTIFY_FDINFO_H__ 3 + 4 + #include <linux/errno.h> 5 + #include <linux/proc_fs.h> 6 + 7 + struct seq_file; 8 + struct file; 9 + 10 + #ifdef CONFIG_PROC_FS 11 + 12 + #ifdef CONFIG_INOTIFY_USER 13 + extern int inotify_show_fdinfo(struct seq_file *m, struct file *f); 14 + #endif 15 + 16 + #ifdef CONFIG_FANOTIFY 17 + extern int fanotify_show_fdinfo(struct seq_file *m, struct file *f); 18 + #endif 19 + 20 + #else /* CONFIG_PROC_FS */ 21 + 22 + #define inotify_show_fdinfo NULL 23 + #define fanotify_show_fdinfo NULL 24 + 25 + #endif /* CONFIG_PROC_FS */ 26 + 27 + #endif /* __FSNOTIFY_FDINFO_H__ */
+2
fs/notify/inotify/inotify_user.c
··· 40 40 #include <linux/wait.h> 41 41 42 42 #include "inotify.h" 43 + #include "../fdinfo.h" 43 44 44 45 #include <asm/ioctls.h> 45 46 ··· 336 335 } 337 336 338 337 static const struct file_operations inotify_fops = { 338 + .show_fdinfo = inotify_show_fdinfo, 339 339 .poll = inotify_poll, 340 340 .read = inotify_read, 341 341 .fasync = inotify_fasync,