list_for_each_entry(info, &kernfs_root(kn)->supers, node) {
                struct kernfs_node *parent;
+               struct inode *p_inode = NULL;
                struct inode *inode;
                struct qstr name;
 
                name = (struct qstr)QSTR_INIT(kn->name, strlen(kn->name));
                parent = kernfs_get_parent(kn);
                if (parent) {
-                       struct inode *p_inode;
-
                        p_inode = ilookup(info->sb, kernfs_ino(parent));
                        if (p_inode) {
                                fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD,
                        kernfs_put(parent);
                }
 
-               fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
-                        NULL, 0);
+               if (!p_inode) {
+                       fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
+                                NULL, 0);
+               }
+
                iput(inode);
        }
 
 
 /*
  * Notify this dentry's parent about a child's events with child name info
  * if parent is watching.
- * Notify also the child without name info if child inode is watching.
+ * Notify only the child without name info if parent is not watching.
  */
 int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
                      int data_type)
 {
+       struct inode *inode = d_inode(dentry);
        struct dentry *parent;
        struct inode *p_inode;
+       struct name_snapshot name;
+       struct qstr *file_name = NULL;
        int ret = 0;
 
+       parent = NULL;
        if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
-               goto notify_child;
+               goto notify;
 
        parent = dget_parent(dentry);
        p_inode = parent->d_inode;
        if (unlikely(!fsnotify_inode_watches_children(p_inode))) {
                __fsnotify_update_child_dentry_flags(p_inode);
        } else if (p_inode->i_fsnotify_mask & mask & ALL_FSNOTIFY_EVENTS) {
-               struct name_snapshot name;
+               /* When notifying parent, child should be passed as data */
+               WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
 
-               /*
-                * We are notifying a parent, so set a flag in mask to inform
-                * backend that event has information about a child entry.
-                */
+               /* Notify both parent and child with child name info */
+               inode = p_inode;
                take_dentry_name_snapshot(&name, dentry);
-               ret = fsnotify(p_inode, mask | FS_EVENT_ON_CHILD, data,
-                              data_type, &name.name, 0);
-               release_dentry_name_snapshot(&name);
+               file_name = &name.name;
+               mask |= FS_EVENT_ON_CHILD;
        }
 
-       dput(parent);
+notify:
+       ret = fsnotify(inode, mask, data, data_type, file_name, 0);
 
-       if (ret)
-               return ret;
+       if (file_name)
+               release_dentry_name_snapshot(&name);
+       dput(parent);
 
-notify_child:
-       return fsnotify(d_inode(dentry), mask, data, data_type, NULL, 0);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(__fsnotify_parent);
 
        struct super_block *sb = to_tell->i_sb;
        struct inode *dir = file_name ? to_tell : NULL;
        struct mount *mnt = NULL;
+       struct inode *child = NULL;
        int ret = 0;
        __u32 test_mask, marks_mask;
 
        if (path)
                mnt = real_mount(path->mnt);
 
+       if (mask & FS_EVENT_ON_CHILD)
+               child = fsnotify_data_inode(data, data_type);
+
        /*
         * Optimization: srcu_read_lock() has a memory barrier which can
         * be expensive.  It protects walking the *_fsnotify_marks lists.
         * need SRCU to keep them "alive".
         */
        if (!to_tell->i_fsnotify_marks && !sb->s_fsnotify_marks &&
-           (!mnt || !mnt->mnt_fsnotify_marks))
+           (!mnt || !mnt->mnt_fsnotify_marks) &&
+           (!child || !child->i_fsnotify_marks))
                return 0;
 
-       /* An event "on child" is not intended for a mount/sb mark */
-       marks_mask = to_tell->i_fsnotify_mask;
-       if (!(mask & FS_EVENT_ON_CHILD)) {
-               marks_mask |= sb->s_fsnotify_mask;
-               if (mnt)
-                       marks_mask |= mnt->mnt_fsnotify_mask;
-       }
+       marks_mask = to_tell->i_fsnotify_mask | sb->s_fsnotify_mask;
+       if (mnt)
+               marks_mask |= mnt->mnt_fsnotify_mask;
+       if (child)
+               marks_mask |= child->i_fsnotify_mask;
+
 
        /*
         * if this is a modify event we may need to clear the ignored masks
-        * otherwise return if neither the inode nor the vfsmount/sb care about
-        * this type of event.
+        * otherwise return if none of the marks care about this type of event.
         */
        test_mask = (mask & ALL_FSNOTIFY_EVENTS);
        if (!(mask & FS_MODIFY) && !(test_mask & marks_mask))
                iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
                        fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
        }
+       if (child) {
+               iter_info.marks[FSNOTIFY_OBJ_TYPE_CHILD] =
+                       fsnotify_first_mark(&child->i_fsnotify_marks);
+       }
 
        /*
         * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark