From: Amir Goldstein <amir73il@gmail.com>
To: Jan Kara <jack@suse.cz>
Cc: Christian Brauner <brauner@kernel.org>, linux-fsdevel@vger.kernel.org
Subject: [PATCH v2 04/10] fanotify: test event->type instead of event mask when possible
Date: Fri, 24 Apr 2026 19:04:57 +0200 [thread overview]
Message-ID: <20260424170503.2096847-5-amir73il@gmail.com> (raw)
In-Reply-To: <20260424170503.2096847-1-amir73il@gmail.com>
The fanotify_event already has a type field, so tests like
fanotify_is_mnt_event() should check the type and not the mask.
In fanotify_alloc_event() determine the mnt and fs_error event
types by data_type, which uniquely identifies those events.
The helper for classifying an fs permission event is renamed to
fanotify_is_fs_perm_event() and takes the group argument to verify
that this is a filesystem group type.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/notify/fanotify/fanotify.c | 30 +++++++++++++++---------------
fs/notify/fanotify/fanotify.h | 29 +++++++++++++++++++++--------
fs/notify/fanotify/fanotify_user.c | 18 +++++++++---------
include/linux/fsnotify_backend.h | 5 -----
4 files changed, 45 insertions(+), 37 deletions(-)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 494bba49634e1..80116026d3ae0 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -195,7 +195,7 @@ static int fanotify_merge(struct fsnotify_group *group,
* the event structure we have created in fanotify_handle_event() is the
* one we should check for permission response.
*/
- if (fanotify_is_perm_event(new->mask))
+ if (fanotify_is_perm_event(new))
return 0;
hlist_for_each_entry(old, hlist, merge_list) {
@@ -204,7 +204,7 @@ static int fanotify_merge(struct fsnotify_group *group,
if (fanotify_should_merge(old, new)) {
old->mask |= new->mask;
- if (fanotify_is_error_event(old->mask))
+ if (fanotify_is_error_event(old))
FANOTIFY_EE(old)->err_count++;
return 1;
@@ -711,11 +711,9 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,
static struct fanotify_event *fanotify_alloc_error_event(
struct fsnotify_group *group,
__kernel_fsid_t *fsid,
- const void *data, int data_type,
+ struct fs_error_report *report,
unsigned int *hash)
{
- struct fs_error_report *report =
- fsnotify_data_error_report(data, data_type);
struct inode *inode;
struct fanotify_error_event *fee;
int fh_len;
@@ -759,6 +757,8 @@ static struct fanotify_event *fanotify_alloc_event(
fid_mode);
struct inode *dirid = fanotify_dfid_inode(mask, data, data_type, dir);
const struct path *path = fsnotify_data_path(data, data_type);
+ struct fs_error_report *fs_error =
+ fsnotify_data_error_report(data, data_type);
u64 mnt_id = fsnotify_data_mnt_id(data, data_type);
struct mem_cgroup *old_memcg;
struct dentry *moved = NULL;
@@ -845,11 +845,10 @@ static struct fanotify_event *fanotify_alloc_event(
/* Whoever is interested in the event, pays for the allocation. */
old_memcg = set_active_memcg(group->memcg);
- if (fanotify_is_perm_event(mask)) {
+ if (fanotify_is_fs_perm_event(group, mask)) {
event = fanotify_alloc_perm_event(data, data_type, gfp);
- } else if (fanotify_is_error_event(mask)) {
- event = fanotify_alloc_error_event(group, fsid, data,
- data_type, &hash);
+ } else if (fs_error) {
+ event = fanotify_alloc_error_event(group, fsid, fs_error, &hash);
} else if (name_event && (file_name || moved || child)) {
event = fanotify_alloc_name_event(dirid, fsid, file_name, child,
moved, &hash, gfp);
@@ -916,7 +915,7 @@ static void fanotify_insert_event(struct fsnotify_group *group,
assert_spin_locked(&group->notification_lock);
- if (!fanotify_is_hashed_event(event->mask))
+ if (!fanotify_is_hashed_event(event))
return;
pr_debug("%s: group=%p event=%p bucket=%u\n", __func__,
@@ -970,7 +969,8 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
pr_debug("%s: group=%p mask=%x report_mask=%x\n", __func__,
group, mask, match_mask);
- if (fanotify_is_perm_event(mask)) {
+ bool is_perm = fanotify_is_fs_perm_event(group, mask);
+ if (is_perm) {
/*
* fsnotify_prepare_user_wait() fails if we race with mark
* deletion. Just let the operation pass in that case.
@@ -990,7 +990,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
* We don't queue overflow events for permission events as
* there the access is denied and so no event is in fact lost.
*/
- if (!fanotify_is_perm_event(mask))
+ if (!is_perm)
fsnotify_queue_overflow(group);
goto finish;
}
@@ -1000,17 +1000,17 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
fanotify_insert_event);
if (ret) {
/* Permission events shouldn't be merged */
- BUG_ON(ret == 1 && mask & FANOTIFY_PERM_EVENTS);
+ WARN_ON(ret == 1 && is_perm);
/* Our event wasn't used in the end. Free it. */
fsnotify_destroy_event(group, fsn_event);
ret = 0;
- } else if (fanotify_is_perm_event(mask)) {
+ } else if (is_perm) {
ret = fanotify_get_response(group, FANOTIFY_PERM(event),
iter_info);
}
finish:
- if (fanotify_is_perm_event(mask))
+ if (is_perm)
fsnotify_finish_user_wait(iter_info);
return ret;
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index a0619e7694d57..13e3787ddd558 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -265,6 +265,7 @@ struct fanotify_event {
struct pid *pid;
};
+
static inline void fanotify_init_event(struct fanotify_event *event,
unsigned int hash, u32 mask)
{
@@ -457,12 +458,24 @@ FANOTIFY_PERM(struct fanotify_event *event)
return container_of(event, struct fanotify_perm_event, fae);
}
-static inline bool fanotify_is_perm_event(u32 mask)
+static inline bool fanotify_is_fs_perm_event(struct fsnotify_group *group,
+ u32 mask)
{
return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) &&
+ fsnotify_is_fs_watcher(group) &&
mask & FANOTIFY_PERM_EVENTS;
}
+static inline bool fanotify_is_perm_event(struct fanotify_event *event)
+{
+ return event->type == FANOTIFY_EVENT_TYPE_PATH_PERM;
+}
+
+static inline bool fsnotify_is_overflow_event(struct fanotify_event *event)
+{
+ return event->type == FANOTIFY_EVENT_TYPE_OVERFLOW;
+}
+
static inline bool fanotify_event_has_access_range(struct fanotify_event *event)
{
if (!(event->mask & FANOTIFY_PRE_CONTENT_EVENTS))
@@ -476,14 +489,14 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
return container_of(fse, struct fanotify_event, fse);
}
-static inline bool fanotify_is_error_event(u32 mask)
+static inline bool fanotify_is_error_event(struct fanotify_event *event)
{
- return mask & FAN_FS_ERROR;
+ return event->type == FANOTIFY_EVENT_TYPE_FS_ERROR;
}
-static inline bool fanotify_is_mnt_event(u32 mask)
+static inline bool fanotify_is_mnt_event(struct fanotify_event *event)
{
- return mask & (FAN_MNT_ATTACH | FAN_MNT_DETACH);
+ return event->type == FANOTIFY_EVENT_TYPE_MNT;
}
static inline const struct path *fanotify_event_path(struct fanotify_event *event)
@@ -506,10 +519,10 @@ static inline const struct path *fanotify_event_path(struct fanotify_event *even
/*
* Permission events and overflow event do not get merged - don't hash them.
*/
-static inline bool fanotify_is_hashed_event(u32 mask)
+static inline bool fanotify_is_hashed_event(struct fanotify_event *event)
{
- return !(fanotify_is_perm_event(mask) ||
- fsnotify_is_overflow_event(mask));
+ return !(fanotify_is_perm_event(event) ||
+ fsnotify_is_overflow_event(event));
}
static inline unsigned int fanotify_event_hash_bucket(
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 7afb017d40f50..c41c83d86518a 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -257,7 +257,7 @@ static size_t fanotify_event_len(unsigned int info_mode,
int fh_len;
int dot_len = 0;
- if (fanotify_is_error_event(event->mask))
+ if (fanotify_is_error_event(event))
event_len += FANOTIFY_ERROR_INFO_LEN;
if (fanotify_event_has_any_dir_fh(event)) {
@@ -275,7 +275,7 @@ static size_t fanotify_event_len(unsigned int info_mode,
fh_len = fanotify_event_object_fh_len(event);
event_len += fanotify_fid_info_len(fh_len, dot_len);
}
- if (fanotify_is_mnt_event(event->mask))
+ if (fanotify_is_mnt_event(event))
event_len += FANOTIFY_MNT_INFO_LEN;
if (info_mode & FAN_REPORT_PIDFD)
@@ -338,9 +338,9 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group,
* same event we peeked above.
*/
fsnotify_remove_first_event(group);
- if (fanotify_is_perm_event(event->mask))
+ if (fanotify_is_perm_event(event))
FANOTIFY_PERM(event)->state = FAN_EVENT_REPORTED;
- if (fanotify_is_hashed_event(event->mask))
+ if (fanotify_is_hashed_event(event))
fanotify_unhash_event(group, event);
out:
spin_unlock(&group->notification_lock);
@@ -800,7 +800,7 @@ static int copy_info_records_to_user(struct fanotify_event *event,
total_bytes += ret;
}
- if (fanotify_is_error_event(event->mask)) {
+ if (fanotify_is_error_event(event)) {
ret = copy_error_info_to_user(event, buf, count);
if (ret < 0)
return ret;
@@ -818,7 +818,7 @@ static int copy_info_records_to_user(struct fanotify_event *event,
total_bytes += ret;
}
- if (fanotify_is_mnt_event(event->mask)) {
+ if (fanotify_is_mnt_event(event)) {
ret = copy_mnt_info_to_user(event, buf, count);
if (ret < 0)
return ret;
@@ -965,7 +965,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
if (pidfd_file)
fd_install(pidfd, pidfd_file);
- if (fanotify_is_perm_event(event->mask))
+ if (fanotify_is_perm_event(event))
FANOTIFY_PERM(event)->fd = fd;
return metadata.event_len;
@@ -1048,7 +1048,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
* Permission events get queued to wait for response. Other
* events can be destroyed now.
*/
- if (!fanotify_is_perm_event(event->mask)) {
+ if (!fanotify_is_perm_event(event)) {
fsnotify_destroy_event(group, &event->fse);
} else {
if (ret <= 0 || FANOTIFY_PERM(event)->fd < 0) {
@@ -1145,7 +1145,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)
while ((fsn_event = fsnotify_remove_first_event(group))) {
struct fanotify_event *event = FANOTIFY_E(fsn_event);
- if (!(event->mask & FANOTIFY_PERM_EVENTS)) {
+ if (!fanotify_is_perm_event(event)) {
spin_unlock(&group->notification_lock);
fsnotify_destroy_event(group, fsn_event);
} else {
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 8f2821735f068..9ce08d03d041d 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -783,11 +783,6 @@ static inline void fsnotify_queue_overflow(struct fsnotify_group *group)
fsnotify_add_event(group, group->overflow_event, NULL);
}
-static inline bool fsnotify_is_overflow_event(u32 mask)
-{
- return mask & FS_Q_OVERFLOW;
-}
-
static inline bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group)
{
assert_spin_locked(&group->notification_lock);
--
2.54.0
next prev parent reply other threads:[~2026-04-24 17:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-24 17:04 [PATCH v2 00/10] fanotify namespace monitoring Amir Goldstein
2026-04-24 17:04 ` [PATCH v2 01/10] fsnotify: rename fsnotify group flag macros Amir Goldstein
2026-04-24 17:04 ` [PATCH v2 02/10] fsnotify: introduce fsnotify group types Amir Goldstein
2026-04-24 17:04 ` [PATCH v2 03/10] fsnotify: separate the events bitmask macros by group type Amir Goldstein
2026-04-24 17:04 ` Amir Goldstein [this message]
2026-04-24 17:04 ` [PATCH v2 05/10] fsnotify: do not report mount events with fsnotify() Amir Goldstein
2026-04-24 17:04 ` [PATCH v2 06/10] fanotify: gate fs event classification by group type Amir Goldstein
2026-04-24 17:05 ` [PATCH v2 07/10] fanotify: gate fs events checks in fanotify_mark() " Amir Goldstein
2026-04-24 17:05 ` [PATCH v2 08/10] fanotify: add support for watching the namespaces tree Amir Goldstein
2026-04-24 17:05 ` [PATCH v2 09/10] selftests/filesystems: create fanotify test dir Amir Goldstein
2026-04-24 17:05 ` [PATCH v2 10/10] selftests/filesystems: add fanotify namespace notifications test Amir Goldstein
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260424170503.2096847-5-amir73il@gmail.com \
--to=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox