Branch data Line data Source code
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 : 0 : static int show_fdinfo(struct seq_file *m, struct file *f,
24 : : int (*show)(struct seq_file *m, struct fsnotify_mark *mark))
25 : : {
26 : 0 : struct fsnotify_group *group = f->private_data;
27 : : struct fsnotify_mark *mark;
28 : : int ret = 0;
29 : :
30 : 0 : mutex_lock(&group->mark_mutex);
31 [ # # ]: 0 : list_for_each_entry(mark, &group->marks_list, g_list) {
32 : 0 : ret = show(m, mark);
33 [ # # ]: 0 : if (ret)
34 : : break;
35 : : }
36 : 0 : mutex_unlock(&group->mark_mutex);
37 : 0 : 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 : 0 : 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 [ # # ]: 0 : 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 : 0 : inode = igrab(mark->i.inode);
89 [ # # ]: 0 : if (inode) {
90 : 0 : 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 : 0 : inode->i_sb->s_dev,
94 : : mark->mask, mark->ignored_mask);
95 : : ret |= show_mark_fhandle(m, inode);
96 : 0 : ret |= seq_putc(m, '\n');
97 : 0 : iput(inode);
98 : : }
99 : :
100 : 0 : return ret;
101 : : }
102 : :
103 : 0 : int inotify_show_fdinfo(struct seq_file *m, struct file *f)
104 : : {
105 : 0 : 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 : : unsigned int mflags = 0;
115 : : struct inode *inode;
116 : : int ret = 0;
117 : :
118 : : if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE))
119 : : return 0;
120 : :
121 : : if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)
122 : : mflags |= FAN_MARK_IGNORED_SURV_MODIFY;
123 : :
124 : : if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
125 : : inode = igrab(mark->i.inode);
126 : : if (!inode)
127 : : goto out;
128 : : ret = seq_printf(m, "fanotify ino:%lx sdev:%x "
129 : : "mflags:%x mask:%x ignored_mask:%x ",
130 : : inode->i_ino, inode->i_sb->s_dev,
131 : : mflags, mark->mask, mark->ignored_mask);
132 : : ret |= show_mark_fhandle(m, inode);
133 : : ret |= seq_putc(m, '\n');
134 : : iput(inode);
135 : : } else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) {
136 : : struct mount *mnt = real_mount(mark->m.mnt);
137 : :
138 : : ret = seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x "
139 : : "ignored_mask:%x\n", mnt->mnt_id, mflags,
140 : : mark->mask, mark->ignored_mask);
141 : : }
142 : : out:
143 : : return ret;
144 : : }
145 : :
146 : : int fanotify_show_fdinfo(struct seq_file *m, struct file *f)
147 : : {
148 : : struct fsnotify_group *group = f->private_data;
149 : : unsigned int flags = 0;
150 : :
151 : : switch (group->priority) {
152 : : case FS_PRIO_0:
153 : : flags |= FAN_CLASS_NOTIF;
154 : : break;
155 : : case FS_PRIO_1:
156 : : flags |= FAN_CLASS_CONTENT;
157 : : break;
158 : : case FS_PRIO_2:
159 : : flags |= FAN_CLASS_PRE_CONTENT;
160 : : break;
161 : : }
162 : :
163 : : if (group->max_events == UINT_MAX)
164 : : flags |= FAN_UNLIMITED_QUEUE;
165 : :
166 : : if (group->fanotify_data.max_marks == UINT_MAX)
167 : : flags |= FAN_UNLIMITED_MARKS;
168 : :
169 : : seq_printf(m, "fanotify flags:%x event-flags:%x\n",
170 : : flags, group->fanotify_data.f_flags);
171 : :
172 : : return show_fdinfo(m, f, fanotify_fdinfo);
173 : : }
174 : :
175 : : #endif /* CONFIG_FANOTIFY */
176 : :
177 : : #endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */
178 : :
179 : : #endif /* CONFIG_PROC_FS */
|