On Fri, Oct 15, 2021 at 12:39 AM Gabriel Krisman Bertazi <krisman@xxxxxxxxxxxxx> wrote: > > Error events (FAN_FS_ERROR) against the same file system can be merged > by simply iterating the error count. The hash is taken from the fsid, > without considering the FH. This means that only the first error object > is reported. > > Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxxxxxxxx> > --- > fs/notify/fanotify/fanotify.c | 39 ++++++++++++++++++++++++++++++++--- > fs/notify/fanotify/fanotify.h | 4 +++- > 2 files changed, 39 insertions(+), 4 deletions(-) > > diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c > index 9b970359570a..7032083df62a 100644 > --- a/fs/notify/fanotify/fanotify.c > +++ b/fs/notify/fanotify/fanotify.c > @@ -111,6 +111,16 @@ static bool fanotify_name_event_equal(struct fanotify_name_event *fne1, > return fanotify_info_equal(info1, info2); > } > > +static bool fanotify_error_event_equal(struct fanotify_error_event *fee1, > + struct fanotify_error_event *fee2) > +{ > + /* Error events against the same file system are always merged. */ > + if (!fanotify_fsid_equal(&fee1->fsid, &fee2->fsid)) > + return false; > + > + return true; > +} > + > static bool fanotify_should_merge(struct fanotify_event *old, > struct fanotify_event *new) > { > @@ -141,6 +151,9 @@ static bool fanotify_should_merge(struct fanotify_event *old, > case FANOTIFY_EVENT_TYPE_FID_NAME: > return fanotify_name_event_equal(FANOTIFY_NE(old), > FANOTIFY_NE(new)); > + case FANOTIFY_EVENT_TYPE_FS_ERROR: > + return fanotify_error_event_equal(FANOTIFY_EE(old), > + FANOTIFY_EE(new)); > default: > WARN_ON_ONCE(1); > } > @@ -148,6 +161,22 @@ static bool fanotify_should_merge(struct fanotify_event *old, > return false; > } > > +static void fanotify_merge_error_event(struct fanotify_error_event *dest, > + struct fanotify_error_event *origin) > +{ > + dest->err_count++; > +} > + > +static void fanotify_merge_event(struct fanotify_event *dest, > + struct fanotify_event *origin) > +{ > + dest->mask |= origin->mask; > + > + if (origin->type == FANOTIFY_EVENT_TYPE_FS_ERROR) > + fanotify_merge_error_event(FANOTIFY_EE(dest), > + FANOTIFY_EE(origin)); > +} > + > /* Limit event merges to limit CPU overhead per event */ > #define FANOTIFY_MAX_MERGE_EVENTS 128 > > @@ -175,7 +204,7 @@ static int fanotify_merge(struct fsnotify_group *group, > if (++i > FANOTIFY_MAX_MERGE_EVENTS) > break; > if (fanotify_should_merge(old, new)) { > - old->mask |= new->mask; > + fanotify_merge_event(old, new); > return 1; > } > } > @@ -577,7 +606,8 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id, > static struct fanotify_event *fanotify_alloc_error_event( > struct fsnotify_group *group, > __kernel_fsid_t *fsid, > - const void *data, int data_type) > + const void *data, int data_type, > + unsigned int *hash) > { > struct fs_error_report *report = > fsnotify_data_error_report(data, data_type); > @@ -591,6 +621,9 @@ static struct fanotify_event *fanotify_alloc_error_event( > return NULL; > > fee->fae.type = FANOTIFY_EVENT_TYPE_FS_ERROR; > + fee->err_count = 1; > + > + *hash ^= fanotify_hash_fsid(fsid); > > return &fee->fae; > } Forgot to store fee->fsid? Thanks, Amir.