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>
This commit is contained in:
Amir Goldstein 2021-03-04 12:48:26 +02:00 committed by Jan Kara
parent 94e00d28a6
commit b8cd0ee8cd

View file

@ -148,6 +148,9 @@ static bool fanotify_should_merge(struct fanotify_event *old,
return false; 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! */ /* and the list better be locked by something too! */
static int fanotify_merge(struct fsnotify_group *group, static int fanotify_merge(struct fsnotify_group *group,
struct fsnotify_event *event) struct fsnotify_event *event)
@ -155,6 +158,7 @@ static int fanotify_merge(struct fsnotify_group *group,
struct fanotify_event *old, *new = FANOTIFY_E(event); struct fanotify_event *old, *new = FANOTIFY_E(event);
unsigned int bucket = fanotify_event_hash_bucket(group, new); unsigned int bucket = fanotify_event_hash_bucket(group, new);
struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket]; struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket];
int i = 0;
pr_debug("%s: group=%p event=%p bucket=%u\n", __func__, pr_debug("%s: group=%p event=%p bucket=%u\n", __func__,
group, event, bucket); group, event, bucket);
@ -168,6 +172,8 @@ static int fanotify_merge(struct fsnotify_group *group,
return 0; return 0;
hlist_for_each_entry(old, hlist, merge_list) { hlist_for_each_entry(old, hlist, merge_list) {
if (++i > FANOTIFY_MAX_MERGE_EVENTS)
break;
if (fanotify_should_merge(old, new)) { if (fanotify_should_merge(old, new)) {
old->mask |= new->mask; old->mask |= new->mask;
return 1; return 1;