diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 14:39:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 14:39:13 -0400 |
commit | 8c8946f509a494769a8c602b5ed189df01917d39 (patch) | |
tree | dfd96bd6ca5ea6803c6d77f65ba37e04f78b2d3b /include | |
parent | 5f248c9c251c60af3403902b26e08de43964ea0b (diff) | |
parent | 1968f5eed54ce47bde488fd9a450912e4a2d7138 (diff) |
Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify
* 'for-linus' of git://git.infradead.org/users/eparis/notify: (132 commits)
fanotify: use both marks when possible
fsnotify: pass both the vfsmount mark and inode mark
fsnotify: walk the inode and vfsmount lists simultaneously
fsnotify: rework ignored mark flushing
fsnotify: remove global fsnotify groups lists
fsnotify: remove group->mask
fsnotify: remove the global masks
fsnotify: cleanup should_send_event
fanotify: use the mark in handler functions
audit: use the mark in handler functions
dnotify: use the mark in handler functions
inotify: use the mark in handler functions
fsnotify: send fsnotify_mark to groups in event handling functions
fsnotify: Exchange list heads instead of moving elements
fsnotify: srcu to protect read side of inode and vfsmount locks
fsnotify: use an explicit flag to indicate fsnotify_destroy_mark has been called
fsnotify: use _rcu functions for mark list traversal
fsnotify: place marks on object in order of group memory address
vfs/fsnotify: fsnotify_close can delay the final work in fput
fsnotify: store struct file not struct path
...
Fix up trivial delete/modify conflict in fs/notify/inotify/inotify.c.
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-generic/fcntl.h | 8 | ||||
-rw-r--r-- | include/linux/Kbuild | 1 | ||||
-rw-r--r-- | include/linux/dnotify.h | 1 | ||||
-rw-r--r-- | include/linux/fanotify.h | 105 | ||||
-rw-r--r-- | include/linux/fs.h | 16 | ||||
-rw-r--r-- | include/linux/fsnotify.h | 161 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 211 | ||||
-rw-r--r-- | include/linux/inotify.h | 185 | ||||
-rw-r--r-- | include/linux/mount.h | 6 | ||||
-rw-r--r-- | include/linux/security.h | 1 | ||||
-rw-r--r-- | include/linux/syscalls.h | 4 |
11 files changed, 360 insertions, 339 deletions
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h index fcd268ce0674..e3cbc38bdcc2 100644 --- a/include/asm-generic/fcntl.h +++ b/include/asm-generic/fcntl.h | |||
@@ -3,6 +3,14 @@ | |||
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | /* | ||
7 | * FMODE_EXEC is 0x20 | ||
8 | * FMODE_NONOTIFY is 0x1000000 | ||
9 | * These cannot be used by userspace O_* until internal and external open | ||
10 | * flags are split. | ||
11 | * -Eric Paris | ||
12 | */ | ||
13 | |||
6 | #define O_ACCMODE 00000003 | 14 | #define O_ACCMODE 00000003 |
7 | #define O_RDONLY 00000000 | 15 | #define O_RDONLY 00000000 |
8 | #define O_WRONLY 00000001 | 16 | #define O_WRONLY 00000001 |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 9aa9bcadf869..2547daf2aef2 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
@@ -210,6 +210,7 @@ unifdef-y += ethtool.h | |||
210 | unifdef-y += eventpoll.h | 210 | unifdef-y += eventpoll.h |
211 | unifdef-y += signalfd.h | 211 | unifdef-y += signalfd.h |
212 | unifdef-y += ext2_fs.h | 212 | unifdef-y += ext2_fs.h |
213 | unifdef-y += fanotify.h | ||
213 | unifdef-y += fb.h | 214 | unifdef-y += fb.h |
214 | unifdef-y += fcntl.h | 215 | unifdef-y += fcntl.h |
215 | unifdef-y += filter.h | 216 | unifdef-y += filter.h |
diff --git a/include/linux/dnotify.h b/include/linux/dnotify.h index ecc06286226d..3290555a52ee 100644 --- a/include/linux/dnotify.h +++ b/include/linux/dnotify.h | |||
@@ -28,6 +28,7 @@ struct dnotify_struct { | |||
28 | FS_CREATE | FS_DN_RENAME |\ | 28 | FS_CREATE | FS_DN_RENAME |\ |
29 | FS_MOVED_FROM | FS_MOVED_TO) | 29 | FS_MOVED_FROM | FS_MOVED_TO) |
30 | 30 | ||
31 | extern int dir_notify_enable; | ||
31 | extern void dnotify_flush(struct file *, fl_owner_t); | 32 | extern void dnotify_flush(struct file *, fl_owner_t); |
32 | extern int fcntl_dirnotify(int, struct file *, unsigned long); | 33 | extern int fcntl_dirnotify(int, struct file *, unsigned long); |
33 | 34 | ||
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h new file mode 100644 index 000000000000..f0949a57ca9d --- /dev/null +++ b/include/linux/fanotify.h | |||
@@ -0,0 +1,105 @@ | |||
1 | #ifndef _LINUX_FANOTIFY_H | ||
2 | #define _LINUX_FANOTIFY_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | /* the following events that user-space can register for */ | ||
7 | #define FAN_ACCESS 0x00000001 /* File was accessed */ | ||
8 | #define FAN_MODIFY 0x00000002 /* File was modified */ | ||
9 | #define FAN_CLOSE_WRITE 0x00000008 /* Unwrittable file closed */ | ||
10 | #define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */ | ||
11 | #define FAN_OPEN 0x00000020 /* File was opened */ | ||
12 | |||
13 | #define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ | ||
14 | |||
15 | /* FIXME currently Q's have no limit.... */ | ||
16 | #define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ | ||
17 | |||
18 | #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ | ||
19 | #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ | ||
20 | |||
21 | /* helper events */ | ||
22 | #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ | ||
23 | |||
24 | /* flags used for fanotify_init() */ | ||
25 | #define FAN_CLOEXEC 0x00000001 | ||
26 | #define FAN_NONBLOCK 0x00000002 | ||
27 | |||
28 | #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK) | ||
29 | |||
30 | /* flags used for fanotify_modify_mark() */ | ||
31 | #define FAN_MARK_ADD 0x00000001 | ||
32 | #define FAN_MARK_REMOVE 0x00000002 | ||
33 | #define FAN_MARK_DONT_FOLLOW 0x00000004 | ||
34 | #define FAN_MARK_ONLYDIR 0x00000008 | ||
35 | #define FAN_MARK_MOUNT 0x00000010 | ||
36 | #define FAN_MARK_IGNORED_MASK 0x00000020 | ||
37 | #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 | ||
38 | #define FAN_MARK_FLUSH 0x00000080 | ||
39 | |||
40 | #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ | ||
41 | FAN_MARK_REMOVE |\ | ||
42 | FAN_MARK_DONT_FOLLOW |\ | ||
43 | FAN_MARK_ONLYDIR |\ | ||
44 | FAN_MARK_MOUNT |\ | ||
45 | FAN_MARK_IGNORED_MASK |\ | ||
46 | FAN_MARK_IGNORED_SURV_MODIFY) | ||
47 | |||
48 | /* | ||
49 | * All of the events - we build the list by hand so that we can add flags in | ||
50 | * the future and not break backward compatibility. Apps will get only the | ||
51 | * events that they originally wanted. Be sure to add new events here! | ||
52 | */ | ||
53 | #define FAN_ALL_EVENTS (FAN_ACCESS |\ | ||
54 | FAN_MODIFY |\ | ||
55 | FAN_CLOSE |\ | ||
56 | FAN_OPEN) | ||
57 | |||
58 | /* | ||
59 | * All events which require a permission response from userspace | ||
60 | */ | ||
61 | #define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\ | ||
62 | FAN_ACCESS_PERM) | ||
63 | |||
64 | #define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\ | ||
65 | FAN_ALL_PERM_EVENTS |\ | ||
66 | FAN_Q_OVERFLOW) | ||
67 | |||
68 | #define FANOTIFY_METADATA_VERSION 1 | ||
69 | |||
70 | struct fanotify_event_metadata { | ||
71 | __u32 event_len; | ||
72 | __u32 vers; | ||
73 | __s32 fd; | ||
74 | __u64 mask; | ||
75 | __s64 pid; | ||
76 | } __attribute__ ((packed)); | ||
77 | |||
78 | struct fanotify_response { | ||
79 | __s32 fd; | ||
80 | __u32 response; | ||
81 | } __attribute__ ((packed)); | ||
82 | |||
83 | /* Legit userspace responses to a _PERM event */ | ||
84 | #define FAN_ALLOW 0x01 | ||
85 | #define FAN_DENY 0x02 | ||
86 | |||
87 | /* Helper functions to deal with fanotify_event_metadata buffers */ | ||
88 | #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata)) | ||
89 | |||
90 | #define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \ | ||
91 | (struct fanotify_event_metadata*)(((char *)(meta)) + \ | ||
92 | (meta)->event_len)) | ||
93 | |||
94 | #define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \ | ||
95 | (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \ | ||
96 | (long)(meta)->event_len <= (long)(len)) | ||
97 | |||
98 | #ifdef __KERNEL__ | ||
99 | |||
100 | struct fanotify_wait { | ||
101 | struct fsnotify_event *event; | ||
102 | __s32 fd; | ||
103 | }; | ||
104 | #endif /* __KERNEL__ */ | ||
105 | #endif /* _LINUX_FANOTIFY_H */ | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 9e221016a6a9..a8ccf85b8691 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -91,6 +91,9 @@ struct inodes_stat_t { | |||
91 | /* Expect random access pattern */ | 91 | /* Expect random access pattern */ |
92 | #define FMODE_RANDOM ((__force fmode_t)0x1000) | 92 | #define FMODE_RANDOM ((__force fmode_t)0x1000) |
93 | 93 | ||
94 | /* File was opened by fanotify and shouldn't generate fanotify events */ | ||
95 | #define FMODE_NONOTIFY ((__force fmode_t)16777216) /* 0x1000000 */ | ||
96 | |||
94 | /* | 97 | /* |
95 | * The below are the various read and write types that we support. Some of | 98 | * The below are the various read and write types that we support. Some of |
96 | * them include behavioral modifiers that send information down to the | 99 | * them include behavioral modifiers that send information down to the |
@@ -409,9 +412,6 @@ extern int get_max_files(void); | |||
409 | extern int sysctl_nr_open; | 412 | extern int sysctl_nr_open; |
410 | extern struct inodes_stat_t inodes_stat; | 413 | extern struct inodes_stat_t inodes_stat; |
411 | extern int leases_enable, lease_break_time; | 414 | extern int leases_enable, lease_break_time; |
412 | #ifdef CONFIG_DNOTIFY | ||
413 | extern int dir_notify_enable; | ||
414 | #endif | ||
415 | 415 | ||
416 | struct buffer_head; | 416 | struct buffer_head; |
417 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, | 417 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, |
@@ -772,12 +772,7 @@ struct inode { | |||
772 | 772 | ||
773 | #ifdef CONFIG_FSNOTIFY | 773 | #ifdef CONFIG_FSNOTIFY |
774 | __u32 i_fsnotify_mask; /* all events this inode cares about */ | 774 | __u32 i_fsnotify_mask; /* all events this inode cares about */ |
775 | struct hlist_head i_fsnotify_mark_entries; /* fsnotify mark entries */ | 775 | struct hlist_head i_fsnotify_marks; |
776 | #endif | ||
777 | |||
778 | #ifdef CONFIG_INOTIFY | ||
779 | struct list_head inotify_watches; /* watches on this inode */ | ||
780 | struct mutex inotify_mutex; /* protects the watches list */ | ||
781 | #endif | 776 | #endif |
782 | 777 | ||
783 | unsigned long i_state; | 778 | unsigned long i_state; |
@@ -2484,7 +2479,8 @@ int proc_nr_files(struct ctl_table *table, int write, | |||
2484 | int __init get_filesystem_list(char *buf); | 2479 | int __init get_filesystem_list(char *buf); |
2485 | 2480 | ||
2486 | #define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) | 2481 | #define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) |
2487 | #define OPEN_FMODE(flag) ((__force fmode_t)((flag + 1) & O_ACCMODE)) | 2482 | #define OPEN_FMODE(flag) ((__force fmode_t)(((flag + 1) & O_ACCMODE) | \ |
2483 | (flag & FMODE_NONOTIFY))) | ||
2488 | 2484 | ||
2489 | #endif /* __KERNEL__ */ | 2485 | #endif /* __KERNEL__ */ |
2490 | #endif /* _LINUX_FS_H */ | 2486 | #endif /* _LINUX_FS_H */ |
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 01755909ce81..e4e2204187ee 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h | |||
@@ -11,8 +11,6 @@ | |||
11 | * (C) Copyright 2005 Robert Love | 11 | * (C) Copyright 2005 Robert Love |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/dnotify.h> | ||
15 | #include <linux/inotify.h> | ||
16 | #include <linux/fsnotify_backend.h> | 14 | #include <linux/fsnotify_backend.h> |
17 | #include <linux/audit.h> | 15 | #include <linux/audit.h> |
18 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
@@ -21,35 +19,52 @@ | |||
21 | * fsnotify_d_instantiate - instantiate a dentry for inode | 19 | * fsnotify_d_instantiate - instantiate a dentry for inode |
22 | * Called with dcache_lock held. | 20 | * Called with dcache_lock held. |
23 | */ | 21 | */ |
24 | static inline void fsnotify_d_instantiate(struct dentry *entry, | 22 | static inline void fsnotify_d_instantiate(struct dentry *dentry, |
25 | struct inode *inode) | 23 | struct inode *inode) |
26 | { | 24 | { |
27 | __fsnotify_d_instantiate(entry, inode); | 25 | __fsnotify_d_instantiate(dentry, inode); |
28 | |||
29 | inotify_d_instantiate(entry, inode); | ||
30 | } | 26 | } |
31 | 27 | ||
32 | /* Notify this dentry's parent about a child's events. */ | 28 | /* Notify this dentry's parent about a child's events. */ |
33 | static inline void fsnotify_parent(struct dentry *dentry, __u32 mask) | 29 | static inline void fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) |
34 | { | 30 | { |
35 | __fsnotify_parent(dentry, mask); | 31 | if (!dentry) |
32 | dentry = file->f_path.dentry; | ||
33 | |||
34 | __fsnotify_parent(file, dentry, mask); | ||
35 | } | ||
36 | 36 | ||
37 | inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); | 37 | /* simple call site for access decisions */ |
38 | static inline int fsnotify_perm(struct file *file, int mask) | ||
39 | { | ||
40 | struct inode *inode = file->f_path.dentry->d_inode; | ||
41 | __u32 fsnotify_mask = 0; | ||
42 | |||
43 | if (file->f_mode & FMODE_NONOTIFY) | ||
44 | return 0; | ||
45 | if (!(mask & (MAY_READ | MAY_OPEN))) | ||
46 | return 0; | ||
47 | if (mask & MAY_OPEN) | ||
48 | fsnotify_mask = FS_OPEN_PERM; | ||
49 | else if (mask & MAY_READ) | ||
50 | fsnotify_mask = FS_ACCESS_PERM; | ||
51 | else | ||
52 | BUG(); | ||
53 | |||
54 | return fsnotify(inode, fsnotify_mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | ||
38 | } | 55 | } |
39 | 56 | ||
40 | /* | 57 | /* |
41 | * fsnotify_d_move - entry has been moved | 58 | * fsnotify_d_move - dentry has been moved |
42 | * Called with dcache_lock and entry->d_lock held. | 59 | * Called with dcache_lock and dentry->d_lock held. |
43 | */ | 60 | */ |
44 | static inline void fsnotify_d_move(struct dentry *entry) | 61 | static inline void fsnotify_d_move(struct dentry *dentry) |
45 | { | 62 | { |
46 | /* | 63 | /* |
47 | * On move we need to update entry->d_flags to indicate if the new parent | 64 | * On move we need to update dentry->d_flags to indicate if the new parent |
48 | * cares about events from this entry. | 65 | * cares about events from this dentry. |
49 | */ | 66 | */ |
50 | __fsnotify_update_dcache_flags(entry); | 67 | __fsnotify_update_dcache_flags(dentry); |
51 | |||
52 | inotify_d_move(entry); | ||
53 | } | 68 | } |
54 | 69 | ||
55 | /* | 70 | /* |
@@ -57,8 +72,6 @@ static inline void fsnotify_d_move(struct dentry *entry) | |||
57 | */ | 72 | */ |
58 | static inline void fsnotify_link_count(struct inode *inode) | 73 | static inline void fsnotify_link_count(struct inode *inode) |
59 | { | 74 | { |
60 | inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL); | ||
61 | |||
62 | fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 75 | fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
63 | } | 76 | } |
64 | 77 | ||
@@ -66,45 +79,31 @@ static inline void fsnotify_link_count(struct inode *inode) | |||
66 | * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir | 79 | * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir |
67 | */ | 80 | */ |
68 | static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, | 81 | static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, |
69 | const char *old_name, | 82 | const unsigned char *old_name, |
70 | int isdir, struct inode *target, struct dentry *moved) | 83 | int isdir, struct inode *target, struct dentry *moved) |
71 | { | 84 | { |
72 | struct inode *source = moved->d_inode; | 85 | struct inode *source = moved->d_inode; |
73 | u32 in_cookie = inotify_get_cookie(); | ||
74 | u32 fs_cookie = fsnotify_get_cookie(); | 86 | u32 fs_cookie = fsnotify_get_cookie(); |
75 | __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM); | 87 | __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM); |
76 | __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO); | 88 | __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO); |
77 | const char *new_name = moved->d_name.name; | 89 | const unsigned char *new_name = moved->d_name.name; |
78 | 90 | ||
79 | if (old_dir == new_dir) | 91 | if (old_dir == new_dir) |
80 | old_dir_mask |= FS_DN_RENAME; | 92 | old_dir_mask |= FS_DN_RENAME; |
81 | 93 | ||
82 | if (isdir) { | 94 | if (isdir) { |
83 | isdir = IN_ISDIR; | ||
84 | old_dir_mask |= FS_IN_ISDIR; | 95 | old_dir_mask |= FS_IN_ISDIR; |
85 | new_dir_mask |= FS_IN_ISDIR; | 96 | new_dir_mask |= FS_IN_ISDIR; |
86 | } | 97 | } |
87 | 98 | ||
88 | inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir, in_cookie, old_name, | ||
89 | source); | ||
90 | inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, in_cookie, new_name, | ||
91 | source); | ||
92 | |||
93 | fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); | 99 | fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); |
94 | fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie); | 100 | fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie); |
95 | 101 | ||
96 | if (target) { | 102 | if (target) |
97 | inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL); | ||
98 | inotify_inode_is_dead(target); | ||
99 | |||
100 | /* this is really a link_count change not a removal */ | ||
101 | fsnotify_link_count(target); | 103 | fsnotify_link_count(target); |
102 | } | ||
103 | 104 | ||
104 | if (source) { | 105 | if (source) |
105 | inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); | ||
106 | fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 106 | fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
107 | } | ||
108 | audit_inode_child(moved, new_dir); | 107 | audit_inode_child(moved, new_dir); |
109 | } | 108 | } |
110 | 109 | ||
@@ -117,6 +116,14 @@ static inline void fsnotify_inode_delete(struct inode *inode) | |||
117 | } | 116 | } |
118 | 117 | ||
119 | /* | 118 | /* |
119 | * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed | ||
120 | */ | ||
121 | static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt) | ||
122 | { | ||
123 | __fsnotify_vfsmount_delete(mnt); | ||
124 | } | ||
125 | |||
126 | /* | ||
120 | * fsnotify_nameremove - a filename was removed from a directory | 127 | * fsnotify_nameremove - a filename was removed from a directory |
121 | */ | 128 | */ |
122 | static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) | 129 | static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) |
@@ -126,7 +133,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) | |||
126 | if (isdir) | 133 | if (isdir) |
127 | mask |= FS_IN_ISDIR; | 134 | mask |= FS_IN_ISDIR; |
128 | 135 | ||
129 | fsnotify_parent(dentry, mask); | 136 | fsnotify_parent(NULL, dentry, mask); |
130 | } | 137 | } |
131 | 138 | ||
132 | /* | 139 | /* |
@@ -134,9 +141,6 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) | |||
134 | */ | 141 | */ |
135 | static inline void fsnotify_inoderemove(struct inode *inode) | 142 | static inline void fsnotify_inoderemove(struct inode *inode) |
136 | { | 143 | { |
137 | inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL); | ||
138 | inotify_inode_is_dead(inode); | ||
139 | |||
140 | fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 144 | fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
141 | __fsnotify_inode_delete(inode); | 145 | __fsnotify_inode_delete(inode); |
142 | } | 146 | } |
@@ -146,8 +150,6 @@ static inline void fsnotify_inoderemove(struct inode *inode) | |||
146 | */ | 150 | */ |
147 | static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) | 151 | static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) |
148 | { | 152 | { |
149 | inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name, | ||
150 | dentry->d_inode); | ||
151 | audit_inode_child(dentry, inode); | 153 | audit_inode_child(dentry, inode); |
152 | 154 | ||
153 | fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); | 155 | fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
@@ -160,8 +162,6 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) | |||
160 | */ | 162 | */ |
161 | static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) | 163 | static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) |
162 | { | 164 | { |
163 | inotify_inode_queue_event(dir, IN_CREATE, 0, new_dentry->d_name.name, | ||
164 | inode); | ||
165 | fsnotify_link_count(inode); | 165 | fsnotify_link_count(inode); |
166 | audit_inode_child(new_dentry, dir); | 166 | audit_inode_child(new_dentry, dir); |
167 | 167 | ||
@@ -176,7 +176,6 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) | |||
176 | __u32 mask = (FS_CREATE | FS_IN_ISDIR); | 176 | __u32 mask = (FS_CREATE | FS_IN_ISDIR); |
177 | struct inode *d_inode = dentry->d_inode; | 177 | struct inode *d_inode = dentry->d_inode; |
178 | 178 | ||
179 | inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode); | ||
180 | audit_inode_child(dentry, inode); | 179 | audit_inode_child(dentry, inode); |
181 | 180 | ||
182 | fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); | 181 | fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
@@ -185,52 +184,52 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) | |||
185 | /* | 184 | /* |
186 | * fsnotify_access - file was read | 185 | * fsnotify_access - file was read |
187 | */ | 186 | */ |
188 | static inline void fsnotify_access(struct dentry *dentry) | 187 | static inline void fsnotify_access(struct file *file) |
189 | { | 188 | { |
190 | struct inode *inode = dentry->d_inode; | 189 | struct inode *inode = file->f_path.dentry->d_inode; |
191 | __u32 mask = FS_ACCESS; | 190 | __u32 mask = FS_ACCESS; |
192 | 191 | ||
193 | if (S_ISDIR(inode->i_mode)) | 192 | if (S_ISDIR(inode->i_mode)) |
194 | mask |= FS_IN_ISDIR; | 193 | mask |= FS_IN_ISDIR; |
195 | 194 | ||
196 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 195 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
197 | 196 | fsnotify_parent(file, NULL, mask); | |
198 | fsnotify_parent(dentry, mask); | 197 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); |
199 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 198 | } |
200 | } | 199 | } |
201 | 200 | ||
202 | /* | 201 | /* |
203 | * fsnotify_modify - file was modified | 202 | * fsnotify_modify - file was modified |
204 | */ | 203 | */ |
205 | static inline void fsnotify_modify(struct dentry *dentry) | 204 | static inline void fsnotify_modify(struct file *file) |
206 | { | 205 | { |
207 | struct inode *inode = dentry->d_inode; | 206 | struct inode *inode = file->f_path.dentry->d_inode; |
208 | __u32 mask = FS_MODIFY; | 207 | __u32 mask = FS_MODIFY; |
209 | 208 | ||
210 | if (S_ISDIR(inode->i_mode)) | 209 | if (S_ISDIR(inode->i_mode)) |
211 | mask |= FS_IN_ISDIR; | 210 | mask |= FS_IN_ISDIR; |
212 | 211 | ||
213 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 212 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
214 | 213 | fsnotify_parent(file, NULL, mask); | |
215 | fsnotify_parent(dentry, mask); | 214 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); |
216 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 215 | } |
217 | } | 216 | } |
218 | 217 | ||
219 | /* | 218 | /* |
220 | * fsnotify_open - file was opened | 219 | * fsnotify_open - file was opened |
221 | */ | 220 | */ |
222 | static inline void fsnotify_open(struct dentry *dentry) | 221 | static inline void fsnotify_open(struct file *file) |
223 | { | 222 | { |
224 | struct inode *inode = dentry->d_inode; | 223 | struct inode *inode = file->f_path.dentry->d_inode; |
225 | __u32 mask = FS_OPEN; | 224 | __u32 mask = FS_OPEN; |
226 | 225 | ||
227 | if (S_ISDIR(inode->i_mode)) | 226 | if (S_ISDIR(inode->i_mode)) |
228 | mask |= FS_IN_ISDIR; | 227 | mask |= FS_IN_ISDIR; |
229 | 228 | ||
230 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 229 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
231 | 230 | fsnotify_parent(file, NULL, mask); | |
232 | fsnotify_parent(dentry, mask); | 231 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); |
233 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 232 | } |
234 | } | 233 | } |
235 | 234 | ||
236 | /* | 235 | /* |
@@ -238,18 +237,17 @@ static inline void fsnotify_open(struct dentry *dentry) | |||
238 | */ | 237 | */ |
239 | static inline void fsnotify_close(struct file *file) | 238 | static inline void fsnotify_close(struct file *file) |
240 | { | 239 | { |
241 | struct dentry *dentry = file->f_path.dentry; | 240 | struct inode *inode = file->f_path.dentry->d_inode; |
242 | struct inode *inode = dentry->d_inode; | ||
243 | fmode_t mode = file->f_mode; | 241 | fmode_t mode = file->f_mode; |
244 | __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; | 242 | __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; |
245 | 243 | ||
246 | if (S_ISDIR(inode->i_mode)) | 244 | if (S_ISDIR(inode->i_mode)) |
247 | mask |= FS_IN_ISDIR; | 245 | mask |= FS_IN_ISDIR; |
248 | 246 | ||
249 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 247 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
250 | 248 | fsnotify_parent(file, NULL, mask); | |
251 | fsnotify_parent(dentry, mask); | 249 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); |
252 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | 250 | } |
253 | } | 251 | } |
254 | 252 | ||
255 | /* | 253 | /* |
@@ -263,9 +261,7 @@ static inline void fsnotify_xattr(struct dentry *dentry) | |||
263 | if (S_ISDIR(inode->i_mode)) | 261 | if (S_ISDIR(inode->i_mode)) |
264 | mask |= FS_IN_ISDIR; | 262 | mask |= FS_IN_ISDIR; |
265 | 263 | ||
266 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 264 | fsnotify_parent(NULL, dentry, mask); |
267 | |||
268 | fsnotify_parent(dentry, mask); | ||
269 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 265 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
270 | } | 266 | } |
271 | 267 | ||
@@ -299,19 +295,18 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) | |||
299 | if (mask) { | 295 | if (mask) { |
300 | if (S_ISDIR(inode->i_mode)) | 296 | if (S_ISDIR(inode->i_mode)) |
301 | mask |= FS_IN_ISDIR; | 297 | mask |= FS_IN_ISDIR; |
302 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | ||
303 | 298 | ||
304 | fsnotify_parent(dentry, mask); | 299 | fsnotify_parent(NULL, dentry, mask); |
305 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 300 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
306 | } | 301 | } |
307 | } | 302 | } |
308 | 303 | ||
309 | #if defined(CONFIG_INOTIFY) || defined(CONFIG_FSNOTIFY) /* notify helpers */ | 304 | #if defined(CONFIG_FSNOTIFY) /* notify helpers */ |
310 | 305 | ||
311 | /* | 306 | /* |
312 | * fsnotify_oldname_init - save off the old filename before we change it | 307 | * fsnotify_oldname_init - save off the old filename before we change it |
313 | */ | 308 | */ |
314 | static inline const char *fsnotify_oldname_init(const char *name) | 309 | static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name) |
315 | { | 310 | { |
316 | return kstrdup(name, GFP_KERNEL); | 311 | return kstrdup(name, GFP_KERNEL); |
317 | } | 312 | } |
@@ -319,22 +314,22 @@ static inline const char *fsnotify_oldname_init(const char *name) | |||
319 | /* | 314 | /* |
320 | * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init | 315 | * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init |
321 | */ | 316 | */ |
322 | static inline void fsnotify_oldname_free(const char *old_name) | 317 | static inline void fsnotify_oldname_free(const unsigned char *old_name) |
323 | { | 318 | { |
324 | kfree(old_name); | 319 | kfree(old_name); |
325 | } | 320 | } |
326 | 321 | ||
327 | #else /* CONFIG_INOTIFY || CONFIG_FSNOTIFY */ | 322 | #else /* CONFIG_FSNOTIFY */ |
328 | 323 | ||
329 | static inline const char *fsnotify_oldname_init(const char *name) | 324 | static inline const char *fsnotify_oldname_init(const unsigned char *name) |
330 | { | 325 | { |
331 | return NULL; | 326 | return NULL; |
332 | } | 327 | } |
333 | 328 | ||
334 | static inline void fsnotify_oldname_free(const char *old_name) | 329 | static inline void fsnotify_oldname_free(const unsigned char *old_name) |
335 | { | 330 | { |
336 | } | 331 | } |
337 | 332 | ||
338 | #endif /* ! CONFIG_INOTIFY */ | 333 | #endif /* CONFIG_FSNOTIFY */ |
339 | 334 | ||
340 | #endif /* _LINUX_FS_NOTIFY_H */ | 335 | #endif /* _LINUX_FS_NOTIFY_H */ |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 4d6f47b51189..9bbfd7204b04 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -41,6 +41,10 @@ | |||
41 | #define FS_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ | 41 | #define FS_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ |
42 | #define FS_IN_IGNORED 0x00008000 /* last inotify event here */ | 42 | #define FS_IN_IGNORED 0x00008000 /* last inotify event here */ |
43 | 43 | ||
44 | #define FS_OPEN_PERM 0x00010000 /* open event in an permission hook */ | ||
45 | #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ | ||
46 | |||
47 | #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ | ||
44 | #define FS_IN_ISDIR 0x40000000 /* event occurred against dir */ | 48 | #define FS_IN_ISDIR 0x40000000 /* event occurred against dir */ |
45 | #define FS_IN_ONESHOT 0x80000000 /* only send event once */ | 49 | #define FS_IN_ONESHOT 0x80000000 /* only send event once */ |
46 | 50 | ||
@@ -58,13 +62,20 @@ | |||
58 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\ | 62 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\ |
59 | FS_DELETE) | 63 | FS_DELETE) |
60 | 64 | ||
61 | /* listeners that hard code group numbers near the top */ | 65 | #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) |
62 | #define DNOTIFY_GROUP_NUM UINT_MAX | 66 | |
63 | #define INOTIFY_GROUP_NUM (DNOTIFY_GROUP_NUM-1) | 67 | #define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ |
68 | FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \ | ||
69 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \ | ||
70 | FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \ | ||
71 | FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ | ||
72 | FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \ | ||
73 | FS_IN_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ | ||
74 | FS_DN_MULTISHOT | FS_EVENT_ON_CHILD) | ||
64 | 75 | ||
65 | struct fsnotify_group; | 76 | struct fsnotify_group; |
66 | struct fsnotify_event; | 77 | struct fsnotify_event; |
67 | struct fsnotify_mark_entry; | 78 | struct fsnotify_mark; |
68 | struct fsnotify_event_private_data; | 79 | struct fsnotify_event_private_data; |
69 | 80 | ||
70 | /* | 81 | /* |
@@ -80,10 +91,16 @@ struct fsnotify_event_private_data; | |||
80 | * valid group and inode to use to clean up. | 91 | * valid group and inode to use to clean up. |
81 | */ | 92 | */ |
82 | struct fsnotify_ops { | 93 | struct fsnotify_ops { |
83 | bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, __u32 mask); | 94 | bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, |
84 | int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); | 95 | struct fsnotify_mark *inode_mark, |
96 | struct fsnotify_mark *vfsmount_mark, | ||
97 | __u32 mask, void *data, int data_type); | ||
98 | int (*handle_event)(struct fsnotify_group *group, | ||
99 | struct fsnotify_mark *inode_mark, | ||
100 | struct fsnotify_mark *vfsmount_mark, | ||
101 | struct fsnotify_event *event); | ||
85 | void (*free_group_priv)(struct fsnotify_group *group); | 102 | void (*free_group_priv)(struct fsnotify_group *group); |
86 | void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); | 103 | void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); |
87 | void (*free_event_priv)(struct fsnotify_event_private_data *priv); | 104 | void (*free_event_priv)(struct fsnotify_event_private_data *priv); |
88 | }; | 105 | }; |
89 | 106 | ||
@@ -95,22 +112,6 @@ struct fsnotify_ops { | |||
95 | */ | 112 | */ |
96 | struct fsnotify_group { | 113 | struct fsnotify_group { |
97 | /* | 114 | /* |
98 | * global list of all groups receiving events from fsnotify. | ||
99 | * anchored by fsnotify_groups and protected by either fsnotify_grp_mutex | ||
100 | * or fsnotify_grp_srcu depending on write vs read. | ||
101 | */ | ||
102 | struct list_head group_list; | ||
103 | |||
104 | /* | ||
105 | * Defines all of the event types in which this group is interested. | ||
106 | * This mask is a bitwise OR of the FS_* events from above. Each time | ||
107 | * this mask changes for a group (if it changes) the correct functions | ||
108 | * must be called to update the global structures which indicate global | ||
109 | * interest in event types. | ||
110 | */ | ||
111 | __u32 mask; | ||
112 | |||
113 | /* | ||
114 | * How the refcnt is used is up to each group. When the refcnt hits 0 | 115 | * How the refcnt is used is up to each group. When the refcnt hits 0 |
115 | * fsnotify will clean up all of the resources associated with this group. | 116 | * fsnotify will clean up all of the resources associated with this group. |
116 | * As an example, the dnotify group will always have a refcnt=1 and that | 117 | * As an example, the dnotify group will always have a refcnt=1 and that |
@@ -119,7 +120,6 @@ struct fsnotify_group { | |||
119 | * closed. | 120 | * closed. |
120 | */ | 121 | */ |
121 | atomic_t refcnt; /* things with interest in this group */ | 122 | atomic_t refcnt; /* things with interest in this group */ |
122 | unsigned int group_num; /* simply prevents accidental group collision */ | ||
123 | 123 | ||
124 | const struct fsnotify_ops *ops; /* how this group handles things */ | 124 | const struct fsnotify_ops *ops; /* how this group handles things */ |
125 | 125 | ||
@@ -130,15 +130,12 @@ struct fsnotify_group { | |||
130 | unsigned int q_len; /* events on the queue */ | 130 | unsigned int q_len; /* events on the queue */ |
131 | unsigned int max_events; /* maximum events allowed on the list */ | 131 | unsigned int max_events; /* maximum events allowed on the list */ |
132 | 132 | ||
133 | /* stores all fastapth entries assoc with this group so they can be cleaned on unregister */ | 133 | /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ |
134 | spinlock_t mark_lock; /* protect mark_entries list */ | 134 | spinlock_t mark_lock; /* protect marks_list */ |
135 | atomic_t num_marks; /* 1 for each mark entry and 1 for not being | 135 | atomic_t num_marks; /* 1 for each mark and 1 for not being |
136 | * past the point of no return when freeing | 136 | * past the point of no return when freeing |
137 | * a group */ | 137 | * a group */ |
138 | struct list_head mark_entries; /* all inode mark entries for this group */ | 138 | struct list_head marks_list; /* all inode marks for this group */ |
139 | |||
140 | /* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */ | ||
141 | bool on_group_list; | ||
142 | 139 | ||
143 | /* groups can define private fields here or use the void *private */ | 140 | /* groups can define private fields here or use the void *private */ |
144 | union { | 141 | union { |
@@ -152,6 +149,17 @@ struct fsnotify_group { | |||
152 | struct user_struct *user; | 149 | struct user_struct *user; |
153 | } inotify_data; | 150 | } inotify_data; |
154 | #endif | 151 | #endif |
152 | #ifdef CONFIG_FANOTIFY | ||
153 | struct fanotify_group_private_data { | ||
154 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | ||
155 | /* allows a group to block waiting for a userspace response */ | ||
156 | struct mutex access_mutex; | ||
157 | struct list_head access_list; | ||
158 | wait_queue_head_t access_waitq; | ||
159 | #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ | ||
160 | int f_flags; | ||
161 | } fanotify_data; | ||
162 | #endif /* CONFIG_FANOTIFY */ | ||
155 | }; | 163 | }; |
156 | }; | 164 | }; |
157 | 165 | ||
@@ -195,35 +203,57 @@ struct fsnotify_event { | |||
195 | /* to_tell may ONLY be dereferenced during handle_event(). */ | 203 | /* to_tell may ONLY be dereferenced during handle_event(). */ |
196 | struct inode *to_tell; /* either the inode the event happened to or its parent */ | 204 | struct inode *to_tell; /* either the inode the event happened to or its parent */ |
197 | /* | 205 | /* |
198 | * depending on the event type we should have either a path or inode | 206 | * depending on the event type we should have either a file or inode |
199 | * We hold a reference on path, but NOT on inode. Since we have the ref on | 207 | * We hold a reference on file, but NOT on inode. Since we have the ref on |
200 | * the path, it may be dereferenced at any point during this object's | 208 | * the file, it may be dereferenced at any point during this object's |
201 | * lifetime. That reference is dropped when this object's refcnt hits | 209 | * lifetime. That reference is dropped when this object's refcnt hits |
202 | * 0. If this event contains an inode instead of a path, the inode may | 210 | * 0. If this event contains an inode instead of a file, the inode may |
203 | * ONLY be used during handle_event(). | 211 | * ONLY be used during handle_event(). |
204 | */ | 212 | */ |
205 | union { | 213 | union { |
206 | struct path path; | 214 | struct file *file; |
207 | struct inode *inode; | 215 | struct inode *inode; |
208 | }; | 216 | }; |
209 | /* when calling fsnotify tell it if the data is a path or inode */ | 217 | /* when calling fsnotify tell it if the data is a path or inode */ |
210 | #define FSNOTIFY_EVENT_NONE 0 | 218 | #define FSNOTIFY_EVENT_NONE 0 |
211 | #define FSNOTIFY_EVENT_PATH 1 | 219 | #define FSNOTIFY_EVENT_FILE 1 |
212 | #define FSNOTIFY_EVENT_INODE 2 | 220 | #define FSNOTIFY_EVENT_INODE 2 |
213 | #define FSNOTIFY_EVENT_FILE 3 | ||
214 | int data_type; /* which of the above union we have */ | 221 | int data_type; /* which of the above union we have */ |
215 | atomic_t refcnt; /* how many groups still are using/need to send this event */ | 222 | atomic_t refcnt; /* how many groups still are using/need to send this event */ |
216 | __u32 mask; /* the type of access, bitwise OR for FS_* event types */ | 223 | __u32 mask; /* the type of access, bitwise OR for FS_* event types */ |
217 | 224 | ||
218 | u32 sync_cookie; /* used to corrolate events, namely inotify mv events */ | 225 | u32 sync_cookie; /* used to corrolate events, namely inotify mv events */ |
219 | char *file_name; | 226 | const unsigned char *file_name; |
220 | size_t name_len; | 227 | size_t name_len; |
228 | struct pid *tgid; | ||
229 | |||
230 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | ||
231 | __u32 response; /* userspace answer to question */ | ||
232 | #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ | ||
221 | 233 | ||
222 | struct list_head private_data_list; /* groups can store private data here */ | 234 | struct list_head private_data_list; /* groups can store private data here */ |
223 | }; | 235 | }; |
224 | 236 | ||
225 | /* | 237 | /* |
226 | * a mark is simply an entry attached to an in core inode which allows an | 238 | * Inode specific fields in an fsnotify_mark |
239 | */ | ||
240 | struct fsnotify_inode_mark { | ||
241 | struct inode *inode; /* inode this mark is associated with */ | ||
242 | struct hlist_node i_list; /* list of marks by inode->i_fsnotify_marks */ | ||
243 | struct list_head free_i_list; /* tmp list used when freeing this mark */ | ||
244 | }; | ||
245 | |||
246 | /* | ||
247 | * Mount point specific fields in an fsnotify_mark | ||
248 | */ | ||
249 | struct fsnotify_vfsmount_mark { | ||
250 | struct vfsmount *mnt; /* vfsmount this mark is associated with */ | ||
251 | struct hlist_node m_list; /* list of marks by inode->i_fsnotify_marks */ | ||
252 | struct list_head free_m_list; /* tmp list used when freeing this mark */ | ||
253 | }; | ||
254 | |||
255 | /* | ||
256 | * a mark is simply an object attached to an in core inode which allows an | ||
227 | * fsnotify listener to indicate they are either no longer interested in events | 257 | * fsnotify listener to indicate they are either no longer interested in events |
228 | * of a type matching mask or only interested in those events. | 258 | * of a type matching mask or only interested in those events. |
229 | * | 259 | * |
@@ -232,19 +262,28 @@ struct fsnotify_event { | |||
232 | * (such as dnotify) will flush these when the open fd is closed and not at | 262 | * (such as dnotify) will flush these when the open fd is closed and not at |
233 | * inode eviction or modification. | 263 | * inode eviction or modification. |
234 | */ | 264 | */ |
235 | struct fsnotify_mark_entry { | 265 | struct fsnotify_mark { |
236 | __u32 mask; /* mask this mark entry is for */ | 266 | __u32 mask; /* mask this mark is for */ |
237 | /* we hold ref for each i_list and g_list. also one ref for each 'thing' | 267 | /* we hold ref for each i_list and g_list. also one ref for each 'thing' |
238 | * in kernel that found and may be using this mark. */ | 268 | * in kernel that found and may be using this mark. */ |
239 | atomic_t refcnt; /* active things looking at this mark */ | 269 | atomic_t refcnt; /* active things looking at this mark */ |
240 | struct inode *inode; /* inode this entry is associated with */ | 270 | struct fsnotify_group *group; /* group this mark is for */ |
241 | struct fsnotify_group *group; /* group this mark entry is for */ | 271 | struct list_head g_list; /* list of marks by group->i_fsnotify_marks */ |
242 | struct hlist_node i_list; /* list of mark_entries by inode->i_fsnotify_mark_entries */ | 272 | spinlock_t lock; /* protect group and inode */ |
243 | struct list_head g_list; /* list of mark_entries by group->i_fsnotify_mark_entries */ | 273 | union { |
244 | spinlock_t lock; /* protect group, inode, and killme */ | 274 | struct fsnotify_inode_mark i; |
245 | struct list_head free_i_list; /* tmp list used when freeing this mark */ | 275 | struct fsnotify_vfsmount_mark m; |
276 | }; | ||
277 | __u32 ignored_mask; /* events types to ignore */ | ||
246 | struct list_head free_g_list; /* tmp list used when freeing this mark */ | 278 | struct list_head free_g_list; /* tmp list used when freeing this mark */ |
247 | void (*free_mark)(struct fsnotify_mark_entry *entry); /* called on final put+free */ | 279 | #define FSNOTIFY_MARK_FLAG_INODE 0x01 |
280 | #define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02 | ||
281 | #define FSNOTIFY_MARK_FLAG_OBJECT_PINNED 0x04 | ||
282 | #define FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY 0x08 | ||
283 | #define FSNOTIFY_MARK_FLAG_ALIVE 0x10 | ||
284 | unsigned int flags; /* vfsmount or inode mark? */ | ||
285 | struct list_head destroy_list; | ||
286 | void (*free_mark)(struct fsnotify_mark *mark); /* called on final put+free */ | ||
248 | }; | 287 | }; |
249 | 288 | ||
250 | #ifdef CONFIG_FSNOTIFY | 289 | #ifdef CONFIG_FSNOTIFY |
@@ -252,10 +291,11 @@ struct fsnotify_mark_entry { | |||
252 | /* called from the vfs helpers */ | 291 | /* called from the vfs helpers */ |
253 | 292 | ||
254 | /* main fsnotify call to send events */ | 293 | /* main fsnotify call to send events */ |
255 | extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | 294 | extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, |
256 | const char *name, u32 cookie); | 295 | const unsigned char *name, u32 cookie); |
257 | extern void __fsnotify_parent(struct dentry *dentry, __u32 mask); | 296 | extern void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask); |
258 | extern void __fsnotify_inode_delete(struct inode *inode); | 297 | extern void __fsnotify_inode_delete(struct inode *inode); |
298 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); | ||
259 | extern u32 fsnotify_get_cookie(void); | 299 | extern u32 fsnotify_get_cookie(void); |
260 | 300 | ||
261 | static inline int fsnotify_inode_watches_children(struct inode *inode) | 301 | static inline int fsnotify_inode_watches_children(struct inode *inode) |
@@ -304,15 +344,9 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode | |||
304 | 344 | ||
305 | /* called from fsnotify listeners, such as fanotify or dnotify */ | 345 | /* called from fsnotify listeners, such as fanotify or dnotify */ |
306 | 346 | ||
307 | /* must call when a group changes its ->mask */ | ||
308 | extern void fsnotify_recalc_global_mask(void); | ||
309 | /* get a reference to an existing or create a new group */ | 347 | /* get a reference to an existing or create a new group */ |
310 | extern struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, | 348 | extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops); |
311 | __u32 mask, | 349 | /* drop reference on a group from fsnotify_alloc_group */ |
312 | const struct fsnotify_ops *ops); | ||
313 | /* run all marks associated with this group and update group->mask */ | ||
314 | extern void fsnotify_recalc_group_mask(struct fsnotify_group *group); | ||
315 | /* drop reference on a group from fsnotify_obtain_group */ | ||
316 | extern void fsnotify_put_group(struct fsnotify_group *group); | 350 | extern void fsnotify_put_group(struct fsnotify_group *group); |
317 | 351 | ||
318 | /* take a reference to an event */ | 352 | /* take a reference to an event */ |
@@ -323,8 +357,11 @@ extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struc | |||
323 | struct fsnotify_event *event); | 357 | struct fsnotify_event *event); |
324 | 358 | ||
325 | /* attach the event to the group notification queue */ | 359 | /* attach the event to the group notification queue */ |
326 | extern int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event, | 360 | extern struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group, |
327 | struct fsnotify_event_private_data *priv); | 361 | struct fsnotify_event *event, |
362 | struct fsnotify_event_private_data *priv, | ||
363 | struct fsnotify_event *(*merge)(struct list_head *, | ||
364 | struct fsnotify_event *)); | ||
328 | /* true if the group notification queue is empty */ | 365 | /* true if the group notification queue is empty */ |
329 | extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); | 366 | extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); |
330 | /* return, but do not dequeue the first event on the notification queue */ | 367 | /* return, but do not dequeue the first event on the notification queue */ |
@@ -334,38 +371,66 @@ extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group | |||
334 | 371 | ||
335 | /* functions used to manipulate the marks attached to inodes */ | 372 | /* functions used to manipulate the marks attached to inodes */ |
336 | 373 | ||
374 | /* run all marks associated with a vfsmount and update mnt->mnt_fsnotify_mask */ | ||
375 | extern void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt); | ||
337 | /* run all marks associated with an inode and update inode->i_fsnotify_mask */ | 376 | /* run all marks associated with an inode and update inode->i_fsnotify_mask */ |
338 | extern void fsnotify_recalc_inode_mask(struct inode *inode); | 377 | extern void fsnotify_recalc_inode_mask(struct inode *inode); |
339 | extern void fsnotify_init_mark(struct fsnotify_mark_entry *entry, void (*free_mark)(struct fsnotify_mark_entry *entry)); | 378 | extern void fsnotify_init_mark(struct fsnotify_mark *mark, void (*free_mark)(struct fsnotify_mark *mark)); |
340 | /* find (and take a reference) to a mark associated with group and inode */ | 379 | /* find (and take a reference) to a mark associated with group and inode */ |
341 | extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *group, struct inode *inode); | 380 | extern struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group, struct inode *inode); |
381 | /* find (and take a reference) to a mark associated with group and vfsmount */ | ||
382 | extern struct fsnotify_mark *fsnotify_find_vfsmount_mark(struct fsnotify_group *group, struct vfsmount *mnt); | ||
383 | /* copy the values from old into new */ | ||
384 | extern void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old); | ||
385 | /* set the ignored_mask of a mark */ | ||
386 | extern void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mask); | ||
387 | /* set the mask of a mark (might pin the object into memory */ | ||
388 | extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask); | ||
342 | /* attach the mark to both the group and the inode */ | 389 | /* attach the mark to both the group and the inode */ |
343 | extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode); | 390 | extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, |
391 | struct inode *inode, struct vfsmount *mnt, int allow_dups); | ||
344 | /* given a mark, flag it to be freed when all references are dropped */ | 392 | /* given a mark, flag it to be freed when all references are dropped */ |
345 | extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry); | 393 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark); |
394 | /* run all the marks in a group, and clear all of the vfsmount marks */ | ||
395 | extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group); | ||
396 | /* run all the marks in a group, and clear all of the inode marks */ | ||
397 | extern void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group); | ||
398 | /* run all the marks in a group, and clear all of the marks where mark->flags & flags is true*/ | ||
399 | extern void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, unsigned int flags); | ||
346 | /* run all the marks in a group, and flag them to be freed */ | 400 | /* run all the marks in a group, and flag them to be freed */ |
347 | extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); | 401 | extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); |
348 | extern void fsnotify_get_mark(struct fsnotify_mark_entry *entry); | 402 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); |
349 | extern void fsnotify_put_mark(struct fsnotify_mark_entry *entry); | 403 | extern void fsnotify_put_mark(struct fsnotify_mark *mark); |
350 | extern void fsnotify_unmount_inodes(struct list_head *list); | 404 | extern void fsnotify_unmount_inodes(struct list_head *list); |
351 | 405 | ||
352 | /* put here because inotify does some weird stuff when destroying watches */ | 406 | /* put here because inotify does some weird stuff when destroying watches */ |
353 | extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | 407 | extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, |
354 | void *data, int data_is, const char *name, | 408 | void *data, int data_is, |
409 | const unsigned char *name, | ||
355 | u32 cookie, gfp_t gfp); | 410 | u32 cookie, gfp_t gfp); |
356 | 411 | ||
412 | /* fanotify likes to change events after they are on lists... */ | ||
413 | extern struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event); | ||
414 | extern int fsnotify_replace_event(struct fsnotify_event_holder *old_holder, | ||
415 | struct fsnotify_event *new_event); | ||
416 | |||
357 | #else | 417 | #else |
358 | 418 | ||
359 | static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | 419 | static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, |
360 | const char *name, u32 cookie) | 420 | const unsigned char *name, u32 cookie) |
361 | {} | 421 | { |
422 | return 0; | ||
423 | } | ||
362 | 424 | ||
363 | static inline void __fsnotify_parent(struct dentry *dentry, __u32 mask) | 425 | static inline void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) |
364 | {} | 426 | {} |
365 | 427 | ||
366 | static inline void __fsnotify_inode_delete(struct inode *inode) | 428 | static inline void __fsnotify_inode_delete(struct inode *inode) |
367 | {} | 429 | {} |
368 | 430 | ||
431 | static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) | ||
432 | {} | ||
433 | |||
369 | static inline void __fsnotify_update_dcache_flags(struct dentry *dentry) | 434 | static inline void __fsnotify_update_dcache_flags(struct dentry *dentry) |
370 | {} | 435 | {} |
371 | 436 | ||
diff --git a/include/linux/inotify.h b/include/linux/inotify.h index 37ea2894b3c0..d33041e2a42a 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h | |||
@@ -51,6 +51,7 @@ struct inotify_event { | |||
51 | /* special flags */ | 51 | /* special flags */ |
52 | #define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */ | 52 | #define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */ |
53 | #define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */ | 53 | #define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */ |
54 | #define IN_EXCL_UNLINK 0x04000000 /* exclude events on unlinked objects */ | ||
54 | #define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ | 55 | #define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ |
55 | #define IN_ISDIR 0x40000000 /* event occurred against dir */ | 56 | #define IN_ISDIR 0x40000000 /* event occurred against dir */ |
56 | #define IN_ONESHOT 0x80000000 /* only send event once */ | 57 | #define IN_ONESHOT 0x80000000 /* only send event once */ |
@@ -70,177 +71,17 @@ struct inotify_event { | |||
70 | #define IN_NONBLOCK O_NONBLOCK | 71 | #define IN_NONBLOCK O_NONBLOCK |
71 | 72 | ||
72 | #ifdef __KERNEL__ | 73 | #ifdef __KERNEL__ |
73 | 74 | #include <linux/sysctl.h> | |
74 | #include <linux/dcache.h> | 75 | extern struct ctl_table inotify_table[]; /* for sysctl */ |
75 | #include <linux/fs.h> | 76 | |
76 | 77 | #define ALL_INOTIFY_BITS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ | |
77 | /* | 78 | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ |
78 | * struct inotify_watch - represents a watch request on a specific inode | 79 | IN_MOVED_TO | IN_CREATE | IN_DELETE | \ |
79 | * | 80 | IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | \ |
80 | * h_list is protected by ih->mutex of the associated inotify_handle. | 81 | IN_Q_OVERFLOW | IN_IGNORED | IN_ONLYDIR | \ |
81 | * i_list, mask are protected by inode->inotify_mutex of the associated inode. | 82 | IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \ |
82 | * ih, inode, and wd are never written to once the watch is created. | 83 | IN_ISDIR | IN_ONESHOT) |
83 | * | 84 | |
84 | * Callers must use the established inotify interfaces to access inotify_watch | 85 | #endif |
85 | * contents. The content of this structure is private to the inotify | ||
86 | * implementation. | ||
87 | */ | ||
88 | struct inotify_watch { | ||
89 | struct list_head h_list; /* entry in inotify_handle's list */ | ||
90 | struct list_head i_list; /* entry in inode's list */ | ||
91 | atomic_t count; /* reference count */ | ||
92 | struct inotify_handle *ih; /* associated inotify handle */ | ||
93 | struct inode *inode; /* associated inode */ | ||
94 | __s32 wd; /* watch descriptor */ | ||
95 | __u32 mask; /* event mask for this watch */ | ||
96 | }; | ||
97 | |||
98 | struct inotify_operations { | ||
99 | void (*handle_event)(struct inotify_watch *, u32, u32, u32, | ||
100 | const char *, struct inode *); | ||
101 | void (*destroy_watch)(struct inotify_watch *); | ||
102 | }; | ||
103 | |||
104 | #ifdef CONFIG_INOTIFY | ||
105 | |||
106 | /* Kernel API for producing events */ | ||
107 | |||
108 | extern void inotify_d_instantiate(struct dentry *, struct inode *); | ||
109 | extern void inotify_d_move(struct dentry *); | ||
110 | extern void inotify_inode_queue_event(struct inode *, __u32, __u32, | ||
111 | const char *, struct inode *); | ||
112 | extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32, | ||
113 | const char *); | ||
114 | extern void inotify_unmount_inodes(struct list_head *); | ||
115 | extern void inotify_inode_is_dead(struct inode *); | ||
116 | extern u32 inotify_get_cookie(void); | ||
117 | |||
118 | /* Kernel Consumer API */ | ||
119 | |||
120 | extern struct inotify_handle *inotify_init(const struct inotify_operations *); | ||
121 | extern void inotify_init_watch(struct inotify_watch *); | ||
122 | extern void inotify_destroy(struct inotify_handle *); | ||
123 | extern __s32 inotify_find_watch(struct inotify_handle *, struct inode *, | ||
124 | struct inotify_watch **); | ||
125 | extern __s32 inotify_find_update_watch(struct inotify_handle *, struct inode *, | ||
126 | u32); | ||
127 | extern __s32 inotify_add_watch(struct inotify_handle *, struct inotify_watch *, | ||
128 | struct inode *, __u32); | ||
129 | extern __s32 inotify_clone_watch(struct inotify_watch *, struct inotify_watch *); | ||
130 | extern void inotify_evict_watch(struct inotify_watch *); | ||
131 | extern int inotify_rm_watch(struct inotify_handle *, struct inotify_watch *); | ||
132 | extern int inotify_rm_wd(struct inotify_handle *, __u32); | ||
133 | extern void inotify_remove_watch_locked(struct inotify_handle *, | ||
134 | struct inotify_watch *); | ||
135 | extern void get_inotify_watch(struct inotify_watch *); | ||
136 | extern void put_inotify_watch(struct inotify_watch *); | ||
137 | extern int pin_inotify_watch(struct inotify_watch *); | ||
138 | extern void unpin_inotify_watch(struct inotify_watch *); | ||
139 | |||
140 | #else | ||
141 | |||
142 | static inline void inotify_d_instantiate(struct dentry *dentry, | ||
143 | struct inode *inode) | ||
144 | { | ||
145 | } | ||
146 | |||
147 | static inline void inotify_d_move(struct dentry *dentry) | ||
148 | { | ||
149 | } | ||
150 | |||
151 | static inline void inotify_inode_queue_event(struct inode *inode, | ||
152 | __u32 mask, __u32 cookie, | ||
153 | const char *filename, | ||
154 | struct inode *n_inode) | ||
155 | { | ||
156 | } | ||
157 | |||
158 | static inline void inotify_dentry_parent_queue_event(struct dentry *dentry, | ||
159 | __u32 mask, __u32 cookie, | ||
160 | const char *filename) | ||
161 | { | ||
162 | } | ||
163 | |||
164 | static inline void inotify_unmount_inodes(struct list_head *list) | ||
165 | { | ||
166 | } | ||
167 | |||
168 | static inline void inotify_inode_is_dead(struct inode *inode) | ||
169 | { | ||
170 | } | ||
171 | |||
172 | static inline u32 inotify_get_cookie(void) | ||
173 | { | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static inline struct inotify_handle *inotify_init(const struct inotify_operations *ops) | ||
178 | { | ||
179 | return ERR_PTR(-EOPNOTSUPP); | ||
180 | } | ||
181 | |||
182 | static inline void inotify_init_watch(struct inotify_watch *watch) | ||
183 | { | ||
184 | } | ||
185 | |||
186 | static inline void inotify_destroy(struct inotify_handle *ih) | ||
187 | { | ||
188 | } | ||
189 | |||
190 | static inline __s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode, | ||
191 | struct inotify_watch **watchp) | ||
192 | { | ||
193 | return -EOPNOTSUPP; | ||
194 | } | ||
195 | |||
196 | static inline __s32 inotify_find_update_watch(struct inotify_handle *ih, | ||
197 | struct inode *inode, u32 mask) | ||
198 | { | ||
199 | return -EOPNOTSUPP; | ||
200 | } | ||
201 | |||
202 | static inline __s32 inotify_add_watch(struct inotify_handle *ih, | ||
203 | struct inotify_watch *watch, | ||
204 | struct inode *inode, __u32 mask) | ||
205 | { | ||
206 | return -EOPNOTSUPP; | ||
207 | } | ||
208 | |||
209 | static inline int inotify_rm_watch(struct inotify_handle *ih, | ||
210 | struct inotify_watch *watch) | ||
211 | { | ||
212 | return -EOPNOTSUPP; | ||
213 | } | ||
214 | |||
215 | static inline int inotify_rm_wd(struct inotify_handle *ih, __u32 wd) | ||
216 | { | ||
217 | return -EOPNOTSUPP; | ||
218 | } | ||
219 | |||
220 | static inline void inotify_remove_watch_locked(struct inotify_handle *ih, | ||
221 | struct inotify_watch *watch) | ||
222 | { | ||
223 | } | ||
224 | |||
225 | static inline void get_inotify_watch(struct inotify_watch *watch) | ||
226 | { | ||
227 | } | ||
228 | |||
229 | static inline void put_inotify_watch(struct inotify_watch *watch) | ||
230 | { | ||
231 | } | ||
232 | |||
233 | extern inline int pin_inotify_watch(struct inotify_watch *watch) | ||
234 | { | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | extern inline void unpin_inotify_watch(struct inotify_watch *watch) | ||
239 | { | ||
240 | } | ||
241 | |||
242 | #endif /* CONFIG_INOTIFY */ | ||
243 | |||
244 | #endif /* __KERNEL __ */ | ||
245 | 86 | ||
246 | #endif /* _LINUX_INOTIFY_H */ | 87 | #endif /* _LINUX_INOTIFY_H */ |
diff --git a/include/linux/mount.h b/include/linux/mount.h index 4bd05474d11d..907210bd9f9c 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -56,7 +56,11 @@ struct vfsmount { | |||
56 | struct list_head mnt_mounts; /* list of children, anchored here */ | 56 | struct list_head mnt_mounts; /* list of children, anchored here */ |
57 | struct list_head mnt_child; /* and going through their mnt_child */ | 57 | struct list_head mnt_child; /* and going through their mnt_child */ |
58 | int mnt_flags; | 58 | int mnt_flags; |
59 | /* 4 bytes hole on 64bits arches */ | 59 | /* 4 bytes hole on 64bits arches without fsnotify */ |
60 | #ifdef CONFIG_FSNOTIFY | ||
61 | __u32 mnt_fsnotify_mask; | ||
62 | struct hlist_head mnt_fsnotify_marks; | ||
63 | #endif | ||
60 | const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ | 64 | const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ |
61 | struct list_head mnt_list; | 65 | struct list_head mnt_list; |
62 | struct list_head mnt_expire; /* link in fs-specific expiry list */ | 66 | struct list_head mnt_expire; /* link in fs-specific expiry list */ |
diff --git a/include/linux/security.h b/include/linux/security.h index 723a93df756a..5bcb395a49d4 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define __LINUX_SECURITY_H | 23 | #define __LINUX_SECURITY_H |
24 | 24 | ||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/fsnotify.h> | ||
26 | #include <linux/binfmts.h> | 27 | #include <linux/binfmts.h> |
27 | #include <linux/signal.h> | 28 | #include <linux/signal.h> |
28 | #include <linux/resource.h> | 29 | #include <linux/resource.h> |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a6bfd1367d2a..2ab198a1e38d 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -811,6 +811,10 @@ asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, | |||
811 | asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, | 811 | asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, |
812 | struct timespec __user *, const sigset_t __user *, | 812 | struct timespec __user *, const sigset_t __user *, |
813 | size_t); | 813 | size_t); |
814 | asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags); | ||
815 | asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, | ||
816 | u64 mask, int fd, | ||
817 | const char __user *pathname); | ||
814 | 818 | ||
815 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]); | 819 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]); |
816 | 820 | ||