summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2025-07-08 16:36:41 +0200
committerJan Kara <jack@suse.cz>2025-07-28 18:14:38 +0200
commit0d4c4d4ea443babab6ec1a79f481260963fc969a (patch)
tree219a7d83e993f6b00148d530587d5227fffda642 /include
parent08da98e1b2f76cdbacf84b9affaa75960dbce515 (diff)
fsnotify: optimize FMODE_NONOTIFY_PERM for the common cases
The most unlikely watched permission event is FAN_ACCESS_PERM, because at the time that it was introduced there were no evictable ignore mark, so subscribing to FAN_ACCESS_PERM would have incured a very high overhead. Yet, when we set the fmode to FMODE_NOTIFY_HSM(), we never skip trying to send FAN_ACCESS_PERM, which is almost always a waste of cycles. We got to this logic because of bundling FAN_OPEN*_PERM and FAN_ACCESS_PERM in the same category and because FAN_OPEN_PERM is a commonly used event. By open coding fsnotify_open_perm() in fsnotify_open_perm_and_set_mode(), we no longer need to regard FAN_OPEN*_PERM when calculating fmode. This leaves the case of having pre-content events and not having any other permission event in the object masks a more likely case than the other way around. Rework the fmode macros and code so that their meaning now refers only to hooks on an already open file: - FMODE_NOTIFY_NONE() skip all events - FMODE_NOTIFY_ACCESS_PERM() send all permission events including FAN_ACCESS_PERM - FMODE_NOTIFY_HSM() send pre-content permission events Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20250708143641.418603-3-amir73il@gmail.com
Diffstat (limited to 'include')
-rw-r--r--include/linux/fs.h12
-rw-r--r--include/linux/fsnotify.h27
2 files changed, 8 insertions, 31 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b085f161ed22..bc92fdb8bfcc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -200,12 +200,12 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
/*
* The two FMODE_NONOTIFY* define which fsnotify events should not be generated
- * for a file. These are the possible values of (f->f_mode &
- * FMODE_FSNOTIFY_MASK) and their meaning:
+ * for an open file. These are the possible values of
+ * (f->f_mode & FMODE_FSNOTIFY_MASK) and their meaning:
*
* FMODE_NONOTIFY - suppress all (incl. non-permission) events.
* FMODE_NONOTIFY_PERM - suppress permission (incl. pre-content) events.
- * FMODE_NONOTIFY | FMODE_NONOTIFY_PERM - suppress only pre-content events.
+ * FMODE_NONOTIFY | FMODE_NONOTIFY_PERM - suppress only FAN_ACCESS_PERM.
*/
#define FMODE_FSNOTIFY_MASK \
(FMODE_NONOTIFY | FMODE_NONOTIFY_PERM)
@@ -213,13 +213,13 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define FMODE_FSNOTIFY_NONE(mode) \
((mode & FMODE_FSNOTIFY_MASK) == FMODE_NONOTIFY)
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-#define FMODE_FSNOTIFY_PERM(mode) \
+#define FMODE_FSNOTIFY_HSM(mode) \
((mode & FMODE_FSNOTIFY_MASK) == 0 || \
(mode & FMODE_FSNOTIFY_MASK) == (FMODE_NONOTIFY | FMODE_NONOTIFY_PERM))
-#define FMODE_FSNOTIFY_HSM(mode) \
+#define FMODE_FSNOTIFY_ACCESS_PERM(mode) \
((mode & FMODE_FSNOTIFY_MASK) == 0)
#else
-#define FMODE_FSNOTIFY_PERM(mode) 0
+#define FMODE_FSNOTIFY_ACCESS_PERM(mode) 0
#define FMODE_FSNOTIFY_HSM(mode) 0
#endif
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 8c1fa617d375..28a9cb13fbfa 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -147,9 +147,6 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
if (!(perm_mask & (MAY_READ | MAY_WRITE | MAY_ACCESS)))
return 0;
- if (likely(!FMODE_FSNOTIFY_PERM(file->f_mode)))
- return 0;
-
/*
* read()/write() and other types of access generate pre-content events.
*/
@@ -160,7 +157,8 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
return ret;
}
- if (!(perm_mask & MAY_READ))
+ if (!(perm_mask & MAY_READ) ||
+ likely(!FMODE_FSNOTIFY_ACCESS_PERM(file->f_mode)))
return 0;
/*
@@ -208,22 +206,6 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
return fsnotify_file_area_perm(file, perm_mask, NULL, 0);
}
-/*
- * fsnotify_open_perm - permission hook before file open
- */
-static inline int fsnotify_open_perm(struct file *file)
-{
- int ret;
-
- if (file->f_flags & __FMODE_EXEC) {
- ret = fsnotify_path(&file->f_path, FS_OPEN_EXEC_PERM);
- if (ret)
- return ret;
- }
-
- return fsnotify_path(&file->f_path, FS_OPEN_PERM);
-}
-
#else
static inline int fsnotify_open_perm_and_set_mode(struct file *file)
{
@@ -251,11 +233,6 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
{
return 0;
}
-
-static inline int fsnotify_open_perm(struct file *file)
-{
- return 0;
-}
#endif
/*