Skip to content

Commit 8a6ae64

Browse files
krisman-at-collaborajankara
authored andcommitted
fanotify: Support merging of error events
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/[email protected] Reviewed-by: Amir Goldstein <[email protected]> Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Gabriel Krisman Bertazi <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 83e9acb commit 8a6ae64

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

fs/notify/fanotify/fanotify.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ static bool fanotify_name_event_equal(struct fanotify_name_event *fne1,
111111
return fanotify_info_equal(info1, info2);
112112
}
113113

114+
static bool fanotify_error_event_equal(struct fanotify_error_event *fee1,
115+
struct fanotify_error_event *fee2)
116+
{
117+
/* Error events against the same file system are always merged. */
118+
if (!fanotify_fsid_equal(&fee1->fsid, &fee2->fsid))
119+
return false;
120+
121+
return true;
122+
}
123+
114124
static bool fanotify_should_merge(struct fanotify_event *old,
115125
struct fanotify_event *new)
116126
{
@@ -141,6 +151,9 @@ static bool fanotify_should_merge(struct fanotify_event *old,
141151
case FANOTIFY_EVENT_TYPE_FID_NAME:
142152
return fanotify_name_event_equal(FANOTIFY_NE(old),
143153
FANOTIFY_NE(new));
154+
case FANOTIFY_EVENT_TYPE_FS_ERROR:
155+
return fanotify_error_event_equal(FANOTIFY_EE(old),
156+
FANOTIFY_EE(new));
144157
default:
145158
WARN_ON_ONCE(1);
146159
}
@@ -176,6 +189,10 @@ static int fanotify_merge(struct fsnotify_group *group,
176189
break;
177190
if (fanotify_should_merge(old, new)) {
178191
old->mask |= new->mask;
192+
193+
if (fanotify_is_error_event(old->mask))
194+
FANOTIFY_EE(old)->err_count++;
195+
179196
return 1;
180197
}
181198
}
@@ -577,7 +594,8 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
577594
static struct fanotify_event *fanotify_alloc_error_event(
578595
struct fsnotify_group *group,
579596
__kernel_fsid_t *fsid,
580-
const void *data, int data_type)
597+
const void *data, int data_type,
598+
unsigned int *hash)
581599
{
582600
struct fs_error_report *report =
583601
fsnotify_data_error_report(data, data_type);
@@ -591,6 +609,10 @@ static struct fanotify_event *fanotify_alloc_error_event(
591609
return NULL;
592610

593611
fee->fae.type = FANOTIFY_EVENT_TYPE_FS_ERROR;
612+
fee->err_count = 1;
613+
fee->fsid = *fsid;
614+
615+
*hash ^= fanotify_hash_fsid(fsid);
594616

595617
return &fee->fae;
596618
}
@@ -664,7 +686,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
664686
event = fanotify_alloc_perm_event(path, gfp);
665687
} else if (fanotify_is_error_event(mask)) {
666688
event = fanotify_alloc_error_event(group, fsid, data,
667-
data_type);
689+
data_type, &hash);
668690
} else if (name_event && (file_name || child)) {
669691
event = fanotify_alloc_name_event(id, fsid, file_name, child,
670692
&hash, gfp);

fs/notify/fanotify/fanotify.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ FANOTIFY_NE(struct fanotify_event *event)
199199

200200
struct fanotify_error_event {
201201
struct fanotify_event fae;
202+
u32 err_count; /* Suppressed errors count */
203+
204+
__kernel_fsid_t fsid; /* FSID this error refers to. */
202205
};
203206

204207
static inline struct fanotify_error_event *
@@ -332,7 +335,6 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event)
332335
static inline bool fanotify_is_hashed_event(u32 mask)
333336
{
334337
return !(fanotify_is_perm_event(mask) ||
335-
fanotify_is_error_event(mask) ||
336338
fsnotify_is_overflow_event(mask));
337339
}
338340

0 commit comments

Comments
 (0)