Skip to content

Commit 47d9c7c

Browse files
amir73iljankara
authored andcommitted
fsnotify: generalize iteration of marks by object type
Make some code that handles marks of object types inode and vfsmount generic, so it can handle other object types. Introduce fsnotify_foreach_obj_type macro to iterate marks by object type and fsnotify_iter_{should|set}_report_type macros to set/test report_mask. This is going to be used for adding mark of another object type (super block mark). Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent d9a6f30 commit 47d9c7c

File tree

4 files changed

+72
-39
lines changed

4 files changed

+72
-39
lines changed

fs/notify/fsnotify.c

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -269,25 +269,29 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
269269
static unsigned int fsnotify_iter_select_report_types(
270270
struct fsnotify_iter_info *iter_info)
271271
{
272-
struct fsnotify_mark *inode_mark = iter_info->inode_mark;
273-
struct fsnotify_mark *vfsmount_mark = iter_info->vfsmount_mark;
274-
int cmp;
272+
struct fsnotify_group *max_prio_group = NULL;
273+
struct fsnotify_mark *mark;
274+
int type;
275+
276+
/* Choose max prio group among groups of all queue heads */
277+
fsnotify_foreach_obj_type(type) {
278+
mark = iter_info->marks[type];
279+
if (mark &&
280+
fsnotify_compare_groups(max_prio_group, mark->group) > 0)
281+
max_prio_group = mark->group;
282+
}
275283

276-
if (!inode_mark && !vfsmount_mark)
284+
if (!max_prio_group)
277285
return 0;
278286

279-
if (inode_mark && vfsmount_mark) {
280-
cmp = fsnotify_compare_groups(inode_mark->group,
281-
vfsmount_mark->group);
282-
} else {
283-
cmp = inode_mark ? -1 : 1;
284-
}
285-
287+
/* Set the report mask for marks from same group as max prio group */
286288
iter_info->report_mask = 0;
287-
if (cmp <= 0)
288-
iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_INODE_FL;
289-
if (cmp >= 0)
290-
iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL;
289+
fsnotify_foreach_obj_type(type) {
290+
mark = iter_info->marks[type];
291+
if (mark &&
292+
fsnotify_compare_groups(max_prio_group, mark->group) == 0)
293+
fsnotify_iter_set_report_type(iter_info, type);
294+
}
291295

292296
return iter_info->report_mask;
293297
}
@@ -298,13 +302,13 @@ static unsigned int fsnotify_iter_select_report_types(
298302
*/
299303
static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
300304
{
301-
if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_INODE_FL)
302-
iter_info->inode_mark =
303-
fsnotify_next_mark(iter_info->inode_mark);
305+
int type;
304306

305-
if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL)
306-
iter_info->vfsmount_mark =
307-
fsnotify_next_mark(iter_info->vfsmount_mark);
307+
fsnotify_foreach_obj_type(type) {
308+
if (fsnotify_iter_should_report_type(iter_info, type))
309+
iter_info->marks[type] =
310+
fsnotify_next_mark(iter_info->marks[type]);
311+
}
308312
}
309313

310314
/*
@@ -351,15 +355,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
351355

352356
if ((mask & FS_MODIFY) ||
353357
(test_mask & to_tell->i_fsnotify_mask)) {
354-
iter_info.inode_mark =
358+
iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
355359
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
356360
}
357361

358362
if (mnt && ((mask & FS_MODIFY) ||
359363
(test_mask & mnt->mnt_fsnotify_mask))) {
360-
iter_info.inode_mark =
364+
iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
361365
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
362-
iter_info.vfsmount_mark =
366+
iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
363367
fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
364368
}
365369

fs/notify/inotify/inotify_user.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,10 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
485485
struct fsnotify_group *group)
486486
{
487487
struct inotify_inode_mark *i_mark;
488-
struct fsnotify_iter_info iter_info = {
489-
.inode_mark = fsn_mark,
490-
.report_mask = FSNOTIFY_OBJ_TYPE_INODE_FL,
491-
};
488+
struct fsnotify_iter_info iter_info = { };
489+
490+
fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE,
491+
fsn_mark);
492492

493493
/* Queue ignore event for the watch */
494494
inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL,

fs/notify/mark.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark)
294294

295295
bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
296296
{
297-
/* This can fail if mark is being removed */
298-
if (!fsnotify_get_mark_safe(iter_info->inode_mark))
299-
return false;
300-
if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) {
301-
fsnotify_put_mark_wake(iter_info->inode_mark);
302-
return false;
297+
int type;
298+
299+
fsnotify_foreach_obj_type(type) {
300+
/* This can fail if mark is being removed */
301+
if (!fsnotify_get_mark_safe(iter_info->marks[type]))
302+
goto fail;
303303
}
304304

305305
/*
@@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
310310
srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx);
311311

312312
return true;
313+
314+
fail:
315+
for (type--; type >= 0; type--)
316+
fsnotify_put_mark_wake(iter_info->marks[type]);
317+
return false;
313318
}
314319

315320
void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info)
316321
{
322+
int type;
323+
317324
iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
318-
fsnotify_put_mark_wake(iter_info->inode_mark);
319-
fsnotify_put_mark_wake(iter_info->vfsmount_mark);
325+
fsnotify_foreach_obj_type(type)
326+
fsnotify_put_mark_wake(iter_info->marks[type]);
320327
}
321328

322329
/*

include/linux/fsnotify_backend.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,23 +211,45 @@ enum fsnotify_obj_type {
211211
#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
212212

213213
struct fsnotify_iter_info {
214-
struct fsnotify_mark *inode_mark;
215-
struct fsnotify_mark *vfsmount_mark;
214+
struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT];
216215
unsigned int report_mask;
217216
int srcu_idx;
218217
};
219218

219+
static inline bool fsnotify_iter_should_report_type(
220+
struct fsnotify_iter_info *iter_info, int type)
221+
{
222+
return (iter_info->report_mask & (1U << type));
223+
}
224+
225+
static inline void fsnotify_iter_set_report_type(
226+
struct fsnotify_iter_info *iter_info, int type)
227+
{
228+
iter_info->report_mask |= (1U << type);
229+
}
230+
231+
static inline void fsnotify_iter_set_report_type_mark(
232+
struct fsnotify_iter_info *iter_info, int type,
233+
struct fsnotify_mark *mark)
234+
{
235+
iter_info->marks[type] = mark;
236+
iter_info->report_mask |= (1U << type);
237+
}
238+
220239
#define FSNOTIFY_ITER_FUNCS(name, NAME) \
221240
static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \
222241
struct fsnotify_iter_info *iter_info) \
223242
{ \
224243
return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \
225-
iter_info->name##_mark : NULL; \
244+
iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \
226245
}
227246

228247
FSNOTIFY_ITER_FUNCS(inode, INODE)
229248
FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT)
230249

250+
#define fsnotify_foreach_obj_type(type) \
251+
for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++)
252+
231253
/*
232254
* Inode / vfsmount point to this structure which tracks all marks attached to
233255
* the inode / vfsmount. The reference to inode / vfsmount is held by this

0 commit comments

Comments
 (0)