diff options
author | Amir Goldstein <amir73il@gmail.com> | 2024-03-17 20:41:54 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2024-04-04 16:24:16 +0200 |
commit | a5e57b4d370c6d320e5bfb0c919fe00aee29e039 (patch) | |
tree | 846c1566071186acee107432ed2d18117872a3c9 /include/linux/fsnotify.h | |
parent | 477cf917dd02853ba78a73cdeb6548889e5f8cd7 (diff) |
fsnotify: optimize the case of no permission event watchers
Commit e43de7f0862b ("fsnotify: optimize the case of no marks of any type")
optimized the case where there are no fsnotify watchers on any of the
filesystem's objects.
It is quite common for a system to have a single local filesystem and
it is quite common for the system to have some inotify watches on some
config files or directories, so the optimization of no marks at all is
often not in effect.
Permission event watchers, which require high priority group are more
rare, so optimizing the case of no marks og high priority groups can
improve performance for more systems, especially for performance
sensitive io workloads.
Count per-sb watched objects by high priority groups and use that the
optimize out the call to __fsnotify_parent() and fsnotify() in fsnotify
permission hooks.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Message-Id: <20240317184154.1200192-11-amir73il@gmail.com>
Diffstat (limited to 'include/linux/fsnotify.h')
-rw-r--r-- | include/linux/fsnotify.h | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 48dc65702415..4da80e92f804 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -17,8 +17,9 @@ #include <linux/slab.h> #include <linux/bug.h> -/* Are there any inode/mount/sb objects that are being watched at all? */ -static inline bool fsnotify_sb_has_watchers(struct super_block *sb) +/* Are there any inode/mount/sb objects watched with priority prio or above? */ +static inline bool fsnotify_sb_has_priority_watchers(struct super_block *sb, + int prio) { struct fsnotify_sb_info *sbinfo = fsnotify_sb_info(sb); @@ -26,7 +27,13 @@ static inline bool fsnotify_sb_has_watchers(struct super_block *sb) if (!sbinfo) return false; - return atomic_long_read(&sbinfo->watched_objects); + return atomic_long_read(&sbinfo->watched_objects[prio]); +} + +/* Are there any inode/mount/sb objects that are being watched at all? */ +static inline bool fsnotify_sb_has_watchers(struct super_block *sb) +{ + return fsnotify_sb_has_priority_watchers(sb, 0); } /* @@ -109,6 +116,12 @@ static inline int fsnotify_file(struct file *file, __u32 mask) return 0; path = &file->f_path; + /* Permission events require group prio >= FSNOTIFY_PRIO_CONTENT */ + if (mask & ALL_FSNOTIFY_PERM_EVENTS && + !fsnotify_sb_has_priority_watchers(path->dentry->d_sb, + FSNOTIFY_PRIO_CONTENT)) + return 0; + return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); } |