--- x/fs/notify/fsnotify.c +++ y/fs/notify/fsnotify.c @@ -101,8 +101,8 @@ void fsnotify_sb_delete(struct super_blo wait_var_event(fsnotify_sb_watched_objects(sb), !atomic_long_read(fsnotify_sb_watched_objects(sb))); WARN_ON(fsnotify_sb_has_priority_watchers(sb, FSNOTIFY_PRIO_CONTENT)); - WARN_ON(fsnotify_sb_has_priority_watchers(sb, - FSNOTIFY_PRIO_PRE_CONTENT)); + WARN_ON(fsnotify_sb_has_priority_watchers(sb, FSNOTIFY_PRIO_PRE_CONTENT)); + synchronize_srcu(&fsnotify_mark_srcu); kfree(sbinfo); } @@ -499,7 +499,7 @@ int fsnotify(__u32 mask, const void *dat { const struct path *path = fsnotify_data_path(data, data_type); struct super_block *sb = fsnotify_data_sb(data, data_type); - struct fsnotify_sb_info *sbinfo = fsnotify_sb_info(sb); + struct fsnotify_sb_info *sbinfo; struct fsnotify_iter_info iter_info = {}; struct mount *mnt = NULL; struct inode *inode2 = NULL; @@ -529,6 +529,8 @@ int fsnotify(__u32 mask, const void *dat inode2_type = FSNOTIFY_ITER_TYPE_PARENT; } + iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); + sbinfo = fsnotify_sb_info(sb); /* * Optimization: srcu_read_lock() has a memory barrier which can * be expensive. It protects walking the *_fsnotify_marks lists. @@ -539,8 +541,10 @@ int fsnotify(__u32 mask, const void *dat if ((!sbinfo || !sbinfo->sb_marks) && (!mnt || !mnt->mnt_fsnotify_marks) && (!inode || !inode->i_fsnotify_marks) && - (!inode2 || !inode2->i_fsnotify_marks)) - return 0; + (!inode2 || !inode2->i_fsnotify_marks)) { + ret = 0; + goto out; + } marks_mask = sb->s_fsnotify_mask; if (mnt) @@ -558,10 +562,10 @@ int fsnotify(__u32 mask, const void *dat * Otherwise, return if none of the marks care about this type of event. */ test_mask = (mask & ALL_FSNOTIFY_EVENTS); - if (!(test_mask & marks_mask)) - return 0; - - iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); + if (!(test_mask & marks_mask)) { + ret = 0; + goto out; + } if (sbinfo) { iter_info.marks[FSNOTIFY_ITER_TYPE_SB] =