On Thu, Nov 14, 2024 at 9:44 AM Song Liu <song@xxxxxxxxxx> wrote: > > fanotify fastpath handler enables handling fanotify events within the > kernel, and thus saves a trip to the user space. fanotify fastpath handler > can be useful in many use cases. For example, if a user is only interested > in events for some files in side a directory, a fastpath handler can be > used to filter out irrelevant events. > > fanotify fastpath handler is attached to fsnotify_group. At most one > fastpath handler can be attached to a fsnotify_group. The attach/detach > of fastpath handlers are controlled by two new ioctls on the fanotify fds: > FAN_IOC_ADD_FP and FAN_IOC_DEL_FP. > > fanotify fastpath handler is packaged in a kernel module. In the future, > it is also possible to package fastpath handler in a BPF program. Since > loading modules requires CAP_SYS_ADMIN, _loading_ fanotify fastpath > handler in kernel modules is limited to CAP_SYS_ADMIN. However, > non-SYS_CAP_ADMIN users can _attach_ fastpath handler loaded by sys admin > to their fanotify fds. To make fanotify fastpath handler more useful > for non-CAP_SYS_ADMIN users, a fastpath handler can take arguments at > attach time. > > sysfs entry /sys/kernel/fanotify_fastpath is added to help users know > which fastpath handlers are available. At the moment, files are added for > each fastpath handler: flags, desc, and init_args. > > Signed-off-by: Song Liu <song@xxxxxxxxxx> > --- > fs/notify/fanotify/Kconfig | 13 ++ > fs/notify/fanotify/Makefile | 1 + > fs/notify/fanotify/fanotify.c | 29 +++ > fs/notify/fanotify/fanotify_fastpath.c | 282 +++++++++++++++++++++++++ > fs/notify/fanotify/fanotify_user.c | 7 + > include/linux/fanotify.h | 131 ++++++++++++ > include/linux/fsnotify_backend.h | 4 + > include/uapi/linux/fanotify.h | 25 +++ > 8 files changed, 492 insertions(+) > create mode 100644 fs/notify/fanotify/fanotify_fastpath.c > > diff --git a/fs/notify/fanotify/Kconfig b/fs/notify/fanotify/Kconfig > index 0e36aaf379b7..74677d3699a3 100644 > --- a/fs/notify/fanotify/Kconfig > +++ b/fs/notify/fanotify/Kconfig > @@ -24,3 +24,16 @@ config FANOTIFY_ACCESS_PERMISSIONS > hierarchical storage management systems. > > If unsure, say N. > + > +config FANOTIFY_FASTPATH > + bool "fanotify fastpath handler" > + depends on FANOTIFY > + default y > + help > + Say Y here if you want to use fanotify in kernel fastpath handler. > + The fastpath handler can be implemented in a kernel module or a > + BPF program. The fastpath handler can speed up fanotify in many > + use cases. For example, when the listener is only interested in > + a subset of events. > + > + If unsure, say Y. > \ No newline at end of file > diff --git a/fs/notify/fanotify/Makefile b/fs/notify/fanotify/Makefile > index 25ef222915e5..543cb7aa08fc 100644 > --- a/fs/notify/fanotify/Makefile > +++ b/fs/notify/fanotify/Makefile > @@ -1,2 +1,3 @@ > # SPDX-License-Identifier: GPL-2.0-only > obj-$(CONFIG_FANOTIFY) += fanotify.o fanotify_user.o > +obj-$(CONFIG_FANOTIFY_FASTPATH) += fanotify_fastpath.o > diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c > index 224bccaab4cc..b395b628a58b 100644 > --- a/fs/notify/fanotify/fanotify.c > +++ b/fs/notify/fanotify/fanotify.c > @@ -18,6 +18,8 @@ > > #include "fanotify.h" > > +extern struct srcu_struct fsnotify_mark_srcu; > + > static bool fanotify_path_equal(const struct path *p1, const struct path *p2) > { > return p1->mnt == p2->mnt && p1->dentry == p2->dentry; > @@ -888,6 +890,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, > struct fsnotify_event *fsn_event; > __kernel_fsid_t fsid = {}; > u32 match_mask = 0; > + struct fanotify_fastpath_hook *fp_hook __maybe_unused; > > BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS); > BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY); > @@ -933,6 +936,27 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, > if (FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS)) > fsid = fanotify_get_fsid(iter_info); > > +#ifdef CONFIG_FANOTIFY_FASTPATH > + fp_hook = srcu_dereference(group->fanotify_data.fp_hook, &fsnotify_mark_srcu); > + if (fp_hook) { > + struct fanotify_fastpath_event fp_event = { > + .mask = mask, > + .data = data, > + .data_type = data_type, > + .dir = dir, > + .file_name = file_name, > + .fsid = &fsid, > + .match_mask = match_mask, > + }; > + > + ret = fp_hook->ops->fp_handler(group, fp_hook, &fp_event); > + if (ret == FAN_FP_RET_SKIP_EVENT) { > + ret = 0; > + goto finish; > + } > + } > +#endif > + To me it makes sense that the fastpath module could also return a negative (deny) result for permission events. Is there a specific reason that you did not handle this or just didn't think of this option? Thanks, Amir.