Commit 47d9c7cc authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara

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: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent d9a6f30b
...@@ -269,25 +269,29 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark) ...@@ -269,25 +269,29 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
static unsigned int fsnotify_iter_select_report_types( static unsigned int fsnotify_iter_select_report_types(
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
struct fsnotify_mark *inode_mark = iter_info->inode_mark; struct fsnotify_group *max_prio_group = NULL;
struct fsnotify_mark *vfsmount_mark = iter_info->vfsmount_mark; struct fsnotify_mark *mark;
int cmp; int type;
/* Choose max prio group among groups of all queue heads */
fsnotify_foreach_obj_type(type) {
mark = iter_info->marks[type];
if (mark &&
fsnotify_compare_groups(max_prio_group, mark->group) > 0)
max_prio_group = mark->group;
}
if (!inode_mark && !vfsmount_mark) if (!max_prio_group)
return 0; return 0;
if (inode_mark && vfsmount_mark) { /* Set the report mask for marks from same group as max prio group */
cmp = fsnotify_compare_groups(inode_mark->group,
vfsmount_mark->group);
} else {
cmp = inode_mark ? -1 : 1;
}
iter_info->report_mask = 0; iter_info->report_mask = 0;
if (cmp <= 0) fsnotify_foreach_obj_type(type) {
iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_INODE_FL; mark = iter_info->marks[type];
if (cmp >= 0) if (mark &&
iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL; fsnotify_compare_groups(max_prio_group, mark->group) == 0)
fsnotify_iter_set_report_type(iter_info, type);
}
return iter_info->report_mask; return iter_info->report_mask;
} }
...@@ -298,13 +302,13 @@ static unsigned int fsnotify_iter_select_report_types( ...@@ -298,13 +302,13 @@ static unsigned int fsnotify_iter_select_report_types(
*/ */
static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
{ {
if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_INODE_FL) int type;
iter_info->inode_mark =
fsnotify_next_mark(iter_info->inode_mark);
if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL) fsnotify_foreach_obj_type(type) {
iter_info->vfsmount_mark = if (fsnotify_iter_should_report_type(iter_info, type))
fsnotify_next_mark(iter_info->vfsmount_mark); iter_info->marks[type] =
fsnotify_next_mark(iter_info->marks[type]);
}
} }
/* /*
...@@ -351,15 +355,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, ...@@ -351,15 +355,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
if ((mask & FS_MODIFY) || if ((mask & FS_MODIFY) ||
(test_mask & to_tell->i_fsnotify_mask)) { (test_mask & to_tell->i_fsnotify_mask)) {
iter_info.inode_mark = iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
fsnotify_first_mark(&to_tell->i_fsnotify_marks); fsnotify_first_mark(&to_tell->i_fsnotify_marks);
} }
if (mnt && ((mask & FS_MODIFY) || if (mnt && ((mask & FS_MODIFY) ||
(test_mask & mnt->mnt_fsnotify_mask))) { (test_mask & mnt->mnt_fsnotify_mask))) {
iter_info.inode_mark = iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
fsnotify_first_mark(&to_tell->i_fsnotify_marks); fsnotify_first_mark(&to_tell->i_fsnotify_marks);
iter_info.vfsmount_mark = iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
fsnotify_first_mark(&mnt->mnt_fsnotify_marks); fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
} }
......
...@@ -485,10 +485,10 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, ...@@ -485,10 +485,10 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
struct fsnotify_group *group) struct fsnotify_group *group)
{ {
struct inotify_inode_mark *i_mark; struct inotify_inode_mark *i_mark;
struct fsnotify_iter_info iter_info = { struct fsnotify_iter_info iter_info = { };
.inode_mark = fsn_mark,
.report_mask = FSNOTIFY_OBJ_TYPE_INODE_FL, fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE,
}; fsn_mark);
/* Queue ignore event for the watch */ /* Queue ignore event for the watch */
inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL, inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL,
......
...@@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark) ...@@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark)
bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
{ {
/* This can fail if mark is being removed */ int type;
if (!fsnotify_get_mark_safe(iter_info->inode_mark))
return false; fsnotify_foreach_obj_type(type) {
if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) { /* This can fail if mark is being removed */
fsnotify_put_mark_wake(iter_info->inode_mark); if (!fsnotify_get_mark_safe(iter_info->marks[type]))
return false; goto fail;
} }
/* /*
...@@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) ...@@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx); srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx);
return true; return true;
fail:
for (type--; type >= 0; type--)
fsnotify_put_mark_wake(iter_info->marks[type]);
return false;
} }
void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info)
{ {
int type;
iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
fsnotify_put_mark_wake(iter_info->inode_mark); fsnotify_foreach_obj_type(type)
fsnotify_put_mark_wake(iter_info->vfsmount_mark); fsnotify_put_mark_wake(iter_info->marks[type]);
} }
/* /*
......
...@@ -211,23 +211,45 @@ enum fsnotify_obj_type { ...@@ -211,23 +211,45 @@ enum fsnotify_obj_type {
#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
struct fsnotify_iter_info { struct fsnotify_iter_info {
struct fsnotify_mark *inode_mark; struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT];
struct fsnotify_mark *vfsmount_mark;
unsigned int report_mask; unsigned int report_mask;
int srcu_idx; int srcu_idx;
}; };
static inline bool fsnotify_iter_should_report_type(
struct fsnotify_iter_info *iter_info, int type)
{
return (iter_info->report_mask & (1U << type));
}
static inline void fsnotify_iter_set_report_type(
struct fsnotify_iter_info *iter_info, int type)
{
iter_info->report_mask |= (1U << type);
}
static inline void fsnotify_iter_set_report_type_mark(
struct fsnotify_iter_info *iter_info, int type,
struct fsnotify_mark *mark)
{
iter_info->marks[type] = mark;
iter_info->report_mask |= (1U << type);
}
#define FSNOTIFY_ITER_FUNCS(name, NAME) \ #define FSNOTIFY_ITER_FUNCS(name, NAME) \
static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \
struct fsnotify_iter_info *iter_info) \ struct fsnotify_iter_info *iter_info) \
{ \ { \
return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \ return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \
iter_info->name##_mark : NULL; \ iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \
} }
FSNOTIFY_ITER_FUNCS(inode, INODE) FSNOTIFY_ITER_FUNCS(inode, INODE)
FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT)
#define fsnotify_foreach_obj_type(type) \
for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++)
/* /*
* Inode / vfsmount point to this structure which tracks all marks attached to * Inode / vfsmount point to this structure which tracks all marks attached to
* the inode / vfsmount. The reference to inode / vfsmount is held by this * the inode / vfsmount. The reference to inode / vfsmount is held by this
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment