diff options
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 | ||
