diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-29 12:19:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-29 12:19:53 -0400 |
commit | 79257514f532bd6e500267a061ae2cae4e3d28d5 (patch) | |
tree | bc5fcfbbe48351516cef082ca53afb3ab7ff42f1 | |
parent | 7da4221b530f0427cc09bdaa5c5c1bd86d30583d (diff) | |
parent | 721fb6fbfd2132164c2e8777cc837f9b2c1794dc (diff) |
Merge tag 'for_v4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull fsnotify updates from Jan Kara:
"Amir's patches to implement superblock fanotify watches, Xiaoming's
patch to enable reporting of thread IDs in fanotify events instead of
TGIDs (sadly the patch got mis-attributed to Amir and I've noticed
only now), and a fix of possible oops on umount caused by fsnotify
infrastructure"
* tag 'for_v4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
fsnotify: Fix busy inodes during unmount
fs: group frequently accessed fields of struct super_block together
fanotify: support reporting thread id instead of process id
fanotify: add BUILD_BUG_ON() to count the bits of fanotify constants
fsnotify: convert runtime BUG_ON() to BUILD_BUG_ON()
fanotify: deprecate uapi FAN_ALL_* constants
fanotify: simplify handling of FAN_ONDIR
fsnotify: generalize handling of extra event flags
fanotify: fix collision of internal and uapi mark flags
fanotify: store fanotify_init() flags in group's fanotify_data
fanotify: add API to attach/detach super block mark
fsnotify: send path type events to group with super block marks
fsnotify: add super block object type
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 17 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify.h | 4 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 103 | ||||
-rw-r--r-- | fs/notify/fdinfo.c | 29 | ||||
-rw-r--r-- | fs/notify/fsnotify.c | 42 | ||||
-rw-r--r-- | fs/notify/fsnotify.h | 11 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 2 | ||||
-rw-r--r-- | fs/notify/mark.c | 43 | ||||
-rw-r--r-- | fs/super.c | 2 | ||||
-rw-r--r-- | include/linux/fanotify.h | 59 | ||||
-rw-r--r-- | include/linux/fs.h | 22 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 30 | ||||
-rw-r--r-- | include/uapi/linux/fanotify.h | 25 |
13 files changed, 267 insertions, 122 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 94b52157bf8d..5769cf3ff035 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -25,7 +25,7 @@ static bool should_merge(struct fsnotify_event *old_fsn, | |||
25 | old = FANOTIFY_E(old_fsn); | 25 | old = FANOTIFY_E(old_fsn); |
26 | new = FANOTIFY_E(new_fsn); | 26 | new = FANOTIFY_E(new_fsn); |
27 | 27 | ||
28 | if (old_fsn->inode == new_fsn->inode && old->tgid == new->tgid && | 28 | if (old_fsn->inode == new_fsn->inode && old->pid == new->pid && |
29 | old->path.mnt == new->path.mnt && | 29 | old->path.mnt == new->path.mnt && |
30 | old->path.dentry == new->path.dentry) | 30 | old->path.dentry == new->path.dentry) |
31 | return true; | 31 | return true; |
@@ -131,8 +131,8 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info, | |||
131 | !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) | 131 | !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) |
132 | return false; | 132 | return false; |
133 | 133 | ||
134 | if (event_mask & FAN_ALL_OUTGOING_EVENTS & marks_mask & | 134 | if (event_mask & FANOTIFY_OUTGOING_EVENTS & |
135 | ~marks_ignored_mask) | 135 | marks_mask & ~marks_ignored_mask) |
136 | return true; | 136 | return true; |
137 | 137 | ||
138 | return false; | 138 | return false; |
@@ -171,7 +171,10 @@ struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group, | |||
171 | goto out; | 171 | goto out; |
172 | init: __maybe_unused | 172 | init: __maybe_unused |
173 | fsnotify_init_event(&event->fse, inode, mask); | 173 | fsnotify_init_event(&event->fse, inode, mask); |
174 | event->tgid = get_pid(task_tgid(current)); | 174 | if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) |
175 | event->pid = get_pid(task_pid(current)); | ||
176 | else | ||
177 | event->pid = get_pid(task_tgid(current)); | ||
175 | if (path) { | 178 | if (path) { |
176 | event->path = *path; | 179 | event->path = *path; |
177 | path_get(&event->path); | 180 | path_get(&event->path); |
@@ -205,6 +208,8 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
205 | BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); | 208 | BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); |
206 | BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR); | 209 | BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR); |
207 | 210 | ||
211 | BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 10); | ||
212 | |||
208 | if (!fanotify_should_send_event(iter_info, mask, data, data_type)) | 213 | if (!fanotify_should_send_event(iter_info, mask, data, data_type)) |
209 | return 0; | 214 | return 0; |
210 | 215 | ||
@@ -236,7 +241,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
236 | ret = fsnotify_add_event(group, fsn_event, fanotify_merge); | 241 | ret = fsnotify_add_event(group, fsn_event, fanotify_merge); |
237 | if (ret) { | 242 | if (ret) { |
238 | /* Permission events shouldn't be merged */ | 243 | /* Permission events shouldn't be merged */ |
239 | BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS); | 244 | BUG_ON(ret == 1 && mask & FANOTIFY_PERM_EVENTS); |
240 | /* Our event wasn't used in the end. Free it. */ | 245 | /* Our event wasn't used in the end. Free it. */ |
241 | fsnotify_destroy_event(group, fsn_event); | 246 | fsnotify_destroy_event(group, fsn_event); |
242 | 247 | ||
@@ -268,7 +273,7 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event) | |||
268 | 273 | ||
269 | event = FANOTIFY_E(fsn_event); | 274 | event = FANOTIFY_E(fsn_event); |
270 | path_put(&event->path); | 275 | path_put(&event->path); |
271 | put_pid(event->tgid); | 276 | put_pid(event->pid); |
272 | if (fanotify_is_perm_event(fsn_event->mask)) { | 277 | if (fanotify_is_perm_event(fsn_event->mask)) { |
273 | kmem_cache_free(fanotify_perm_event_cachep, | 278 | kmem_cache_free(fanotify_perm_event_cachep, |
274 | FANOTIFY_PE(fsn_event)); | 279 | FANOTIFY_PE(fsn_event)); |
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 8609ba06f474..ea05b8a401e7 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h | |||
@@ -19,7 +19,7 @@ struct fanotify_event_info { | |||
19 | * during this object's lifetime | 19 | * during this object's lifetime |
20 | */ | 20 | */ |
21 | struct path path; | 21 | struct path path; |
22 | struct pid *tgid; | 22 | struct pid *pid; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | /* | 25 | /* |
@@ -44,7 +44,7 @@ FANOTIFY_PE(struct fsnotify_event *fse) | |||
44 | static inline bool fanotify_is_perm_event(u32 mask) | 44 | static inline bool fanotify_is_perm_event(u32 mask) |
45 | { | 45 | { |
46 | return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) && | 46 | return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) && |
47 | mask & FAN_ALL_PERM_EVENTS; | 47 | mask & FANOTIFY_PERM_EVENTS; |
48 | } | 48 | } |
49 | 49 | ||
50 | static inline struct fanotify_event_info *FANOTIFY_E(struct fsnotify_event *fse) | 50 | static inline struct fanotify_event_info *FANOTIFY_E(struct fsnotify_event *fse) |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 69054886915b..e03be5071362 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -131,8 +131,8 @@ static int fill_event_metadata(struct fsnotify_group *group, | |||
131 | metadata->metadata_len = FAN_EVENT_METADATA_LEN; | 131 | metadata->metadata_len = FAN_EVENT_METADATA_LEN; |
132 | metadata->vers = FANOTIFY_METADATA_VERSION; | 132 | metadata->vers = FANOTIFY_METADATA_VERSION; |
133 | metadata->reserved = 0; | 133 | metadata->reserved = 0; |
134 | metadata->mask = fsn_event->mask & FAN_ALL_OUTGOING_EVENTS; | 134 | metadata->mask = fsn_event->mask & FANOTIFY_OUTGOING_EVENTS; |
135 | metadata->pid = pid_vnr(event->tgid); | 135 | metadata->pid = pid_vnr(event->pid); |
136 | if (unlikely(fsn_event->mask & FAN_Q_OVERFLOW)) | 136 | if (unlikely(fsn_event->mask & FAN_Q_OVERFLOW)) |
137 | metadata->fd = FAN_NOFD; | 137 | metadata->fd = FAN_NOFD; |
138 | else { | 138 | else { |
@@ -191,7 +191,7 @@ static int process_access_response(struct fsnotify_group *group, | |||
191 | if (fd < 0) | 191 | if (fd < 0) |
192 | return -EINVAL; | 192 | return -EINVAL; |
193 | 193 | ||
194 | if ((response & FAN_AUDIT) && !group->fanotify_data.audit) | 194 | if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT)) |
195 | return -EINVAL; | 195 | return -EINVAL; |
196 | 196 | ||
197 | event = dequeue_event(group, fd); | 197 | event = dequeue_event(group, fd); |
@@ -395,7 +395,7 @@ static int fanotify_release(struct inode *ignored, struct file *file) | |||
395 | */ | 395 | */ |
396 | while (!fsnotify_notify_queue_is_empty(group)) { | 396 | while (!fsnotify_notify_queue_is_empty(group)) { |
397 | fsn_event = fsnotify_remove_first_event(group); | 397 | fsn_event = fsnotify_remove_first_event(group); |
398 | if (!(fsn_event->mask & FAN_ALL_PERM_EVENTS)) { | 398 | if (!(fsn_event->mask & FANOTIFY_PERM_EVENTS)) { |
399 | spin_unlock(&group->notification_lock); | 399 | spin_unlock(&group->notification_lock); |
400 | fsnotify_destroy_event(group, fsn_event); | 400 | fsnotify_destroy_event(group, fsn_event); |
401 | spin_lock(&group->notification_lock); | 401 | spin_lock(&group->notification_lock); |
@@ -506,18 +506,10 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, | |||
506 | 506 | ||
507 | spin_lock(&fsn_mark->lock); | 507 | spin_lock(&fsn_mark->lock); |
508 | if (!(flags & FAN_MARK_IGNORED_MASK)) { | 508 | if (!(flags & FAN_MARK_IGNORED_MASK)) { |
509 | __u32 tmask = fsn_mark->mask & ~mask; | ||
510 | |||
511 | if (flags & FAN_MARK_ONDIR) | ||
512 | tmask &= ~FAN_ONDIR; | ||
513 | |||
514 | oldmask = fsn_mark->mask; | 509 | oldmask = fsn_mark->mask; |
515 | fsn_mark->mask = tmask; | 510 | fsn_mark->mask &= ~mask; |
516 | } else { | 511 | } else { |
517 | __u32 tmask = fsn_mark->ignored_mask & ~mask; | 512 | fsn_mark->ignored_mask &= ~mask; |
518 | if (flags & FAN_MARK_ONDIR) | ||
519 | tmask &= ~FAN_ONDIR; | ||
520 | fsn_mark->ignored_mask = tmask; | ||
521 | } | 513 | } |
522 | *destroy = !(fsn_mark->mask | fsn_mark->ignored_mask); | 514 | *destroy = !(fsn_mark->mask | fsn_mark->ignored_mask); |
523 | spin_unlock(&fsn_mark->lock); | 515 | spin_unlock(&fsn_mark->lock); |
@@ -563,6 +555,13 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | |||
563 | mask, flags); | 555 | mask, flags); |
564 | } | 556 | } |
565 | 557 | ||
558 | static int fanotify_remove_sb_mark(struct fsnotify_group *group, | ||
559 | struct super_block *sb, __u32 mask, | ||
560 | unsigned int flags) | ||
561 | { | ||
562 | return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask, flags); | ||
563 | } | ||
564 | |||
566 | static int fanotify_remove_inode_mark(struct fsnotify_group *group, | 565 | static int fanotify_remove_inode_mark(struct fsnotify_group *group, |
567 | struct inode *inode, __u32 mask, | 566 | struct inode *inode, __u32 mask, |
568 | unsigned int flags) | 567 | unsigned int flags) |
@@ -579,19 +578,10 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, | |||
579 | 578 | ||
580 | spin_lock(&fsn_mark->lock); | 579 | spin_lock(&fsn_mark->lock); |
581 | if (!(flags & FAN_MARK_IGNORED_MASK)) { | 580 | if (!(flags & FAN_MARK_IGNORED_MASK)) { |
582 | __u32 tmask = fsn_mark->mask | mask; | ||
583 | |||
584 | if (flags & FAN_MARK_ONDIR) | ||
585 | tmask |= FAN_ONDIR; | ||
586 | |||
587 | oldmask = fsn_mark->mask; | 581 | oldmask = fsn_mark->mask; |
588 | fsn_mark->mask = tmask; | 582 | fsn_mark->mask |= mask; |
589 | } else { | 583 | } else { |
590 | __u32 tmask = fsn_mark->ignored_mask | mask; | 584 | fsn_mark->ignored_mask |= mask; |
591 | if (flags & FAN_MARK_ONDIR) | ||
592 | tmask |= FAN_ONDIR; | ||
593 | |||
594 | fsn_mark->ignored_mask = tmask; | ||
595 | if (flags & FAN_MARK_IGNORED_SURV_MODIFY) | 585 | if (flags & FAN_MARK_IGNORED_SURV_MODIFY) |
596 | fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; | 586 | fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; |
597 | } | 587 | } |
@@ -658,6 +648,14 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, | |||
658 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags); | 648 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags); |
659 | } | 649 | } |
660 | 650 | ||
651 | static int fanotify_add_sb_mark(struct fsnotify_group *group, | ||
652 | struct super_block *sb, __u32 mask, | ||
653 | unsigned int flags) | ||
654 | { | ||
655 | return fanotify_add_mark(group, &sb->s_fsnotify_marks, | ||
656 | FSNOTIFY_OBJ_TYPE_SB, mask, flags); | ||
657 | } | ||
658 | |||
661 | static int fanotify_add_inode_mark(struct fsnotify_group *group, | 659 | static int fanotify_add_inode_mark(struct fsnotify_group *group, |
662 | struct inode *inode, __u32 mask, | 660 | struct inode *inode, __u32 mask, |
663 | unsigned int flags) | 661 | unsigned int flags) |
@@ -686,16 +684,16 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
686 | struct user_struct *user; | 684 | struct user_struct *user; |
687 | struct fanotify_event_info *oevent; | 685 | struct fanotify_event_info *oevent; |
688 | 686 | ||
689 | pr_debug("%s: flags=%d event_f_flags=%d\n", | 687 | pr_debug("%s: flags=%x event_f_flags=%x\n", |
690 | __func__, flags, event_f_flags); | 688 | __func__, flags, event_f_flags); |
691 | 689 | ||
692 | if (!capable(CAP_SYS_ADMIN)) | 690 | if (!capable(CAP_SYS_ADMIN)) |
693 | return -EPERM; | 691 | return -EPERM; |
694 | 692 | ||
695 | #ifdef CONFIG_AUDITSYSCALL | 693 | #ifdef CONFIG_AUDITSYSCALL |
696 | if (flags & ~(FAN_ALL_INIT_FLAGS | FAN_ENABLE_AUDIT)) | 694 | if (flags & ~(FANOTIFY_INIT_FLAGS | FAN_ENABLE_AUDIT)) |
697 | #else | 695 | #else |
698 | if (flags & ~FAN_ALL_INIT_FLAGS) | 696 | if (flags & ~FANOTIFY_INIT_FLAGS) |
699 | #endif | 697 | #endif |
700 | return -EINVAL; | 698 | return -EINVAL; |
701 | 699 | ||
@@ -731,6 +729,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
731 | } | 729 | } |
732 | 730 | ||
733 | group->fanotify_data.user = user; | 731 | group->fanotify_data.user = user; |
732 | group->fanotify_data.flags = flags; | ||
734 | atomic_inc(&user->fanotify_listeners); | 733 | atomic_inc(&user->fanotify_listeners); |
735 | group->memcg = get_mem_cgroup_from_mm(current->mm); | 734 | group->memcg = get_mem_cgroup_from_mm(current->mm); |
736 | 735 | ||
@@ -746,7 +745,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
746 | group->fanotify_data.f_flags = event_f_flags; | 745 | group->fanotify_data.f_flags = event_f_flags; |
747 | init_waitqueue_head(&group->fanotify_data.access_waitq); | 746 | init_waitqueue_head(&group->fanotify_data.access_waitq); |
748 | INIT_LIST_HEAD(&group->fanotify_data.access_list); | 747 | INIT_LIST_HEAD(&group->fanotify_data.access_list); |
749 | switch (flags & FAN_ALL_CLASS_BITS) { | 748 | switch (flags & FANOTIFY_CLASS_BITS) { |
750 | case FAN_CLASS_NOTIF: | 749 | case FAN_CLASS_NOTIF: |
751 | group->priority = FS_PRIO_0; | 750 | group->priority = FS_PRIO_0; |
752 | break; | 751 | break; |
@@ -783,7 +782,6 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
783 | fd = -EPERM; | 782 | fd = -EPERM; |
784 | if (!capable(CAP_AUDIT_WRITE)) | 783 | if (!capable(CAP_AUDIT_WRITE)) |
785 | goto out_destroy_group; | 784 | goto out_destroy_group; |
786 | group->fanotify_data.audit = true; | ||
787 | } | 785 | } |
788 | 786 | ||
789 | fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); | 787 | fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); |
@@ -805,7 +803,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
805 | struct fsnotify_group *group; | 803 | struct fsnotify_group *group; |
806 | struct fd f; | 804 | struct fd f; |
807 | struct path path; | 805 | struct path path; |
808 | u32 valid_mask = FAN_ALL_EVENTS | FAN_EVENT_ON_CHILD; | 806 | u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS; |
807 | unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS; | ||
809 | int ret; | 808 | int ret; |
810 | 809 | ||
811 | pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", | 810 | pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", |
@@ -815,8 +814,18 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
815 | if (mask & ((__u64)0xffffffff << 32)) | 814 | if (mask & ((__u64)0xffffffff << 32)) |
816 | return -EINVAL; | 815 | return -EINVAL; |
817 | 816 | ||
818 | if (flags & ~FAN_ALL_MARK_FLAGS) | 817 | if (flags & ~FANOTIFY_MARK_FLAGS) |
818 | return -EINVAL; | ||
819 | |||
820 | switch (mark_type) { | ||
821 | case FAN_MARK_INODE: | ||
822 | case FAN_MARK_MOUNT: | ||
823 | case FAN_MARK_FILESYSTEM: | ||
824 | break; | ||
825 | default: | ||
819 | return -EINVAL; | 826 | return -EINVAL; |
827 | } | ||
828 | |||
820 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { | 829 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { |
821 | case FAN_MARK_ADD: /* fallthrough */ | 830 | case FAN_MARK_ADD: /* fallthrough */ |
822 | case FAN_MARK_REMOVE: | 831 | case FAN_MARK_REMOVE: |
@@ -824,20 +833,15 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
824 | return -EINVAL; | 833 | return -EINVAL; |
825 | break; | 834 | break; |
826 | case FAN_MARK_FLUSH: | 835 | case FAN_MARK_FLUSH: |
827 | if (flags & ~(FAN_MARK_MOUNT | FAN_MARK_FLUSH)) | 836 | if (flags & ~(FANOTIFY_MARK_TYPE_BITS | FAN_MARK_FLUSH)) |
828 | return -EINVAL; | 837 | return -EINVAL; |
829 | break; | 838 | break; |
830 | default: | 839 | default: |
831 | return -EINVAL; | 840 | return -EINVAL; |
832 | } | 841 | } |
833 | 842 | ||
834 | if (mask & FAN_ONDIR) { | ||
835 | flags |= FAN_MARK_ONDIR; | ||
836 | mask &= ~FAN_ONDIR; | ||
837 | } | ||
838 | |||
839 | if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) | 843 | if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) |
840 | valid_mask |= FAN_ALL_PERM_EVENTS; | 844 | valid_mask |= FANOTIFY_PERM_EVENTS; |
841 | 845 | ||
842 | if (mask & ~valid_mask) | 846 | if (mask & ~valid_mask) |
843 | return -EINVAL; | 847 | return -EINVAL; |
@@ -857,14 +861,16 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
857 | * allowed to set permissions events. | 861 | * allowed to set permissions events. |
858 | */ | 862 | */ |
859 | ret = -EINVAL; | 863 | ret = -EINVAL; |
860 | if (mask & FAN_ALL_PERM_EVENTS && | 864 | if (mask & FANOTIFY_PERM_EVENTS && |
861 | group->priority == FS_PRIO_0) | 865 | group->priority == FS_PRIO_0) |
862 | goto fput_and_out; | 866 | goto fput_and_out; |
863 | 867 | ||
864 | if (flags & FAN_MARK_FLUSH) { | 868 | if (flags & FAN_MARK_FLUSH) { |
865 | ret = 0; | 869 | ret = 0; |
866 | if (flags & FAN_MARK_MOUNT) | 870 | if (mark_type == FAN_MARK_MOUNT) |
867 | fsnotify_clear_vfsmount_marks_by_group(group); | 871 | fsnotify_clear_vfsmount_marks_by_group(group); |
872 | else if (mark_type == FAN_MARK_FILESYSTEM) | ||
873 | fsnotify_clear_sb_marks_by_group(group); | ||
868 | else | 874 | else |
869 | fsnotify_clear_inode_marks_by_group(group); | 875 | fsnotify_clear_inode_marks_by_group(group); |
870 | goto fput_and_out; | 876 | goto fput_and_out; |
@@ -875,7 +881,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
875 | goto fput_and_out; | 881 | goto fput_and_out; |
876 | 882 | ||
877 | /* inode held in place by reference to path; group by fget on fd */ | 883 | /* inode held in place by reference to path; group by fget on fd */ |
878 | if (!(flags & FAN_MARK_MOUNT)) | 884 | if (mark_type == FAN_MARK_INODE) |
879 | inode = path.dentry->d_inode; | 885 | inode = path.dentry->d_inode; |
880 | else | 886 | else |
881 | mnt = path.mnt; | 887 | mnt = path.mnt; |
@@ -883,14 +889,18 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
883 | /* create/update an inode mark */ | 889 | /* create/update an inode mark */ |
884 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { | 890 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { |
885 | case FAN_MARK_ADD: | 891 | case FAN_MARK_ADD: |
886 | if (flags & FAN_MARK_MOUNT) | 892 | if (mark_type == FAN_MARK_MOUNT) |
887 | ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags); | 893 | ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags); |
894 | else if (mark_type == FAN_MARK_FILESYSTEM) | ||
895 | ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask, flags); | ||
888 | else | 896 | else |
889 | ret = fanotify_add_inode_mark(group, inode, mask, flags); | 897 | ret = fanotify_add_inode_mark(group, inode, mask, flags); |
890 | break; | 898 | break; |
891 | case FAN_MARK_REMOVE: | 899 | case FAN_MARK_REMOVE: |
892 | if (flags & FAN_MARK_MOUNT) | 900 | if (mark_type == FAN_MARK_MOUNT) |
893 | ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags); | 901 | ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags); |
902 | else if (mark_type == FAN_MARK_FILESYSTEM) | ||
903 | ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask, flags); | ||
894 | else | 904 | else |
895 | ret = fanotify_remove_inode_mark(group, inode, mask, flags); | 905 | ret = fanotify_remove_inode_mark(group, inode, mask, flags); |
896 | break; | 906 | break; |
@@ -934,6 +944,9 @@ COMPAT_SYSCALL_DEFINE6(fanotify_mark, | |||
934 | */ | 944 | */ |
935 | static int __init fanotify_user_setup(void) | 945 | static int __init fanotify_user_setup(void) |
936 | { | 946 | { |
947 | BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 7); | ||
948 | BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9); | ||
949 | |||
937 | fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, | 950 | fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, |
938 | SLAB_PANIC|SLAB_ACCOUNT); | 951 | SLAB_PANIC|SLAB_ACCOUNT); |
939 | fanotify_event_cachep = KMEM_CACHE(fanotify_event_info, SLAB_PANIC); | 952 | fanotify_event_cachep = KMEM_CACHE(fanotify_event_info, SLAB_PANIC); |
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c index 86fcf5814279..348a184bcdda 100644 --- a/fs/notify/fdinfo.c +++ b/fs/notify/fdinfo.c | |||
@@ -131,37 +131,20 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) | |||
131 | 131 | ||
132 | seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", | 132 | seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", |
133 | mnt->mnt_id, mflags, mark->mask, mark->ignored_mask); | 133 | mnt->mnt_id, mflags, mark->mask, mark->ignored_mask); |
134 | } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_SB) { | ||
135 | struct super_block *sb = fsnotify_conn_sb(mark->connector); | ||
136 | |||
137 | seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n", | ||
138 | sb->s_dev, mflags, mark->mask, mark->ignored_mask); | ||
134 | } | 139 | } |
135 | } | 140 | } |
136 | 141 | ||
137 | void fanotify_show_fdinfo(struct seq_file *m, struct file *f) | 142 | void fanotify_show_fdinfo(struct seq_file *m, struct file *f) |
138 | { | 143 | { |
139 | struct fsnotify_group *group = f->private_data; | 144 | struct fsnotify_group *group = f->private_data; |
140 | unsigned int flags = 0; | ||
141 | |||
142 | switch (group->priority) { | ||
143 | case FS_PRIO_0: | ||
144 | flags |= FAN_CLASS_NOTIF; | ||
145 | break; | ||
146 | case FS_PRIO_1: | ||
147 | flags |= FAN_CLASS_CONTENT; | ||
148 | break; | ||
149 | case FS_PRIO_2: | ||
150 | flags |= FAN_CLASS_PRE_CONTENT; | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | if (group->max_events == UINT_MAX) | ||
155 | flags |= FAN_UNLIMITED_QUEUE; | ||
156 | |||
157 | if (group->fanotify_data.max_marks == UINT_MAX) | ||
158 | flags |= FAN_UNLIMITED_MARKS; | ||
159 | |||
160 | if (group->fanotify_data.audit) | ||
161 | flags |= FAN_ENABLE_AUDIT; | ||
162 | 145 | ||
163 | seq_printf(m, "fanotify flags:%x event-flags:%x\n", | 146 | seq_printf(m, "fanotify flags:%x event-flags:%x\n", |
164 | flags, group->fanotify_data.f_flags); | 147 | group->fanotify_data.flags, group->fanotify_data.f_flags); |
165 | 148 | ||
166 | show_fdinfo(m, f, fanotify_fdinfo); | 149 | show_fdinfo(m, f, fanotify_fdinfo); |
167 | } | 150 | } |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index ababdbfab537..2172ba516c61 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -48,7 +48,7 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt) | |||
48 | * Called during unmount with no locks held, so needs to be safe against | 48 | * Called during unmount with no locks held, so needs to be safe against |
49 | * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block. | 49 | * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block. |
50 | */ | 50 | */ |
51 | void fsnotify_unmount_inodes(struct super_block *sb) | 51 | static void fsnotify_unmount_inodes(struct super_block *sb) |
52 | { | 52 | { |
53 | struct inode *inode, *iput_inode = NULL; | 53 | struct inode *inode, *iput_inode = NULL; |
54 | 54 | ||
@@ -96,6 +96,15 @@ void fsnotify_unmount_inodes(struct super_block *sb) | |||
96 | 96 | ||
97 | if (iput_inode) | 97 | if (iput_inode) |
98 | iput(iput_inode); | 98 | iput(iput_inode); |
99 | /* Wait for outstanding inode references from connectors */ | ||
100 | wait_var_event(&sb->s_fsnotify_inode_refs, | ||
101 | !atomic_long_read(&sb->s_fsnotify_inode_refs)); | ||
102 | } | ||
103 | |||
104 | void fsnotify_sb_delete(struct super_block *sb) | ||
105 | { | ||
106 | fsnotify_unmount_inodes(sb); | ||
107 | fsnotify_clear_marks_by_sb(sb); | ||
99 | } | 108 | } |
100 | 109 | ||
101 | /* | 110 | /* |
@@ -190,7 +199,7 @@ static int send_to_group(struct inode *to_tell, | |||
190 | struct fsnotify_iter_info *iter_info) | 199 | struct fsnotify_iter_info *iter_info) |
191 | { | 200 | { |
192 | struct fsnotify_group *group = NULL; | 201 | struct fsnotify_group *group = NULL; |
193 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); | 202 | __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); |
194 | __u32 marks_mask = 0; | 203 | __u32 marks_mask = 0; |
195 | __u32 marks_ignored_mask = 0; | 204 | __u32 marks_ignored_mask = 0; |
196 | struct fsnotify_mark *mark; | 205 | struct fsnotify_mark *mark; |
@@ -319,15 +328,17 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, | |||
319 | const unsigned char *file_name, u32 cookie) | 328 | const unsigned char *file_name, u32 cookie) |
320 | { | 329 | { |
321 | struct fsnotify_iter_info iter_info = {}; | 330 | struct fsnotify_iter_info iter_info = {}; |
322 | struct mount *mnt; | 331 | struct super_block *sb = NULL; |
332 | struct mount *mnt = NULL; | ||
333 | __u32 mnt_or_sb_mask = 0; | ||
323 | int ret = 0; | 334 | int ret = 0; |
324 | /* global tests shouldn't care about events on child only the specific event */ | 335 | __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); |
325 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); | ||
326 | 336 | ||
327 | if (data_is == FSNOTIFY_EVENT_PATH) | 337 | if (data_is == FSNOTIFY_EVENT_PATH) { |
328 | mnt = real_mount(((const struct path *)data)->mnt); | 338 | mnt = real_mount(((const struct path *)data)->mnt); |
329 | else | 339 | sb = mnt->mnt.mnt_sb; |
330 | mnt = NULL; | 340 | mnt_or_sb_mask = mnt->mnt_fsnotify_mask | sb->s_fsnotify_mask; |
341 | } | ||
331 | 342 | ||
332 | /* | 343 | /* |
333 | * Optimization: srcu_read_lock() has a memory barrier which can | 344 | * Optimization: srcu_read_lock() has a memory barrier which can |
@@ -337,16 +348,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, | |||
337 | * need SRCU to keep them "alive". | 348 | * need SRCU to keep them "alive". |
338 | */ | 349 | */ |
339 | if (!to_tell->i_fsnotify_marks && | 350 | if (!to_tell->i_fsnotify_marks && |
340 | (!mnt || !mnt->mnt_fsnotify_marks)) | 351 | (!mnt || (!mnt->mnt_fsnotify_marks && !sb->s_fsnotify_marks))) |
341 | return 0; | 352 | return 0; |
342 | /* | 353 | /* |
343 | * if this is a modify event we may need to clear the ignored masks | 354 | * if this is a modify event we may need to clear the ignored masks |
344 | * otherwise return if neither the inode nor the vfsmount care about | 355 | * otherwise return if neither the inode nor the vfsmount/sb care about |
345 | * this type of event. | 356 | * this type of event. |
346 | */ | 357 | */ |
347 | if (!(mask & FS_MODIFY) && | 358 | if (!(mask & FS_MODIFY) && |
348 | !(test_mask & to_tell->i_fsnotify_mask) && | 359 | !(test_mask & (to_tell->i_fsnotify_mask | mnt_or_sb_mask))) |
349 | !(mnt && test_mask & mnt->mnt_fsnotify_mask)) | ||
350 | return 0; | 360 | return 0; |
351 | 361 | ||
352 | iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); | 362 | iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); |
@@ -356,11 +366,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, | |||
356 | if (mnt) { | 366 | if (mnt) { |
357 | iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] = | 367 | iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] = |
358 | fsnotify_first_mark(&mnt->mnt_fsnotify_marks); | 368 | fsnotify_first_mark(&mnt->mnt_fsnotify_marks); |
369 | iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] = | ||
370 | fsnotify_first_mark(&sb->s_fsnotify_marks); | ||
359 | } | 371 | } |
360 | 372 | ||
361 | /* | 373 | /* |
362 | * We need to merge inode & vfsmount mark lists so that inode mark | 374 | * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark |
363 | * ignore masks are properly reflected for mount mark notifications. | 375 | * ignore masks are properly reflected for mount/sb mark notifications. |
364 | * That's why this traversal is so complicated... | 376 | * That's why this traversal is so complicated... |
365 | */ | 377 | */ |
366 | while (fsnotify_iter_select_report_types(&iter_info)) { | 378 | while (fsnotify_iter_select_report_types(&iter_info)) { |
@@ -386,7 +398,7 @@ static __init int fsnotify_init(void) | |||
386 | { | 398 | { |
387 | int ret; | 399 | int ret; |
388 | 400 | ||
389 | BUG_ON(hweight32(ALL_FSNOTIFY_EVENTS) != 23); | 401 | BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 23); |
390 | 402 | ||
391 | ret = init_srcu_struct(&fsnotify_mark_srcu); | 403 | ret = init_srcu_struct(&fsnotify_mark_srcu); |
392 | if (ret) | 404 | if (ret) |
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index 7902653dd577..5a00121fb219 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h | |||
@@ -21,6 +21,12 @@ static inline struct mount *fsnotify_conn_mount( | |||
21 | return container_of(conn->obj, struct mount, mnt_fsnotify_marks); | 21 | return container_of(conn->obj, struct mount, mnt_fsnotify_marks); |
22 | } | 22 | } |
23 | 23 | ||
24 | static inline struct super_block *fsnotify_conn_sb( | ||
25 | struct fsnotify_mark_connector *conn) | ||
26 | { | ||
27 | return container_of(conn->obj, struct super_block, s_fsnotify_marks); | ||
28 | } | ||
29 | |||
24 | /* destroy all events sitting in this groups notification queue */ | 30 | /* destroy all events sitting in this groups notification queue */ |
25 | extern void fsnotify_flush_notify(struct fsnotify_group *group); | 31 | extern void fsnotify_flush_notify(struct fsnotify_group *group); |
26 | 32 | ||
@@ -43,6 +49,11 @@ static inline void fsnotify_clear_marks_by_mount(struct vfsmount *mnt) | |||
43 | { | 49 | { |
44 | fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify_marks); | 50 | fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify_marks); |
45 | } | 51 | } |
52 | /* run the list of all marks associated with sb and destroy them */ | ||
53 | static inline void fsnotify_clear_marks_by_sb(struct super_block *sb) | ||
54 | { | ||
55 | fsnotify_destroy_marks(&sb->s_fsnotify_marks); | ||
56 | } | ||
46 | /* Wait until all marks queued for destruction are destroyed */ | 57 | /* Wait until all marks queued for destruction are destroyed */ |
47 | extern void fsnotify_wait_marks_destroyed(void); | 58 | extern void fsnotify_wait_marks_destroyed(void); |
48 | 59 | ||
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index ac6978d3208c..105576daca4a 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -815,7 +815,7 @@ static int __init inotify_user_setup(void) | |||
815 | BUILD_BUG_ON(IN_ISDIR != FS_ISDIR); | 815 | BUILD_BUG_ON(IN_ISDIR != FS_ISDIR); |
816 | BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT); | 816 | BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT); |
817 | 817 | ||
818 | BUG_ON(hweight32(ALL_INOTIFY_BITS) != 22); | 818 | BUILD_BUG_ON(HWEIGHT32(ALL_INOTIFY_BITS) != 22); |
819 | 819 | ||
820 | inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark, | 820 | inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark, |
821 | SLAB_PANIC|SLAB_ACCOUNT); | 821 | SLAB_PANIC|SLAB_ACCOUNT); |
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 59cdb27826de..d2dd16cb5989 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -115,6 +115,8 @@ static __u32 *fsnotify_conn_mask_p(struct fsnotify_mark_connector *conn) | |||
115 | return &fsnotify_conn_inode(conn)->i_fsnotify_mask; | 115 | return &fsnotify_conn_inode(conn)->i_fsnotify_mask; |
116 | else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) | 116 | else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) |
117 | return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask; | 117 | return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask; |
118 | else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) | ||
119 | return &fsnotify_conn_sb(conn)->s_fsnotify_mask; | ||
118 | return NULL; | 120 | return NULL; |
119 | } | 121 | } |
120 | 122 | ||
@@ -179,19 +181,24 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work) | |||
179 | } | 181 | } |
180 | } | 182 | } |
181 | 183 | ||
182 | static struct inode *fsnotify_detach_connector_from_object( | 184 | static void *fsnotify_detach_connector_from_object( |
183 | struct fsnotify_mark_connector *conn) | 185 | struct fsnotify_mark_connector *conn, |
186 | unsigned int *type) | ||
184 | { | 187 | { |
185 | struct inode *inode = NULL; | 188 | struct inode *inode = NULL; |
186 | 189 | ||
190 | *type = conn->type; | ||
187 | if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) | 191 | if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) |
188 | return NULL; | 192 | return NULL; |
189 | 193 | ||
190 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { | 194 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { |
191 | inode = fsnotify_conn_inode(conn); | 195 | inode = fsnotify_conn_inode(conn); |
192 | inode->i_fsnotify_mask = 0; | 196 | inode->i_fsnotify_mask = 0; |
197 | atomic_long_inc(&inode->i_sb->s_fsnotify_inode_refs); | ||
193 | } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { | 198 | } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { |
194 | fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; | 199 | fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; |
200 | } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) { | ||
201 | fsnotify_conn_sb(conn)->s_fsnotify_mask = 0; | ||
195 | } | 202 | } |
196 | 203 | ||
197 | rcu_assign_pointer(*(conn->obj), NULL); | 204 | rcu_assign_pointer(*(conn->obj), NULL); |
@@ -211,10 +218,29 @@ static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark) | |||
211 | fsnotify_put_group(group); | 218 | fsnotify_put_group(group); |
212 | } | 219 | } |
213 | 220 | ||
221 | /* Drop object reference originally held by a connector */ | ||
222 | static void fsnotify_drop_object(unsigned int type, void *objp) | ||
223 | { | ||
224 | struct inode *inode; | ||
225 | struct super_block *sb; | ||
226 | |||
227 | if (!objp) | ||
228 | return; | ||
229 | /* Currently only inode references are passed to be dropped */ | ||
230 | if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE)) | ||
231 | return; | ||
232 | inode = objp; | ||
233 | sb = inode->i_sb; | ||
234 | iput(inode); | ||
235 | if (atomic_long_dec_and_test(&sb->s_fsnotify_inode_refs)) | ||
236 | wake_up_var(&sb->s_fsnotify_inode_refs); | ||
237 | } | ||
238 | |||
214 | void fsnotify_put_mark(struct fsnotify_mark *mark) | 239 | void fsnotify_put_mark(struct fsnotify_mark *mark) |
215 | { | 240 | { |
216 | struct fsnotify_mark_connector *conn; | 241 | struct fsnotify_mark_connector *conn; |
217 | struct inode *inode = NULL; | 242 | void *objp = NULL; |
243 | unsigned int type = FSNOTIFY_OBJ_TYPE_DETACHED; | ||
218 | bool free_conn = false; | 244 | bool free_conn = false; |
219 | 245 | ||
220 | /* Catch marks that were actually never attached to object */ | 246 | /* Catch marks that were actually never attached to object */ |
@@ -234,7 +260,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) | |||
234 | conn = mark->connector; | 260 | conn = mark->connector; |
235 | hlist_del_init_rcu(&mark->obj_list); | 261 | hlist_del_init_rcu(&mark->obj_list); |
236 | if (hlist_empty(&conn->list)) { | 262 | if (hlist_empty(&conn->list)) { |
237 | inode = fsnotify_detach_connector_from_object(conn); | 263 | objp = fsnotify_detach_connector_from_object(conn, &type); |
238 | free_conn = true; | 264 | free_conn = true; |
239 | } else { | 265 | } else { |
240 | __fsnotify_recalc_mask(conn); | 266 | __fsnotify_recalc_mask(conn); |
@@ -242,7 +268,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) | |||
242 | mark->connector = NULL; | 268 | mark->connector = NULL; |
243 | spin_unlock(&conn->lock); | 269 | spin_unlock(&conn->lock); |
244 | 270 | ||
245 | iput(inode); | 271 | fsnotify_drop_object(type, objp); |
246 | 272 | ||
247 | if (free_conn) { | 273 | if (free_conn) { |
248 | spin_lock(&destroy_lock); | 274 | spin_lock(&destroy_lock); |
@@ -709,7 +735,8 @@ void fsnotify_destroy_marks(fsnotify_connp_t *connp) | |||
709 | { | 735 | { |
710 | struct fsnotify_mark_connector *conn; | 736 | struct fsnotify_mark_connector *conn; |
711 | struct fsnotify_mark *mark, *old_mark = NULL; | 737 | struct fsnotify_mark *mark, *old_mark = NULL; |
712 | struct inode *inode; | 738 | void *objp; |
739 | unsigned int type; | ||
713 | 740 | ||
714 | conn = fsnotify_grab_connector(connp); | 741 | conn = fsnotify_grab_connector(connp); |
715 | if (!conn) | 742 | if (!conn) |
@@ -735,11 +762,11 @@ void fsnotify_destroy_marks(fsnotify_connp_t *connp) | |||
735 | * mark references get dropped. It would lead to strange results such | 762 | * mark references get dropped. It would lead to strange results such |
736 | * as delaying inode deletion or blocking unmount. | 763 | * as delaying inode deletion or blocking unmount. |
737 | */ | 764 | */ |
738 | inode = fsnotify_detach_connector_from_object(conn); | 765 | objp = fsnotify_detach_connector_from_object(conn, &type); |
739 | spin_unlock(&conn->lock); | 766 | spin_unlock(&conn->lock); |
740 | if (old_mark) | 767 | if (old_mark) |
741 | fsnotify_put_mark(old_mark); | 768 | fsnotify_put_mark(old_mark); |
742 | iput(inode); | 769 | fsnotify_drop_object(type, objp); |
743 | } | 770 | } |
744 | 771 | ||
745 | /* | 772 | /* |
diff --git a/fs/super.c b/fs/super.c index f3a8c008e164..ca53a08497ed 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -442,7 +442,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
442 | sync_filesystem(sb); | 442 | sync_filesystem(sb); |
443 | sb->s_flags &= ~SB_ACTIVE; | 443 | sb->s_flags &= ~SB_ACTIVE; |
444 | 444 | ||
445 | fsnotify_unmount_inodes(sb); | 445 | fsnotify_sb_delete(sb); |
446 | cgroup_writeback_umount(); | 446 | cgroup_writeback_umount(); |
447 | 447 | ||
448 | evict_inodes(sb); | 448 | evict_inodes(sb); |
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 096c96f4f16a..a5a60691e48b 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h | |||
@@ -4,6 +4,61 @@ | |||
4 | 4 | ||
5 | #include <uapi/linux/fanotify.h> | 5 | #include <uapi/linux/fanotify.h> |
6 | 6 | ||
7 | /* not valid from userspace, only kernel internal */ | 7 | #define FAN_GROUP_FLAG(group, flag) \ |
8 | #define FAN_MARK_ONDIR 0x00000100 | 8 | ((group)->fanotify_data.flags & (flag)) |
9 | |||
10 | /* | ||
11 | * Flags allowed to be passed from/to userspace. | ||
12 | * | ||
13 | * We intentionally do not add new bits to the old FAN_ALL_* constants, because | ||
14 | * they are uapi exposed constants. If there are programs out there using | ||
15 | * these constant, the programs may break if re-compiled with new uapi headers | ||
16 | * and then run on an old kernel. | ||
17 | */ | ||
18 | #define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ | ||
19 | FAN_CLASS_PRE_CONTENT) | ||
20 | |||
21 | #define FANOTIFY_INIT_FLAGS (FANOTIFY_CLASS_BITS | \ | ||
22 | FAN_REPORT_TID | \ | ||
23 | FAN_CLOEXEC | FAN_NONBLOCK | \ | ||
24 | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS) | ||
25 | |||
26 | #define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \ | ||
27 | FAN_MARK_FILESYSTEM) | ||
28 | |||
29 | #define FANOTIFY_MARK_FLAGS (FANOTIFY_MARK_TYPE_BITS | \ | ||
30 | FAN_MARK_ADD | \ | ||
31 | FAN_MARK_REMOVE | \ | ||
32 | FAN_MARK_DONT_FOLLOW | \ | ||
33 | FAN_MARK_ONLYDIR | \ | ||
34 | FAN_MARK_IGNORED_MASK | \ | ||
35 | FAN_MARK_IGNORED_SURV_MODIFY | \ | ||
36 | FAN_MARK_FLUSH) | ||
37 | |||
38 | /* Events that user can request to be notified on */ | ||
39 | #define FANOTIFY_EVENTS (FAN_ACCESS | FAN_MODIFY | \ | ||
40 | FAN_CLOSE | FAN_OPEN) | ||
41 | |||
42 | /* Events that require a permission response from user */ | ||
43 | #define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM) | ||
44 | |||
45 | /* Extra flags that may be reported with event or control handling of events */ | ||
46 | #define FANOTIFY_EVENT_FLAGS (FAN_EVENT_ON_CHILD | FAN_ONDIR) | ||
47 | |||
48 | /* Events that may be reported to user */ | ||
49 | #define FANOTIFY_OUTGOING_EVENTS (FANOTIFY_EVENTS | \ | ||
50 | FANOTIFY_PERM_EVENTS | \ | ||
51 | FAN_Q_OVERFLOW) | ||
52 | |||
53 | #define ALL_FANOTIFY_EVENT_BITS (FANOTIFY_OUTGOING_EVENTS | \ | ||
54 | FANOTIFY_EVENT_FLAGS) | ||
55 | |||
56 | /* Do not use these old uapi constants internally */ | ||
57 | #undef FAN_ALL_CLASS_BITS | ||
58 | #undef FAN_ALL_INIT_FLAGS | ||
59 | #undef FAN_ALL_MARK_FLAGS | ||
60 | #undef FAN_ALL_EVENTS | ||
61 | #undef FAN_ALL_PERM_EVENTS | ||
62 | #undef FAN_ALL_OUTGOING_EVENTS | ||
63 | |||
9 | #endif /* _LINUX_FANOTIFY_H */ | 64 | #endif /* _LINUX_FANOTIFY_H */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 771341470bce..8252df30b9a1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1412,17 +1412,26 @@ struct super_block { | |||
1412 | 1412 | ||
1413 | struct sb_writers s_writers; | 1413 | struct sb_writers s_writers; |
1414 | 1414 | ||
1415 | /* | ||
1416 | * Keep s_fs_info, s_time_gran, s_fsnotify_mask, and | ||
1417 | * s_fsnotify_marks together for cache efficiency. They are frequently | ||
1418 | * accessed and rarely modified. | ||
1419 | */ | ||
1420 | void *s_fs_info; /* Filesystem private info */ | ||
1421 | |||
1422 | /* Granularity of c/m/atime in ns (cannot be worse than a second) */ | ||
1423 | u32 s_time_gran; | ||
1424 | #ifdef CONFIG_FSNOTIFY | ||
1425 | __u32 s_fsnotify_mask; | ||
1426 | struct fsnotify_mark_connector __rcu *s_fsnotify_marks; | ||
1427 | #endif | ||
1428 | |||
1415 | char s_id[32]; /* Informational name */ | 1429 | char s_id[32]; /* Informational name */ |
1416 | uuid_t s_uuid; /* UUID */ | 1430 | uuid_t s_uuid; /* UUID */ |
1417 | 1431 | ||
1418 | void *s_fs_info; /* Filesystem private info */ | ||
1419 | unsigned int s_max_links; | 1432 | unsigned int s_max_links; |
1420 | fmode_t s_mode; | 1433 | fmode_t s_mode; |
1421 | 1434 | ||
1422 | /* Granularity of c/m/atime in ns. | ||
1423 | Cannot be worse than a second */ | ||
1424 | u32 s_time_gran; | ||
1425 | |||
1426 | /* | 1435 | /* |
1427 | * The next field is for VFS *only*. No filesystems have any business | 1436 | * The next field is for VFS *only*. No filesystems have any business |
1428 | * even looking at it. You had been warned. | 1437 | * even looking at it. You had been warned. |
@@ -1447,6 +1456,9 @@ struct super_block { | |||
1447 | /* Number of inodes with nlink == 0 but still referenced */ | 1456 | /* Number of inodes with nlink == 0 but still referenced */ |
1448 | atomic_long_t s_remove_count; | 1457 | atomic_long_t s_remove_count; |
1449 | 1458 | ||
1459 | /* Pending fsnotify inode refs */ | ||
1460 | atomic_long_t s_fsnotify_inode_refs; | ||
1461 | |||
1450 | /* Being remounted read-only */ | 1462 | /* Being remounted read-only */ |
1451 | int s_readonly_remount; | 1463 | int s_readonly_remount; |
1452 | 1464 | ||
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index b8f4182f42f1..135b973e44d1 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -68,15 +68,20 @@ | |||
68 | 68 | ||
69 | #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM) | 69 | #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM) |
70 | 70 | ||
71 | /* Events that can be reported to backends */ | ||
71 | #define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ | 72 | #define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ |
72 | FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \ | 73 | FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \ |
73 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \ | 74 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \ |
74 | FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \ | 75 | FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \ |
75 | FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ | 76 | FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ |
76 | FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \ | 77 | FS_OPEN_PERM | FS_ACCESS_PERM | FS_DN_RENAME) |
77 | FS_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ | 78 | |
79 | /* Extra flags that may be reported with event or control handling of events */ | ||
80 | #define ALL_FSNOTIFY_FLAGS (FS_EXCL_UNLINK | FS_ISDIR | FS_IN_ONESHOT | \ | ||
78 | FS_DN_MULTISHOT | FS_EVENT_ON_CHILD) | 81 | FS_DN_MULTISHOT | FS_EVENT_ON_CHILD) |
79 | 82 | ||
83 | #define ALL_FSNOTIFY_BITS (ALL_FSNOTIFY_EVENTS | ALL_FSNOTIFY_FLAGS) | ||
84 | |||
80 | struct fsnotify_group; | 85 | struct fsnotify_group; |
81 | struct fsnotify_event; | 86 | struct fsnotify_event; |
82 | struct fsnotify_mark; | 87 | struct fsnotify_mark; |
@@ -189,10 +194,10 @@ struct fsnotify_group { | |||
189 | /* allows a group to block waiting for a userspace response */ | 194 | /* allows a group to block waiting for a userspace response */ |
190 | struct list_head access_list; | 195 | struct list_head access_list; |
191 | wait_queue_head_t access_waitq; | 196 | wait_queue_head_t access_waitq; |
192 | int f_flags; | 197 | int flags; /* flags from fanotify_init() */ |
198 | int f_flags; /* event_f_flags from fanotify_init() */ | ||
193 | unsigned int max_marks; | 199 | unsigned int max_marks; |
194 | struct user_struct *user; | 200 | struct user_struct *user; |
195 | bool audit; | ||
196 | } fanotify_data; | 201 | } fanotify_data; |
197 | #endif /* CONFIG_FANOTIFY */ | 202 | #endif /* CONFIG_FANOTIFY */ |
198 | }; | 203 | }; |
@@ -206,12 +211,14 @@ struct fsnotify_group { | |||
206 | enum fsnotify_obj_type { | 211 | enum fsnotify_obj_type { |
207 | FSNOTIFY_OBJ_TYPE_INODE, | 212 | FSNOTIFY_OBJ_TYPE_INODE, |
208 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, | 213 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, |
214 | FSNOTIFY_OBJ_TYPE_SB, | ||
209 | FSNOTIFY_OBJ_TYPE_COUNT, | 215 | FSNOTIFY_OBJ_TYPE_COUNT, |
210 | FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT | 216 | FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT |
211 | }; | 217 | }; |
212 | 218 | ||
213 | #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) | 219 | #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) |
214 | #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) | 220 | #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) |
221 | #define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) | ||
215 | #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) | 222 | #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) |
216 | 223 | ||
217 | static inline bool fsnotify_valid_obj_type(unsigned int type) | 224 | static inline bool fsnotify_valid_obj_type(unsigned int type) |
@@ -255,6 +262,7 @@ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ | |||
255 | 262 | ||
256 | FSNOTIFY_ITER_FUNCS(inode, INODE) | 263 | FSNOTIFY_ITER_FUNCS(inode, INODE) |
257 | FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) | 264 | FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) |
265 | FSNOTIFY_ITER_FUNCS(sb, SB) | ||
258 | 266 | ||
259 | #define fsnotify_foreach_obj_type(type) \ | 267 | #define fsnotify_foreach_obj_type(type) \ |
260 | for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) | 268 | for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) |
@@ -267,8 +275,8 @@ struct fsnotify_mark_connector; | |||
267 | typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; | 275 | typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; |
268 | 276 | ||
269 | /* | 277 | /* |
270 | * Inode / vfsmount point to this structure which tracks all marks attached to | 278 | * Inode/vfsmount/sb point to this structure which tracks all marks attached to |
271 | * the inode / vfsmount. The reference to inode / vfsmount is held by this | 279 | * the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this |
272 | * structure. We destroy this structure when there are no more marks attached | 280 | * structure. We destroy this structure when there are no more marks attached |
273 | * to it. The structure is protected by fsnotify_mark_srcu. | 281 | * to it. The structure is protected by fsnotify_mark_srcu. |
274 | */ | 282 | */ |
@@ -335,6 +343,7 @@ extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int dat | |||
335 | extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask); | 343 | extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask); |
336 | extern void __fsnotify_inode_delete(struct inode *inode); | 344 | extern void __fsnotify_inode_delete(struct inode *inode); |
337 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); | 345 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); |
346 | extern void fsnotify_sb_delete(struct super_block *sb); | ||
338 | extern u32 fsnotify_get_cookie(void); | 347 | extern u32 fsnotify_get_cookie(void); |
339 | 348 | ||
340 | static inline int fsnotify_inode_watches_children(struct inode *inode) | 349 | static inline int fsnotify_inode_watches_children(struct inode *inode) |
@@ -455,9 +464,13 @@ static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *gr | |||
455 | { | 464 | { |
456 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL); | 465 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL); |
457 | } | 466 | } |
467 | /* run all the marks in a group, and clear all of the sn marks */ | ||
468 | static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group) | ||
469 | { | ||
470 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_SB_FL); | ||
471 | } | ||
458 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); | 472 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); |
459 | extern void fsnotify_put_mark(struct fsnotify_mark *mark); | 473 | extern void fsnotify_put_mark(struct fsnotify_mark *mark); |
460 | extern void fsnotify_unmount_inodes(struct super_block *sb); | ||
461 | extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); | 474 | extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); |
462 | extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); | 475 | extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); |
463 | 476 | ||
@@ -484,6 +497,9 @@ static inline void __fsnotify_inode_delete(struct inode *inode) | |||
484 | static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) | 497 | static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) |
485 | {} | 498 | {} |
486 | 499 | ||
500 | static inline void fsnotify_sb_delete(struct super_block *sb) | ||
501 | {} | ||
502 | |||
487 | static inline void fsnotify_update_flags(struct dentry *dentry) | 503 | static inline void fsnotify_update_flags(struct dentry *dentry) |
488 | {} | 504 | {} |
489 | 505 | ||
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index 74247917de04..b86740d1c50a 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h | |||
@@ -27,10 +27,12 @@ | |||
27 | #define FAN_CLOEXEC 0x00000001 | 27 | #define FAN_CLOEXEC 0x00000001 |
28 | #define FAN_NONBLOCK 0x00000002 | 28 | #define FAN_NONBLOCK 0x00000002 |
29 | 29 | ||
30 | /* These are NOT bitwise flags. Both bits are used togther. */ | 30 | /* These are NOT bitwise flags. Both bits are used together. */ |
31 | #define FAN_CLASS_NOTIF 0x00000000 | 31 | #define FAN_CLASS_NOTIF 0x00000000 |
32 | #define FAN_CLASS_CONTENT 0x00000004 | 32 | #define FAN_CLASS_CONTENT 0x00000004 |
33 | #define FAN_CLASS_PRE_CONTENT 0x00000008 | 33 | #define FAN_CLASS_PRE_CONTENT 0x00000008 |
34 | |||
35 | /* Deprecated - do not use this in programs and do not add new flags here! */ | ||
34 | #define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ | 36 | #define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ |
35 | FAN_CLASS_PRE_CONTENT) | 37 | FAN_CLASS_PRE_CONTENT) |
36 | 38 | ||
@@ -38,6 +40,10 @@ | |||
38 | #define FAN_UNLIMITED_MARKS 0x00000020 | 40 | #define FAN_UNLIMITED_MARKS 0x00000020 |
39 | #define FAN_ENABLE_AUDIT 0x00000040 | 41 | #define FAN_ENABLE_AUDIT 0x00000040 |
40 | 42 | ||
43 | /* Flags to determine fanotify event format */ | ||
44 | #define FAN_REPORT_TID 0x00000100 /* event->pid is thread id */ | ||
45 | |||
46 | /* Deprecated - do not use this in programs and do not add new flags here! */ | ||
41 | #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ | 47 | #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ |
42 | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\ | 48 | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\ |
43 | FAN_UNLIMITED_MARKS) | 49 | FAN_UNLIMITED_MARKS) |
@@ -47,11 +53,18 @@ | |||
47 | #define FAN_MARK_REMOVE 0x00000002 | 53 | #define FAN_MARK_REMOVE 0x00000002 |
48 | #define FAN_MARK_DONT_FOLLOW 0x00000004 | 54 | #define FAN_MARK_DONT_FOLLOW 0x00000004 |
49 | #define FAN_MARK_ONLYDIR 0x00000008 | 55 | #define FAN_MARK_ONLYDIR 0x00000008 |
50 | #define FAN_MARK_MOUNT 0x00000010 | 56 | /* FAN_MARK_MOUNT is 0x00000010 */ |
51 | #define FAN_MARK_IGNORED_MASK 0x00000020 | 57 | #define FAN_MARK_IGNORED_MASK 0x00000020 |
52 | #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 | 58 | #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 |
53 | #define FAN_MARK_FLUSH 0x00000080 | 59 | #define FAN_MARK_FLUSH 0x00000080 |
60 | /* FAN_MARK_FILESYSTEM is 0x00000100 */ | ||
54 | 61 | ||
62 | /* These are NOT bitwise flags. Both bits can be used togther. */ | ||
63 | #define FAN_MARK_INODE 0x00000000 | ||
64 | #define FAN_MARK_MOUNT 0x00000010 | ||
65 | #define FAN_MARK_FILESYSTEM 0x00000100 | ||
66 | |||
67 | /* Deprecated - do not use this in programs and do not add new flags here! */ | ||
55 | #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ | 68 | #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ |
56 | FAN_MARK_REMOVE |\ | 69 | FAN_MARK_REMOVE |\ |
57 | FAN_MARK_DONT_FOLLOW |\ | 70 | FAN_MARK_DONT_FOLLOW |\ |
@@ -61,11 +74,7 @@ | |||
61 | FAN_MARK_IGNORED_SURV_MODIFY |\ | 74 | FAN_MARK_IGNORED_SURV_MODIFY |\ |
62 | FAN_MARK_FLUSH) | 75 | FAN_MARK_FLUSH) |
63 | 76 | ||
64 | /* | 77 | /* Deprecated - do not use this in programs and do not add new flags here! */ |
65 | * All of the events - we build the list by hand so that we can add flags in | ||
66 | * the future and not break backward compatibility. Apps will get only the | ||
67 | * events that they originally wanted. Be sure to add new events here! | ||
68 | */ | ||
69 | #define FAN_ALL_EVENTS (FAN_ACCESS |\ | 78 | #define FAN_ALL_EVENTS (FAN_ACCESS |\ |
70 | FAN_MODIFY |\ | 79 | FAN_MODIFY |\ |
71 | FAN_CLOSE |\ | 80 | FAN_CLOSE |\ |
@@ -74,9 +83,11 @@ | |||
74 | /* | 83 | /* |
75 | * All events which require a permission response from userspace | 84 | * All events which require a permission response from userspace |
76 | */ | 85 | */ |
86 | /* Deprecated - do not use this in programs and do not add new flags here! */ | ||
77 | #define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\ | 87 | #define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\ |
78 | FAN_ACCESS_PERM) | 88 | FAN_ACCESS_PERM) |
79 | 89 | ||
90 | /* Deprecated - do not use this in programs and do not add new flags here! */ | ||
80 | #define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\ | 91 | #define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\ |
81 | FAN_ALL_PERM_EVENTS |\ | 92 | FAN_ALL_PERM_EVENTS |\ |
82 | FAN_Q_OVERFLOW) | 93 | FAN_Q_OVERFLOW) |