aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-30 14:50:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-30 14:50:37 -0400
commit1792f17b7210280a3d7ff29da9614ba779cfcedb (patch)
treee45797137b7fc4877dd60b289d6fb75c6bdcdcf0 /fs
parentf02a38d86a14b6e544e218d806ffb0442785f62b (diff)
parent6bff7eccb0d9bdef4123aad5399e73cbc26683a6 (diff)
Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify
* 'for-linus' of git://git.infradead.org/users/eparis/notify: (22 commits) Ensure FMODE_NONOTIFY is not set by userspace make fanotify_read() restartable across signals fsnotify: remove alignment padding from fsnotify_mark on 64 bit builds fs/notify/fanotify/fanotify_user.c: fix warnings fanotify: Fix FAN_CLOSE comments fanotify: do not recalculate the mask if the ignored mask changed fanotify: ignore events on directories unless specifically requested fsnotify: rename FS_IN_ISDIR to FS_ISDIR fanotify: do not send events for irregular files fanotify: limit number of listeners per user fanotify: allow userspace to override max marks fanotify: limit the number of marks in a single fanotify group fanotify: allow userspace to override max queue depth fsnotify: implement a default maximum queue depth fanotify: ignore fanotify ignore marks if open writers fanotify: allow userspace to flush all marks fsnotify: call fsnotify_parent in perm events fsnotify: correctly handle return codes from listeners fanotify: use __aligned_u64 in fanotify userspace metadata fanotify: implement fanotify listener ordering ...
Diffstat (limited to 'fs')
-rw-r--r--fs/notify/Kconfig2
-rw-r--r--fs/notify/fanotify/fanotify.c27
-rw-r--r--fs/notify/fanotify/fanotify_user.c98
-rw-r--r--fs/notify/fsnotify.c35
-rw-r--r--fs/notify/inode_mark.c9
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--fs/notify/vfsmount_mark.c6
7 files changed, 146 insertions, 33 deletions
diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig
index b388443c3a09..22c629eedd82 100644
--- a/fs/notify/Kconfig
+++ b/fs/notify/Kconfig
@@ -3,4 +3,4 @@ config FSNOTIFY
3 3
4source "fs/notify/dnotify/Kconfig" 4source "fs/notify/dnotify/Kconfig"
5source "fs/notify/inotify/Kconfig" 5source "fs/notify/inotify/Kconfig"
6#source "fs/notify/fanotify/Kconfig" 6source "fs/notify/fanotify/Kconfig"
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 85366c78cc37..b04f88eed09e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -131,6 +131,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW); 131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM); 132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); 133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
134 BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
134 135
135 pr_debug("%s: group=%p event=%p\n", __func__, group, event); 136 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
136 137
@@ -160,20 +161,21 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
160 __u32 event_mask, void *data, int data_type) 161 __u32 event_mask, void *data, int data_type)
161{ 162{
162 __u32 marks_mask, marks_ignored_mask; 163 __u32 marks_mask, marks_ignored_mask;
164 struct path *path = data;
163 165
164 pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p " 166 pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
165 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell, 167 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
166 inode_mark, vfsmnt_mark, event_mask, data, data_type); 168 inode_mark, vfsmnt_mark, event_mask, data, data_type);
167 169
168 /* sorry, fanotify only gives a damn about files and dirs */
169 if (!S_ISREG(to_tell->i_mode) &&
170 !S_ISDIR(to_tell->i_mode))
171 return false;
172
173 /* if we don't have enough info to send an event to userspace say no */ 170 /* if we don't have enough info to send an event to userspace say no */
174 if (data_type != FSNOTIFY_EVENT_PATH) 171 if (data_type != FSNOTIFY_EVENT_PATH)
175 return false; 172 return false;
176 173
174 /* sorry, fanotify only gives a damn about files and dirs */
175 if (!S_ISREG(path->dentry->d_inode->i_mode) &&
176 !S_ISDIR(path->dentry->d_inode->i_mode))
177 return false;
178
177 if (inode_mark && vfsmnt_mark) { 179 if (inode_mark && vfsmnt_mark) {
178 marks_mask = (vfsmnt_mark->mask | inode_mark->mask); 180 marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
179 marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask); 181 marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
@@ -194,16 +196,29 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
194 BUG(); 196 BUG();
195 } 197 }
196 198
199 if (S_ISDIR(path->dentry->d_inode->i_mode) &&
200 (marks_ignored_mask & FS_ISDIR))
201 return false;
202
197 if (event_mask & marks_mask & ~marks_ignored_mask) 203 if (event_mask & marks_mask & ~marks_ignored_mask)
198 return true; 204 return true;
199 205
200 return false; 206 return false;
201} 207}
202 208
209static void fanotify_free_group_priv(struct fsnotify_group *group)
210{
211 struct user_struct *user;
212
213 user = group->fanotify_data.user;
214 atomic_dec(&user->fanotify_listeners);
215 free_uid(user);
216}
217
203const struct fsnotify_ops fanotify_fsnotify_ops = { 218const struct fsnotify_ops fanotify_fsnotify_ops = {
204 .handle_event = fanotify_handle_event, 219 .handle_event = fanotify_handle_event,
205 .should_send_event = fanotify_should_send_event, 220 .should_send_event = fanotify_should_send_event,
206 .free_group_priv = NULL, 221 .free_group_priv = fanotify_free_group_priv,
207 .free_event_priv = NULL, 222 .free_event_priv = NULL,
208 .freeing_mark = NULL, 223 .freeing_mark = NULL,
209}; 224};
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index bbcb98e7fcc6..063224812b7e 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -16,6 +16,10 @@
16 16
17#include <asm/ioctls.h> 17#include <asm/ioctls.h>
18 18
19#define FANOTIFY_DEFAULT_MAX_EVENTS 16384
20#define FANOTIFY_DEFAULT_MAX_MARKS 8192
21#define FANOTIFY_DEFAULT_MAX_LISTENERS 128
22
19extern const struct fsnotify_ops fanotify_fsnotify_ops; 23extern const struct fsnotify_ops fanotify_fsnotify_ops;
20 24
21static struct kmem_cache *fanotify_mark_cache __read_mostly; 25static struct kmem_cache *fanotify_mark_cache __read_mostly;
@@ -326,7 +330,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
326 ret = -EAGAIN; 330 ret = -EAGAIN;
327 if (file->f_flags & O_NONBLOCK) 331 if (file->f_flags & O_NONBLOCK)
328 break; 332 break;
329 ret = -EINTR; 333 ret = -ERESTARTSYS;
330 if (signal_pending(current)) 334 if (signal_pending(current))
331 break; 335 break;
332 336
@@ -372,11 +376,10 @@ static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t
372static int fanotify_release(struct inode *ignored, struct file *file) 376static int fanotify_release(struct inode *ignored, struct file *file)
373{ 377{
374 struct fsnotify_group *group = file->private_data; 378 struct fsnotify_group *group = file->private_data;
375 struct fanotify_response_event *re, *lre;
376
377 pr_debug("%s: file=%p group=%p\n", __func__, file, group);
378 379
379#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 380#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
381 struct fanotify_response_event *re, *lre;
382
380 mutex_lock(&group->fanotify_data.access_mutex); 383 mutex_lock(&group->fanotify_data.access_mutex);
381 384
382 group->fanotify_data.bypass_perm = true; 385 group->fanotify_data.bypass_perm = true;
@@ -554,18 +557,24 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
554 __u32 mask, 557 __u32 mask,
555 unsigned int flags) 558 unsigned int flags)
556{ 559{
557 __u32 oldmask; 560 __u32 oldmask = -1;
558 561
559 spin_lock(&fsn_mark->lock); 562 spin_lock(&fsn_mark->lock);
560 if (!(flags & FAN_MARK_IGNORED_MASK)) { 563 if (!(flags & FAN_MARK_IGNORED_MASK)) {
561 oldmask = fsn_mark->mask; 564 oldmask = fsn_mark->mask;
562 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask)); 565 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask));
563 } else { 566 } else {
564 oldmask = fsn_mark->ignored_mask; 567 __u32 tmask = fsn_mark->ignored_mask | mask;
565 fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask | mask)); 568 fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask);
566 if (flags & FAN_MARK_IGNORED_SURV_MODIFY) 569 if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
567 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; 570 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
568 } 571 }
572
573 if (!(flags & FAN_MARK_ONDIR)) {
574 __u32 tmask = fsn_mark->ignored_mask | FAN_ONDIR;
575 fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask);
576 }
577
569 spin_unlock(&fsn_mark->lock); 578 spin_unlock(&fsn_mark->lock);
570 579
571 return mask & ~oldmask; 580 return mask & ~oldmask;
@@ -582,6 +591,9 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
582 if (!fsn_mark) { 591 if (!fsn_mark) {
583 int ret; 592 int ret;
584 593
594 if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
595 return -ENOSPC;
596
585 fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); 597 fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
586 if (!fsn_mark) 598 if (!fsn_mark)
587 return -ENOMEM; 599 return -ENOMEM;
@@ -610,10 +622,23 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
610 622
611 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode); 623 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
612 624
625 /*
626 * If some other task has this inode open for write we should not add
627 * an ignored mark, unless that ignored mark is supposed to survive
628 * modification changes anyway.
629 */
630 if ((flags & FAN_MARK_IGNORED_MASK) &&
631 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
632 (atomic_read(&inode->i_writecount) > 0))
633 return 0;
634
613 fsn_mark = fsnotify_find_inode_mark(group, inode); 635 fsn_mark = fsnotify_find_inode_mark(group, inode);
614 if (!fsn_mark) { 636 if (!fsn_mark) {
615 int ret; 637 int ret;
616 638
639 if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
640 return -ENOSPC;
641
617 fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); 642 fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
618 if (!fsn_mark) 643 if (!fsn_mark)
619 return -ENOMEM; 644 return -ENOMEM;
@@ -637,6 +662,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
637{ 662{
638 struct fsnotify_group *group; 663 struct fsnotify_group *group;
639 int f_flags, fd; 664 int f_flags, fd;
665 struct user_struct *user;
640 666
641 pr_debug("%s: flags=%d event_f_flags=%d\n", 667 pr_debug("%s: flags=%d event_f_flags=%d\n",
642 __func__, flags, event_f_flags); 668 __func__, flags, event_f_flags);
@@ -647,6 +673,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
647 if (flags & ~FAN_ALL_INIT_FLAGS) 673 if (flags & ~FAN_ALL_INIT_FLAGS)
648 return -EINVAL; 674 return -EINVAL;
649 675
676 user = get_current_user();
677 if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) {
678 free_uid(user);
679 return -EMFILE;
680 }
681
650 f_flags = O_RDWR | FMODE_NONOTIFY; 682 f_flags = O_RDWR | FMODE_NONOTIFY;
651 if (flags & FAN_CLOEXEC) 683 if (flags & FAN_CLOEXEC)
652 f_flags |= O_CLOEXEC; 684 f_flags |= O_CLOEXEC;
@@ -658,12 +690,47 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
658 if (IS_ERR(group)) 690 if (IS_ERR(group))
659 return PTR_ERR(group); 691 return PTR_ERR(group);
660 692
693 group->fanotify_data.user = user;
694 atomic_inc(&user->fanotify_listeners);
695
661 group->fanotify_data.f_flags = event_f_flags; 696 group->fanotify_data.f_flags = event_f_flags;
662#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 697#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
663 mutex_init(&group->fanotify_data.access_mutex); 698 mutex_init(&group->fanotify_data.access_mutex);
664 init_waitqueue_head(&group->fanotify_data.access_waitq); 699 init_waitqueue_head(&group->fanotify_data.access_waitq);
665 INIT_LIST_HEAD(&group->fanotify_data.access_list); 700 INIT_LIST_HEAD(&group->fanotify_data.access_list);
666#endif 701#endif
702 switch (flags & FAN_ALL_CLASS_BITS) {
703 case FAN_CLASS_NOTIF:
704 group->priority = FS_PRIO_0;
705 break;
706 case FAN_CLASS_CONTENT:
707 group->priority = FS_PRIO_1;
708 break;
709 case FAN_CLASS_PRE_CONTENT:
710 group->priority = FS_PRIO_2;
711 break;
712 default:
713 fd = -EINVAL;
714 goto out_put_group;
715 }
716
717 if (flags & FAN_UNLIMITED_QUEUE) {
718 fd = -EPERM;
719 if (!capable(CAP_SYS_ADMIN))
720 goto out_put_group;
721 group->max_events = UINT_MAX;
722 } else {
723 group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS;
724 }
725
726 if (flags & FAN_UNLIMITED_MARKS) {
727 fd = -EPERM;
728 if (!capable(CAP_SYS_ADMIN))
729 goto out_put_group;
730 group->fanotify_data.max_marks = UINT_MAX;
731 } else {
732 group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
733 }
667 734
668 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); 735 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
669 if (fd < 0) 736 if (fd < 0)
@@ -704,6 +771,12 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
704 default: 771 default:
705 return -EINVAL; 772 return -EINVAL;
706 } 773 }
774
775 if (mask & FAN_ONDIR) {
776 flags |= FAN_MARK_ONDIR;
777 mask &= ~FAN_ONDIR;
778 }
779
707#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 780#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
708 if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD)) 781 if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD))
709#else 782#else
@@ -719,6 +792,16 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
719 ret = -EINVAL; 792 ret = -EINVAL;
720 if (unlikely(filp->f_op != &fanotify_fops)) 793 if (unlikely(filp->f_op != &fanotify_fops))
721 goto fput_and_out; 794 goto fput_and_out;
795 group = filp->private_data;
796
797 /*
798 * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not
799 * allowed to set permissions events.
800 */
801 ret = -EINVAL;
802 if (mask & FAN_ALL_PERM_EVENTS &&
803 group->priority == FS_PRIO_0)
804 goto fput_and_out;
722 805
723 ret = fanotify_find_path(dfd, pathname, &path, flags); 806 ret = fanotify_find_path(dfd, pathname, &path, flags);
724 if (ret) 807 if (ret)
@@ -729,7 +812,6 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
729 inode = path.dentry->d_inode; 812 inode = path.dentry->d_inode;
730 else 813 else
731 mnt = path.mnt; 814 mnt = path.mnt;
732 group = filp->private_data;
733 815
734 /* create/update an inode mark */ 816 /* create/update an inode mark */
735 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { 817 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 4498a208df94..20dc218707ca 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -84,16 +84,17 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
84} 84}
85 85
86/* Notify this dentry's parent about a child's events. */ 86/* Notify this dentry's parent about a child's events. */
87void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 87int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
88{ 88{
89 struct dentry *parent; 89 struct dentry *parent;
90 struct inode *p_inode; 90 struct inode *p_inode;
91 int ret = 0;
91 92
92 if (!dentry) 93 if (!dentry)
93 dentry = path->dentry; 94 dentry = path->dentry;
94 95
95 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) 96 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
96 return; 97 return 0;
97 98
98 parent = dget_parent(dentry); 99 parent = dget_parent(dentry);
99 p_inode = parent->d_inode; 100 p_inode = parent->d_inode;
@@ -106,14 +107,16 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
106 mask |= FS_EVENT_ON_CHILD; 107 mask |= FS_EVENT_ON_CHILD;
107 108
108 if (path) 109 if (path)
109 fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, 110 ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
110 dentry->d_name.name, 0); 111 dentry->d_name.name, 0);
111 else 112 else
112 fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, 113 ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
113 dentry->d_name.name, 0); 114 dentry->d_name.name, 0);
114 } 115 }
115 116
116 dput(parent); 117 dput(parent);
118
119 return ret;
117} 120}
118EXPORT_SYMBOL_GPL(__fsnotify_parent); 121EXPORT_SYMBOL_GPL(__fsnotify_parent);
119 122
@@ -252,20 +255,23 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
252 255
253 if (inode_group > vfsmount_group) { 256 if (inode_group > vfsmount_group) {
254 /* handle inode */ 257 /* handle inode */
255 send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, 258 ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
256 data_is, cookie, file_name, &event); 259 data_is, cookie, file_name, &event);
257 /* we didn't use the vfsmount_mark */ 260 /* we didn't use the vfsmount_mark */
258 vfsmount_group = NULL; 261 vfsmount_group = NULL;
259 } else if (vfsmount_group > inode_group) { 262 } else if (vfsmount_group > inode_group) {
260 send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, 263 ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
261 data_is, cookie, file_name, &event); 264 data_is, cookie, file_name, &event);
262 inode_group = NULL; 265 inode_group = NULL;
263 } else { 266 } else {
264 send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, 267 ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
265 mask, data, data_is, cookie, file_name, 268 mask, data, data_is, cookie, file_name,
266 &event); 269 &event);
267 } 270 }
268 271
272 if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
273 goto out;
274
269 if (inode_group) 275 if (inode_group)
270 inode_node = srcu_dereference(inode_node->next, 276 inode_node = srcu_dereference(inode_node->next,
271 &fsnotify_mark_srcu); 277 &fsnotify_mark_srcu);
@@ -273,7 +279,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
273 vfsmount_node = srcu_dereference(vfsmount_node->next, 279 vfsmount_node = srcu_dereference(vfsmount_node->next,
274 &fsnotify_mark_srcu); 280 &fsnotify_mark_srcu);
275 } 281 }
276 282 ret = 0;
283out:
277 srcu_read_unlock(&fsnotify_mark_srcu, idx); 284 srcu_read_unlock(&fsnotify_mark_srcu, idx);
278 /* 285 /*
279 * fsnotify_create_event() took a reference so the event can't be cleaned 286 * fsnotify_create_event() took a reference so the event can't be cleaned
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index 21ed10660b80..4c29fcf557d1 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -177,7 +177,8 @@ void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *mark,
177 * Attach an initialized mark to a given inode. 177 * Attach an initialized mark to a given inode.
178 * These marks may be used for the fsnotify backend to determine which 178 * These marks may be used for the fsnotify backend to determine which
179 * event types should be delivered to which group and for which inodes. These 179 * event types should be delivered to which group and for which inodes. These
180 * marks are ordered according to the group's location in memory. 180 * marks are ordered according to priority, highest number first, and then by
181 * the group's location in memory.
181 */ 182 */
182int fsnotify_add_inode_mark(struct fsnotify_mark *mark, 183int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
183 struct fsnotify_group *group, struct inode *inode, 184 struct fsnotify_group *group, struct inode *inode,
@@ -211,7 +212,11 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
211 goto out; 212 goto out;
212 } 213 }
213 214
214 if (mark->group < lmark->group) 215 if (mark->group->priority < lmark->group->priority)
216 continue;
217
218 if ((mark->group->priority == lmark->group->priority) &&
219 (mark->group < lmark->group))
215 continue; 220 continue;
216 221
217 hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list); 222 hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 24edc1185d53..444c305a468c 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -862,7 +862,7 @@ static int __init inotify_user_setup(void)
862 BUILD_BUG_ON(IN_Q_OVERFLOW != FS_Q_OVERFLOW); 862 BUILD_BUG_ON(IN_Q_OVERFLOW != FS_Q_OVERFLOW);
863 BUILD_BUG_ON(IN_IGNORED != FS_IN_IGNORED); 863 BUILD_BUG_ON(IN_IGNORED != FS_IN_IGNORED);
864 BUILD_BUG_ON(IN_EXCL_UNLINK != FS_EXCL_UNLINK); 864 BUILD_BUG_ON(IN_EXCL_UNLINK != FS_EXCL_UNLINK);
865 BUILD_BUG_ON(IN_ISDIR != FS_IN_ISDIR); 865 BUILD_BUG_ON(IN_ISDIR != FS_ISDIR);
866 BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT); 866 BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT);
867 867
868 BUG_ON(hweight32(ALL_INOTIFY_BITS) != 21); 868 BUG_ON(hweight32(ALL_INOTIFY_BITS) != 21);
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c
index 56772b578fbd..85eebff6d0d7 100644
--- a/fs/notify/vfsmount_mark.c
+++ b/fs/notify/vfsmount_mark.c
@@ -169,7 +169,11 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
169 goto out; 169 goto out;
170 } 170 }
171 171
172 if (mark->group < lmark->group) 172 if (mark->group->priority < lmark->group->priority)
173 continue;
174
175 if ((mark->group->priority == lmark->group->priority) &&
176 (mark->group < lmark->group))
173 continue; 177 continue;
174 178
175 hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list); 179 hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list);