diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 5a4ec30..4ad969b 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -84,7 +84,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
 static int dnotify_handle_event(struct fsnotify_group *group,
 				struct inode *inode,
 				struct fsnotify_mark *inode_mark,
-				struct fsnotify_mark *vfsmount_mark,
+				u32 unused,
 				u32 mask, const void *data, int data_type,
 				const unsigned char *file_name, u32 cookie)
 {
@@ -98,8 +98,6 @@ static int dnotify_handle_event(struct fsnotify_group *group,
 	if (!S_ISDIR(inode->i_mode))
 		return 0;
 
-	BUG_ON(vfsmount_mark);
-
 	dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
 
 	spin_lock(&inode_mark->lock);
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 9b26e2f..6a2db65 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -87,17 +87,17 @@ static int fanotify_get_response(struct fsnotify_group *group,
 }
 #endif
 
-static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
-				       struct fsnotify_mark *vfsmnt_mark,
+static bool fanotify_should_send_event(struct fsnotify_mark *mark,
+				       u32 ignored_mask,
 				       u32 event_mask,
 				       const void *data, int data_type)
 {
-	__u32 marks_mask = 0, marks_ignored_mask = 0;
+	__u32 mark_mask = mark->mask;
 	const struct path *path = data;
 
-	pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p"
-		 " data_type=%d\n", __func__, inode_mark, vfsmnt_mark,
-		 event_mask, data, data_type);
+	pr_debug("%s: mark=%p mark_mask=%x ignored_mask=%x event_mask=%x"
+		 " data=%p data_type=%d\n", __func__, mark, mark_mask,
+		 ignored_mask, event_mask, data, data_type);
 
 	/* if we don't have enough info to send an event to userspace say no */
 	if (data_type != FSNOTIFY_EVENT_PATH)
@@ -108,28 +108,22 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
 	    !d_can_lookup(path->dentry))
 		return false;
 
-	if (inode_mark) {
+	if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
 		/*
 		 * if the event is for a child and this inode doesn't care about
 		 * events on the child, don't send it!
 		 */
 		if ((event_mask & FS_EVENT_ON_CHILD) &&
-		    !(inode_mark->mask & FS_EVENT_ON_CHILD))
+		    !(mark_mask & FS_EVENT_ON_CHILD))
 			return false;
-		marks_mask |= inode_mark->mask;
-		marks_ignored_mask |= inode_mark->ignored_mask;
-	}
-	if (vfsmnt_mark) {
-		marks_mask |= vfsmnt_mark->mask;
-		marks_ignored_mask |= vfsmnt_mark->ignored_mask;
 	}
 
 	if (d_is_dir(path->dentry) &&
-	    !(marks_mask & FS_ISDIR & ~marks_ignored_mask))
+	    !(mark_mask & FS_ISDIR & ~ignored_mask))
 		return false;
 
-	if (event_mask & FAN_ALL_OUTGOING_EVENTS & marks_mask &
-				 ~marks_ignored_mask)
+	if (event_mask & FAN_ALL_OUTGOING_EVENTS & mark_mask &
+				 ~ignored_mask)
 		return true;
 
 	return false;
@@ -171,8 +165,8 @@ init: __maybe_unused
 
 static int fanotify_handle_event(struct fsnotify_group *group,
 				 struct inode *inode,
-				 struct fsnotify_mark *inode_mark,
-				 struct fsnotify_mark *fanotify_mark,
+				 struct fsnotify_mark *mark,
+				 u32 ignored_mask,
 				 u32 mask, const void *data, int data_type,
 				 const unsigned char *file_name, u32 cookie)
 {
@@ -191,7 +185,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 	BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
 	BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
 
-	if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data,
+	if (!fanotify_should_send_event(mark, ignored_mask, mask, data,
 					data_type))
 		return FSNOTIFY_DROPPED;
 
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index caed3c4..6af8f81 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -146,56 +146,61 @@ static __u32 update_ignored_mask(struct fsnotify_mark *inode_mark,
 	return ignored_mask;
 }
 
-static int send_to_group(struct inode *to_tell,
-			 struct fsnotify_mark *inode_mark,
-			 struct fsnotify_mark *vfsmount_mark,
-			 __u32 mask, const void *data,
-			 int data_is, u32 cookie,
-			 const unsigned char *file_name)
+static int send_to_group_mark(struct inode *to_tell,
+			      struct fsnotify_mark *mark,
+			      __u32 ignored_mask,
+			      __u32 mask, const void *data,
+			      int data_is, u32 cookie,
+			      const unsigned char *file_name)
 {
-	struct fsnotify_group *group = NULL;
-	__u32 inode_test_mask = 0;
-	__u32 vfsmount_test_mask = 0;
-	__u32 ignored_mask;
-
-	if (unlikely(!inode_mark && !vfsmount_mark)) {
-		BUG();
-		return 0;
-	}
+	struct fsnotify_group *group = mark->group;
+	__u32 test_mask;
 
-	ignored_mask = update_ignored_mask(inode_mark, vfsmount_mark, mask);
-
-	/* does the inode mark tell us to do something? */
-	if (inode_mark) {
-		group = inode_mark->group;
-		inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
-		inode_test_mask &= inode_mark->mask;
-		inode_test_mask &= ~ignored_mask;
-	}
+	/* does the mark tell us to do something? */
+	test_mask = (mask & mark->mask & ~FS_EVENT_ON_CHILD);
 
-	/* does the vfsmount_mark tell us to do something? */
-	if (vfsmount_mark) {
-		vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
-		group = vfsmount_mark->group;
-		vfsmount_test_mask &= vfsmount_mark->mask;
-		vfsmount_test_mask &= ~ignored_mask;
-	}
-
-	pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
-		 " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
-		 " ignored_mask=%x data=%p data_is=%d cookie=%d\n",
-		 __func__, group, to_tell, mask, inode_mark,
-		 inode_test_mask, vfsmount_mark, vfsmount_test_mask,
+	pr_debug("%s: group=%p to_tell=%p mask=%x mark=%p test_mask=%x"
+		 " ignored_mask=%x"" data=%p data_is=%d cookie=%d\n",
+		 __func__, group, to_tell, mask, mark, test_mask,
 		 ignored_mask, data, data_is, cookie);
 
-	if (!inode_test_mask && !vfsmount_test_mask)
+	if (!(test_mask & ~ignored_mask))
 		return FSNOTIFY_DROPPED;
 
-	return group->ops->handle_event(group, to_tell, inode_mark,
-					vfsmount_mark, mask, data, data_is,
+	return group->ops->handle_event(group, to_tell, mark,
+					ignored_mask, mask, data, data_is,
 					file_name, cookie);
 }
 
+static int send_to_group(struct inode *to_tell,
+			 struct fsnotify_mark *inode_mark,
+			 struct fsnotify_mark *vfsmount_mark,
+			 __u32 mask, const void *data,
+			 int data_is, u32 cookie,
+			 const unsigned char *file_name)
+{
+	int ret = FSNOTIFY_DROPPED;
+	__u32 ignored_mask = update_ignored_mask(inode_mark, vfsmount_mark,
+						 mask);
+
+	if (inode_mark)
+		ret = send_to_group_mark(to_tell, inode_mark,
+					 ignored_mask, mask,
+					 data, data_is, cookie, file_name);
+	/*
+	 * If event was dropped by group when handling with inode mark
+	 * (FSNOTIFY_DROPPED), resend to the group with vfsmount mark.
+	 * If event was handled by group with inode mark (FSNOTIFY_DONE)
+	 * or error was returned, then we don't need to send the event
+	 * to the same group again with vfsmount mark.
+	 */
+	if (vfsmount_mark && ret == FSNOTIFY_DROPPED)
+		ret = send_to_group_mark(to_tell, vfsmount_mark,
+					 ignored_mask, mask,
+					 data, data_is, cookie, file_name);
+
+	return ret;
+}
 /*
  * This is the main call to fsnotify.  The VFS calls into hook specific functions
  * in linux/fsnotify.h.  Those functions then in turn call here.  Here will call
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h
index a6f5907..f25ad80 100644
--- a/fs/notify/inotify/inotify.h
+++ b/fs/notify/inotify/inotify.h
@@ -25,7 +25,7 @@ extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 extern int inotify_handle_event(struct fsnotify_group *group,
 				struct inode *inode,
 				struct fsnotify_mark *inode_mark,
-				struct fsnotify_mark *vfsmount_mark,
+				u32 unused,
 				u32 mask, const void *data, int data_type,
 				const unsigned char *file_name, u32 cookie);
 
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 19e7ec1..bef7e0d 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -65,7 +65,7 @@ static int inotify_merge(struct list_head *list,
 int inotify_handle_event(struct fsnotify_group *group,
 			 struct inode *inode,
 			 struct fsnotify_mark *inode_mark,
-			 struct fsnotify_mark *vfsmount_mark,
+			 u32 unused,
 			 u32 mask, const void *data, int data_type,
 			 const unsigned char *file_name, u32 cookie)
 {
@@ -76,8 +76,6 @@ int inotify_handle_event(struct fsnotify_group *group,
 	int len = 0;
 	int alloc_len = sizeof(struct inotify_event_info);
 
-	BUG_ON(vfsmount_mark);
-
 	if ((inode_mark->mask & FS_EXCL_UNLINK) &&
 	    (data_type == FSNOTIFY_EVENT_PATH)) {
 		const struct path *path = data;
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 69d1ea3..eba9ed3 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -493,7 +493,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 	struct inotify_inode_mark *i_mark;
 
 	/* Queue ignore event for the watch */
-	inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
+	inotify_handle_event(group, NULL, fsn_mark, 0, FS_IN_IGNORED,
 			     NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
 
 	i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index cbf9e92..594d6db 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -110,8 +110,8 @@ struct fsnotify_fname;
 struct fsnotify_ops {
 	int (*handle_event)(struct fsnotify_group *group,
 			    struct inode *inode,
-			    struct fsnotify_mark *inode_mark,
-			    struct fsnotify_mark *vfsmount_mark,
+			    struct fsnotify_mark *mark,
+			    u32 ignored_mask,
 			    u32 mask, const void *data, int data_type,
 			    const unsigned char *file_name, u32 cookie);
 	void (*free_group_priv)(struct fsnotify_group *group);
diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
index 7ea57e5..6db88ad 100644
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -166,7 +166,7 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark)
 static int audit_mark_handle_event(struct fsnotify_group *group,
 				    struct inode *to_tell,
 				    struct fsnotify_mark *inode_mark,
-				    struct fsnotify_mark *vfsmount_mark,
+				    u32 unused,
 				    u32 mask, const void *data, int data_type,
 				    const unsigned char *dname, u32 cookie)
 {
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 8b1dde9..4393553 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -946,7 +946,7 @@ static void evict_chunk(struct audit_chunk *chunk)
 static int audit_tree_handle_event(struct fsnotify_group *group,
 				   struct inode *to_tell,
 				   struct fsnotify_mark *inode_mark,
-				   struct fsnotify_mark *vfsmount_mark,
+				   u32 unused,
 				   u32 mask, const void *data, int data_type,
 				   const unsigned char *file_name, u32 cookie)
 {
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f79e465..6c3f811 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -470,7 +470,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
 static int audit_watch_handle_event(struct fsnotify_group *group,
 				    struct inode *to_tell,
 				    struct fsnotify_mark *inode_mark,
-				    struct fsnotify_mark *vfsmount_mark,
+				    u32 unused,
 				    u32 mask, const void *data, int data_type,
 				    const unsigned char *dname, u32 cookie)
 {
