diff options
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/Makefile | 2 | ||||
-rw-r--r-- | fs/notify/fanotify/Kconfig | 2 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 1 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 90 | ||||
-rw-r--r-- | fs/notify/fdinfo.c | 179 | ||||
-rw-r--r-- | fs/notify/fdinfo.h | 27 | ||||
-rw-r--r-- | fs/notify/inode_mark.c | 5 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 30 | ||||
-rw-r--r-- | fs/notify/notification.c | 2 |
9 files changed, 265 insertions, 73 deletions
diff --git a/fs/notify/Makefile b/fs/notify/Makefile index ae5f33a6d868..96d3420d0242 100644 --- a/fs/notify/Makefile +++ b/fs/notify/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o \ | 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 | obj-y += dnotify/ | 4 | obj-y += dnotify/ |
5 | obj-y += inotify/ | 5 | obj-y += inotify/ |
diff --git a/fs/notify/fanotify/Kconfig b/fs/notify/fanotify/Kconfig index 7dceff005a67..e5f911bd80d2 100644 --- a/fs/notify/fanotify/Kconfig +++ b/fs/notify/fanotify/Kconfig | |||
@@ -4,7 +4,7 @@ config FANOTIFY | |||
4 | select ANON_INODES | 4 | select ANON_INODES |
5 | default n | 5 | default n |
6 | ---help--- | 6 | ---help--- |
7 | Say Y here to enable fanotify suport. fanotify is a file access | 7 | Say Y here to enable fanotify support. fanotify is a file access |
8 | notification system which differs from inotify in that it sends | 8 | notification system which differs from inotify in that it sends |
9 | an open file descriptor to the userspace listener along with | 9 | an open file descriptor to the userspace listener along with |
10 | the event. | 10 | the event. |
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index aeb5b5abbd4f..0c2f9122b262 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -27,6 +27,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) | |||
27 | if ((old->path.mnt == new->path.mnt) && | 27 | if ((old->path.mnt == new->path.mnt) && |
28 | (old->path.dentry == new->path.dentry)) | 28 | (old->path.dentry == new->path.dentry)) |
29 | return true; | 29 | return true; |
30 | break; | ||
30 | case (FSNOTIFY_EVENT_NONE): | 31 | case (FSNOTIFY_EVENT_NONE): |
31 | return true; | 32 | return true; |
32 | default: | 33 | default: |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index f0e7a57bc899..9ff4a5ee6e20 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/ioctls.h> | 17 | #include <asm/ioctls.h> |
18 | 18 | ||
19 | #include "../../mount.h" | 19 | #include "../../mount.h" |
20 | #include "../fdinfo.h" | ||
20 | 21 | ||
21 | #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 | 22 | #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 |
22 | #define FANOTIFY_DEFAULT_MAX_MARKS 8192 | 23 | #define FANOTIFY_DEFAULT_MAX_MARKS 8192 |
@@ -58,7 +59,9 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, | |||
58 | return fsnotify_remove_notify_event(group); | 59 | return fsnotify_remove_notify_event(group); |
59 | } | 60 | } |
60 | 61 | ||
61 | static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | 62 | static int create_fd(struct fsnotify_group *group, |
63 | struct fsnotify_event *event, | ||
64 | struct file **file) | ||
62 | { | 65 | { |
63 | int client_fd; | 66 | int client_fd; |
64 | struct file *new_file; | 67 | struct file *new_file; |
@@ -98,7 +101,7 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | |||
98 | put_unused_fd(client_fd); | 101 | put_unused_fd(client_fd); |
99 | client_fd = PTR_ERR(new_file); | 102 | client_fd = PTR_ERR(new_file); |
100 | } else { | 103 | } else { |
101 | fd_install(client_fd, new_file); | 104 | *file = new_file; |
102 | } | 105 | } |
103 | 106 | ||
104 | return client_fd; | 107 | return client_fd; |
@@ -106,13 +109,15 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | |||
106 | 109 | ||
107 | static int fill_event_metadata(struct fsnotify_group *group, | 110 | static int fill_event_metadata(struct fsnotify_group *group, |
108 | struct fanotify_event_metadata *metadata, | 111 | struct fanotify_event_metadata *metadata, |
109 | struct fsnotify_event *event) | 112 | struct fsnotify_event *event, |
113 | struct file **file) | ||
110 | { | 114 | { |
111 | int ret = 0; | 115 | int ret = 0; |
112 | 116 | ||
113 | pr_debug("%s: group=%p metadata=%p event=%p\n", __func__, | 117 | pr_debug("%s: group=%p metadata=%p event=%p\n", __func__, |
114 | group, metadata, event); | 118 | group, metadata, event); |
115 | 119 | ||
120 | *file = NULL; | ||
116 | metadata->event_len = FAN_EVENT_METADATA_LEN; | 121 | metadata->event_len = FAN_EVENT_METADATA_LEN; |
117 | metadata->metadata_len = FAN_EVENT_METADATA_LEN; | 122 | metadata->metadata_len = FAN_EVENT_METADATA_LEN; |
118 | metadata->vers = FANOTIFY_METADATA_VERSION; | 123 | metadata->vers = FANOTIFY_METADATA_VERSION; |
@@ -121,7 +126,7 @@ static int fill_event_metadata(struct fsnotify_group *group, | |||
121 | if (unlikely(event->mask & FAN_Q_OVERFLOW)) | 126 | if (unlikely(event->mask & FAN_Q_OVERFLOW)) |
122 | metadata->fd = FAN_NOFD; | 127 | metadata->fd = FAN_NOFD; |
123 | else { | 128 | else { |
124 | metadata->fd = create_fd(group, event); | 129 | metadata->fd = create_fd(group, event, file); |
125 | if (metadata->fd < 0) | 130 | if (metadata->fd < 0) |
126 | ret = metadata->fd; | 131 | ret = metadata->fd; |
127 | } | 132 | } |
@@ -220,25 +225,6 @@ static int prepare_for_access_response(struct fsnotify_group *group, | |||
220 | return 0; | 225 | return 0; |
221 | } | 226 | } |
222 | 227 | ||
223 | static void remove_access_response(struct fsnotify_group *group, | ||
224 | struct fsnotify_event *event, | ||
225 | __s32 fd) | ||
226 | { | ||
227 | struct fanotify_response_event *re; | ||
228 | |||
229 | if (!(event->mask & FAN_ALL_PERM_EVENTS)) | ||
230 | return; | ||
231 | |||
232 | re = dequeue_re(group, fd); | ||
233 | if (!re) | ||
234 | return; | ||
235 | |||
236 | BUG_ON(re->event != event); | ||
237 | |||
238 | kmem_cache_free(fanotify_response_event_cache, re); | ||
239 | |||
240 | return; | ||
241 | } | ||
242 | #else | 228 | #else |
243 | static int prepare_for_access_response(struct fsnotify_group *group, | 229 | static int prepare_for_access_response(struct fsnotify_group *group, |
244 | struct fsnotify_event *event, | 230 | struct fsnotify_event *event, |
@@ -247,12 +233,6 @@ static int prepare_for_access_response(struct fsnotify_group *group, | |||
247 | return 0; | 233 | return 0; |
248 | } | 234 | } |
249 | 235 | ||
250 | static void remove_access_response(struct fsnotify_group *group, | ||
251 | struct fsnotify_event *event, | ||
252 | __s32 fd) | ||
253 | { | ||
254 | return; | ||
255 | } | ||
256 | #endif | 236 | #endif |
257 | 237 | ||
258 | static ssize_t copy_event_to_user(struct fsnotify_group *group, | 238 | static ssize_t copy_event_to_user(struct fsnotify_group *group, |
@@ -260,31 +240,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, | |||
260 | char __user *buf) | 240 | char __user *buf) |
261 | { | 241 | { |
262 | struct fanotify_event_metadata fanotify_event_metadata; | 242 | struct fanotify_event_metadata fanotify_event_metadata; |
243 | struct file *f; | ||
263 | int fd, ret; | 244 | int fd, ret; |
264 | 245 | ||
265 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); | 246 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); |
266 | 247 | ||
267 | ret = fill_event_metadata(group, &fanotify_event_metadata, event); | 248 | ret = fill_event_metadata(group, &fanotify_event_metadata, event, &f); |
268 | if (ret < 0) | 249 | if (ret < 0) |
269 | goto out; | 250 | goto out; |
270 | 251 | ||
271 | fd = fanotify_event_metadata.fd; | 252 | fd = fanotify_event_metadata.fd; |
272 | ret = prepare_for_access_response(group, event, fd); | ||
273 | if (ret) | ||
274 | goto out_close_fd; | ||
275 | |||
276 | ret = -EFAULT; | 253 | ret = -EFAULT; |
277 | if (copy_to_user(buf, &fanotify_event_metadata, | 254 | if (copy_to_user(buf, &fanotify_event_metadata, |
278 | fanotify_event_metadata.event_len)) | 255 | fanotify_event_metadata.event_len)) |
279 | goto out_kill_access_response; | 256 | goto out_close_fd; |
280 | 257 | ||
258 | ret = prepare_for_access_response(group, event, fd); | ||
259 | if (ret) | ||
260 | goto out_close_fd; | ||
261 | |||
262 | if (fd != FAN_NOFD) | ||
263 | fd_install(fd, f); | ||
281 | return fanotify_event_metadata.event_len; | 264 | return fanotify_event_metadata.event_len; |
282 | 265 | ||
283 | out_kill_access_response: | ||
284 | remove_access_response(group, event, fd); | ||
285 | out_close_fd: | 266 | out_close_fd: |
286 | if (fd != FAN_NOFD) | 267 | if (fd != FAN_NOFD) { |
287 | sys_close(fd); | 268 | put_unused_fd(fd); |
269 | fput(f); | ||
270 | } | ||
288 | out: | 271 | out: |
289 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 272 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
290 | if (event->mask & FAN_ALL_PERM_EVENTS) { | 273 | if (event->mask & FAN_ALL_PERM_EVENTS) { |
@@ -450,6 +433,7 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
450 | } | 433 | } |
451 | 434 | ||
452 | static const struct file_operations fanotify_fops = { | 435 | static const struct file_operations fanotify_fops = { |
436 | .show_fdinfo = fanotify_show_fdinfo, | ||
453 | .poll = fanotify_poll, | 437 | .poll = fanotify_poll, |
454 | .read = fanotify_read, | 438 | .read = fanotify_read, |
455 | .write = fanotify_write, | 439 | .write = fanotify_write, |
@@ -474,24 +458,22 @@ static int fanotify_find_path(int dfd, const char __user *filename, | |||
474 | dfd, filename, flags); | 458 | dfd, filename, flags); |
475 | 459 | ||
476 | if (filename == NULL) { | 460 | if (filename == NULL) { |
477 | struct file *file; | 461 | struct fd f = fdget(dfd); |
478 | int fput_needed; | ||
479 | 462 | ||
480 | ret = -EBADF; | 463 | ret = -EBADF; |
481 | file = fget_light(dfd, &fput_needed); | 464 | if (!f.file) |
482 | if (!file) | ||
483 | goto out; | 465 | goto out; |
484 | 466 | ||
485 | ret = -ENOTDIR; | 467 | ret = -ENOTDIR; |
486 | if ((flags & FAN_MARK_ONLYDIR) && | 468 | if ((flags & FAN_MARK_ONLYDIR) && |
487 | !(S_ISDIR(file->f_path.dentry->d_inode->i_mode))) { | 469 | !(S_ISDIR(f.file->f_path.dentry->d_inode->i_mode))) { |
488 | fput_light(file, fput_needed); | 470 | fdput(f); |
489 | goto out; | 471 | goto out; |
490 | } | 472 | } |
491 | 473 | ||
492 | *path = file->f_path; | 474 | *path = f.file->f_path; |
493 | path_get(path); | 475 | path_get(path); |
494 | fput_light(file, fput_needed); | 476 | fdput(f); |
495 | } else { | 477 | } else { |
496 | unsigned int lookup_flags = 0; | 478 | unsigned int lookup_flags = 0; |
497 | 479 | ||
@@ -780,9 +762,9 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
780 | struct inode *inode = NULL; | 762 | struct inode *inode = NULL; |
781 | struct vfsmount *mnt = NULL; | 763 | struct vfsmount *mnt = NULL; |
782 | struct fsnotify_group *group; | 764 | struct fsnotify_group *group; |
783 | struct file *filp; | 765 | struct fd f; |
784 | struct path path; | 766 | struct path path; |
785 | int ret, fput_needed; | 767 | int ret; |
786 | 768 | ||
787 | pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", | 769 | pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", |
788 | __func__, fanotify_fd, flags, dfd, pathname, mask); | 770 | __func__, fanotify_fd, flags, dfd, pathname, mask); |
@@ -816,15 +798,15 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
816 | #endif | 798 | #endif |
817 | return -EINVAL; | 799 | return -EINVAL; |
818 | 800 | ||
819 | filp = fget_light(fanotify_fd, &fput_needed); | 801 | f = fdget(fanotify_fd); |
820 | if (unlikely(!filp)) | 802 | if (unlikely(!f.file)) |
821 | return -EBADF; | 803 | return -EBADF; |
822 | 804 | ||
823 | /* verify that this is indeed an fanotify instance */ | 805 | /* verify that this is indeed an fanotify instance */ |
824 | ret = -EINVAL; | 806 | ret = -EINVAL; |
825 | if (unlikely(filp->f_op != &fanotify_fops)) | 807 | if (unlikely(f.file->f_op != &fanotify_fops)) |
826 | goto fput_and_out; | 808 | goto fput_and_out; |
827 | group = filp->private_data; | 809 | group = f.file->private_data; |
828 | 810 | ||
829 | /* | 811 | /* |
830 | * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not | 812 | * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not |
@@ -871,7 +853,7 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
871 | 853 | ||
872 | path_put(&path); | 854 | path_put(&path); |
873 | fput_and_out: | 855 | fput_and_out: |
874 | fput_light(filp, fput_needed); | 856 | fdput(f); |
875 | return ret; | 857 | return ret; |
876 | } | 858 | } |
877 | 859 | ||
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c new file mode 100644 index 000000000000..238a5930cb3c --- /dev/null +++ b/fs/notify/fdinfo.c | |||
@@ -0,0 +1,179 @@ | |||
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 | mutex_lock(&group->mark_mutex); | ||
31 | list_for_each_entry(mark, &group->marks_list, g_list) { | ||
32 | ret = show(m, mark); | ||
33 | if (ret) | ||
34 | break; | ||
35 | } | ||
36 | mutex_unlock(&group->mark_mutex); | ||
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 | 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 */ | ||
diff --git a/fs/notify/fdinfo.h b/fs/notify/fdinfo.h new file mode 100644 index 000000000000..556afda990e9 --- /dev/null +++ b/fs/notify/fdinfo.h | |||
@@ -0,0 +1,27 @@ | |||
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__ */ | ||
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 21230209c957..f31e90fc050d 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -124,8 +124,9 @@ void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) | |||
124 | * given a group and inode, find the mark associated with that combination. | 124 | * given a group and inode, find the mark associated with that combination. |
125 | * if found take a reference to that mark and return it, else return NULL | 125 | * if found take a reference to that mark and return it, else return NULL |
126 | */ | 126 | */ |
127 | struct fsnotify_mark *fsnotify_find_inode_mark_locked(struct fsnotify_group *group, | 127 | static struct fsnotify_mark *fsnotify_find_inode_mark_locked( |
128 | struct inode *inode) | 128 | struct fsnotify_group *group, |
129 | struct inode *inode) | ||
129 | { | 130 | { |
130 | struct fsnotify_mark *mark; | 131 | struct fsnotify_mark *mark; |
131 | struct hlist_node *pos; | 132 | struct hlist_node *pos; |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 463e828f1f31..228a2c2ad8d7 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/wait.h> | 40 | #include <linux/wait.h> |
41 | 41 | ||
42 | #include "inotify.h" | 42 | #include "inotify.h" |
43 | #include "../fdinfo.h" | ||
43 | 44 | ||
44 | #include <asm/ioctls.h> | 45 | #include <asm/ioctls.h> |
45 | 46 | ||
@@ -329,6 +330,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, | |||
329 | } | 330 | } |
330 | 331 | ||
331 | static const struct file_operations inotify_fops = { | 332 | static const struct file_operations inotify_fops = { |
333 | .show_fdinfo = inotify_show_fdinfo, | ||
332 | .poll = inotify_poll, | 334 | .poll = inotify_poll, |
333 | .read = inotify_read, | 335 | .read = inotify_read, |
334 | .fasync = fsnotify_fasync, | 336 | .fasync = fsnotify_fasync, |
@@ -751,16 +753,16 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, | |||
751 | struct fsnotify_group *group; | 753 | struct fsnotify_group *group; |
752 | struct inode *inode; | 754 | struct inode *inode; |
753 | struct path path; | 755 | struct path path; |
754 | struct file *filp; | 756 | struct fd f; |
755 | int ret, fput_needed; | 757 | int ret; |
756 | unsigned flags = 0; | 758 | unsigned flags = 0; |
757 | 759 | ||
758 | filp = fget_light(fd, &fput_needed); | 760 | f = fdget(fd); |
759 | if (unlikely(!filp)) | 761 | if (unlikely(!f.file)) |
760 | return -EBADF; | 762 | return -EBADF; |
761 | 763 | ||
762 | /* verify that this is indeed an inotify instance */ | 764 | /* verify that this is indeed an inotify instance */ |
763 | if (unlikely(filp->f_op != &inotify_fops)) { | 765 | if (unlikely(f.file->f_op != &inotify_fops)) { |
764 | ret = -EINVAL; | 766 | ret = -EINVAL; |
765 | goto fput_and_out; | 767 | goto fput_and_out; |
766 | } | 768 | } |
@@ -776,13 +778,13 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, | |||
776 | 778 | ||
777 | /* inode held in place by reference to path; group by fget on fd */ | 779 | /* inode held in place by reference to path; group by fget on fd */ |
778 | inode = path.dentry->d_inode; | 780 | inode = path.dentry->d_inode; |
779 | group = filp->private_data; | 781 | group = f.file->private_data; |
780 | 782 | ||
781 | /* create/update an inode mark */ | 783 | /* create/update an inode mark */ |
782 | ret = inotify_update_watch(group, inode, mask); | 784 | ret = inotify_update_watch(group, inode, mask); |
783 | path_put(&path); | 785 | path_put(&path); |
784 | fput_and_out: | 786 | fput_and_out: |
785 | fput_light(filp, fput_needed); | 787 | fdput(f); |
786 | return ret; | 788 | return ret; |
787 | } | 789 | } |
788 | 790 | ||
@@ -790,19 +792,19 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd) | |||
790 | { | 792 | { |
791 | struct fsnotify_group *group; | 793 | struct fsnotify_group *group; |
792 | struct inotify_inode_mark *i_mark; | 794 | struct inotify_inode_mark *i_mark; |
793 | struct file *filp; | 795 | struct fd f; |
794 | int ret = 0, fput_needed; | 796 | int ret = 0; |
795 | 797 | ||
796 | filp = fget_light(fd, &fput_needed); | 798 | f = fdget(fd); |
797 | if (unlikely(!filp)) | 799 | if (unlikely(!f.file)) |
798 | return -EBADF; | 800 | return -EBADF; |
799 | 801 | ||
800 | /* verify that this is indeed an inotify instance */ | 802 | /* verify that this is indeed an inotify instance */ |
801 | ret = -EINVAL; | 803 | ret = -EINVAL; |
802 | if (unlikely(filp->f_op != &inotify_fops)) | 804 | if (unlikely(f.file->f_op != &inotify_fops)) |
803 | goto out; | 805 | goto out; |
804 | 806 | ||
805 | group = filp->private_data; | 807 | group = f.file->private_data; |
806 | 808 | ||
807 | ret = -EINVAL; | 809 | ret = -EINVAL; |
808 | i_mark = inotify_idr_find(group, wd); | 810 | i_mark = inotify_idr_find(group, wd); |
@@ -817,7 +819,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd) | |||
817 | fsnotify_put_mark(&i_mark->fsn_mark); | 819 | fsnotify_put_mark(&i_mark->fsn_mark); |
818 | 820 | ||
819 | out: | 821 | out: |
820 | fput_light(filp, fput_needed); | 822 | fdput(f); |
821 | return ret; | 823 | return ret; |
822 | } | 824 | } |
823 | 825 | ||
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index b3963d8c9988..7b51b05f160c 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | /* | 19 | /* |
20 | * Basic idea behind the notification queue: An fsnotify group (like inotify) | 20 | * Basic idea behind the notification queue: An fsnotify group (like inotify) |
21 | * sends the userspace notification about events asyncronously some time after | 21 | * sends the userspace notification about events asynchronously some time after |
22 | * the event happened. When inotify gets an event it will need to add that | 22 | * the event happened. When inotify gets an event it will need to add that |
23 | * event to the group notify queue. Since a single event might need to be on | 23 | * event to the group notify queue. Since a single event might need to be on |
24 | * multiple group's notification queues we can't add the event directly to each | 24 | * multiple group's notification queues we can't add the event directly to each |