diff mbox series

[4/7] fanotify: enable hashed notification queue for FAN_CLASS_NOTIF groups

Message ID 20210202162010.305971-5-amir73il@gmail.com (mailing list archive)
State New, archived
Headers show
Series Performance improvement for fanotify merge | expand

Commit Message

Amir Goldstein Feb. 2, 2021, 4:20 p.m. UTC
To improve performace of merging events when there is a large queue of
events, enable hashed notification queue for FAN_CLASS_NOTIF groups.

Use 128 hash buckets to reduce the avg. event list size by 128.
With the default queue size, that leads to avg. max list size of 128.

When fanotify permission event is canceled, event can be removed
from the middle of the queue and that can break the read order of
events in a hashed queue.  For now, we do not support hashed queue
with any classes that supports permission events.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify_user.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index dee12d927f8d..641c20ad96e4 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -29,6 +29,11 @@ 
 #define FANOTIFY_DEFAULT_MAX_EVENTS	16384
 #define FANOTIFY_DEFAULT_MAX_MARKS	8192
 #define FANOTIFY_DEFAULT_MAX_LISTENERS	128
+/*
+ * 128 hash buckets for fast events merge.
+ * With the default queue size, that leads to avg. list size of 128.
+ */
+#define FANOTIFY_NOTIF_Q_HASH_BITS	7
 
 /*
  * All flags that may be specified in parameter event_f_flags of fanotify_init.
@@ -941,6 +946,7 @@  SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	struct user_struct *user;
 	unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
 	unsigned int class = flags & FANOTIFY_CLASS_BITS;
+	unsigned int q_hash_bits = 0;
 
 	pr_debug("%s: flags=%x event_f_flags=%x\n",
 		 __func__, flags, event_f_flags);
@@ -989,8 +995,17 @@  SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	if (flags & FAN_NONBLOCK)
 		f_flags |= O_NONBLOCK;
 
+	/*
+	 * When fanotify permission event is canceled, event can be removed
+	 * from the middle of the queue and that can break the read order of
+	 * events in a hashed queue.  For now, we do not support hashed queue
+	 * with any classes that supports permission events.
+	 */
+	if (class == FAN_CLASS_NOTIF)
+		q_hash_bits = FANOTIFY_NOTIF_Q_HASH_BITS;
+
 	/* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
-	group = fsnotify_alloc_user_group(0, &fanotify_fsnotify_ops);
+	group = fsnotify_alloc_user_group(q_hash_bits, &fanotify_fsnotify_ops);
 	if (IS_ERR(group)) {
 		free_uid(user);
 		return PTR_ERR(group);