summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2021-03-04 12:48:26 +0200
committerJan Kara <jack@suse.cz>2021-03-16 16:38:29 +0100
commitb8cd0ee8cda68a888a317991c1e918a8cba1a568 (patch)
tree0f42ff64d788a11932bebc8fd4ce2b7ff11618f4 /fs
parent94e00d28a680dff18805ca472b191364347d2234 (diff)
fanotify: limit number of event merge attempts
Event merges are expensive when event queue size is large, so limit the linear search to 128 merge tests. In combination with 128 size hash table, there is a potential to merge with up to 16K events in the hashed queue. Link: https://lore.kernel.org/r/20210304104826.3993892-6-amir73il@gmail.com Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/notify/fanotify/fanotify.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 50b3abc06215..754e27ead874 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -148,6 +148,9 @@ static bool fanotify_should_merge(struct fanotify_event *old,
return false;
}
+/* Limit event merges to limit CPU overhead per event */
+#define FANOTIFY_MAX_MERGE_EVENTS 128
+
/* and the list better be locked by something too! */
static int fanotify_merge(struct fsnotify_group *group,
struct fsnotify_event *event)
@@ -155,6 +158,7 @@ static int fanotify_merge(struct fsnotify_group *group,
struct fanotify_event *old, *new = FANOTIFY_E(event);
unsigned int bucket = fanotify_event_hash_bucket(group, new);
struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket];
+ int i = 0;
pr_debug("%s: group=%p event=%p bucket=%u\n", __func__,
group, event, bucket);
@@ -168,6 +172,8 @@ static int fanotify_merge(struct fsnotify_group *group,
return 0;
hlist_for_each_entry(old, hlist, merge_list) {
+ if (++i > FANOTIFY_MAX_MERGE_EVENTS)
+ break;
if (fanotify_should_merge(old, new)) {
old->mask |= new->mask;
return 1;