Skip to content

Commit

Permalink
fanotify: Support merging of error events
Browse files Browse the repository at this point in the history
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.

Link: https://lore.kernel.org/r/20211025192746.66445-22-krisman@collabora.com
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
Signed-off-by: Jan Kara <jack@suse.cz>
  • Loading branch information
krisman-at-collabora authored and jankara committed Oct 27, 2021
1 parent 83e9acb commit 8a6ae64
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
26 changes: 24 additions & 2 deletions fs/notify/fanotify/fanotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -176,6 +189,10 @@ static int fanotify_merge(struct fsnotify_group *group,
break;
if (fanotify_should_merge(old, new)) {
old->mask |= new->mask;

if (fanotify_is_error_event(old->mask))
FANOTIFY_EE(old)->err_count++;

return 1;
}
}
Expand Down Expand Up @@ -577,7 +594,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);
Expand All @@ -591,6 +609,10 @@ static struct fanotify_event *fanotify_alloc_error_event(
return NULL;

fee->fae.type = FANOTIFY_EVENT_TYPE_FS_ERROR;
fee->err_count = 1;
fee->fsid = *fsid;

*hash ^= fanotify_hash_fsid(fsid);

return &fee->fae;
}
Expand Down Expand Up @@ -664,7 +686,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
event = fanotify_alloc_perm_event(path, gfp);
} else if (fanotify_is_error_event(mask)) {
event = fanotify_alloc_error_event(group, fsid, data,
data_type);
data_type, &hash);
} else if (name_event && (file_name || child)) {
event = fanotify_alloc_name_event(id, fsid, file_name, child,
&hash, gfp);
Expand Down
4 changes: 3 additions & 1 deletion fs/notify/fanotify/fanotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ FANOTIFY_NE(struct fanotify_event *event)

struct fanotify_error_event {
struct fanotify_event fae;
u32 err_count; /* Suppressed errors count */

__kernel_fsid_t fsid; /* FSID this error refers to. */
};

static inline struct fanotify_error_event *
Expand Down Expand Up @@ -332,7 +335,6 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event)
static inline bool fanotify_is_hashed_event(u32 mask)
{
return !(fanotify_is_perm_event(mask) ||
fanotify_is_error_event(mask) ||
fsnotify_is_overflow_event(mask));
}

Expand Down

0 comments on commit 8a6ae64

Please sign in to comment.