]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
fsnotify: generalize iteration of marks by object type
authorAmir Goldstein <amir73il@gmail.com>
Fri, 20 Apr 2018 23:10:52 +0000 (16:10 -0700)
committerJan Kara <jack@suse.cz>
Fri, 18 May 2018 12:58:22 +0000 (14:58 +0200)
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 <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/notify/fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/mark.c
include/linux/fsnotify_backend.h

index 98e91037b11ddd4e53eab5df3a91345508ab9ef8..bc9a51480156209124c0396c068a2f40ccaed9b6 100644 (file)
@@ -269,25 +269,29 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
 static unsigned int fsnotify_iter_select_report_types(
                struct fsnotify_iter_info *iter_info)
 {
-       struct fsnotify_mark *inode_mark = iter_info->inode_mark;
-       struct fsnotify_mark *vfsmount_mark = iter_info->vfsmount_mark;
-       int cmp;
+       struct fsnotify_group *max_prio_group = NULL;
+       struct fsnotify_mark *mark;
+       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;
 
-       if (inode_mark && vfsmount_mark) {
-               cmp = fsnotify_compare_groups(inode_mark->group,
-                                             vfsmount_mark->group);
-       } else {
-               cmp = inode_mark ? -1 : 1;
-       }
-
+       /* Set the report mask for marks from same group as max prio group */
        iter_info->report_mask = 0;
-       if (cmp <= 0)
-               iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_INODE_FL;
-       if (cmp >= 0)
-               iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL;
+       fsnotify_foreach_obj_type(type) {
+               mark = iter_info->marks[type];
+               if (mark &&
+                   fsnotify_compare_groups(max_prio_group, mark->group) == 0)
+                       fsnotify_iter_set_report_type(iter_info, type);
+       }
 
        return iter_info->report_mask;
 }
@@ -298,13 +302,13 @@ static unsigned int fsnotify_iter_select_report_types(
  */
 static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
 {
-       if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_INODE_FL)
-               iter_info->inode_mark =
-                       fsnotify_next_mark(iter_info->inode_mark);
+       int type;
 
-       if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL)
-               iter_info->vfsmount_mark =
-                       fsnotify_next_mark(iter_info->vfsmount_mark);
+       fsnotify_foreach_obj_type(type) {
+               if (fsnotify_iter_should_report_type(iter_info, type))
+                       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,
 
        if ((mask & FS_MODIFY) ||
            (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);
        }
 
        if (mnt && ((mask & FS_MODIFY) ||
                    (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);
-               iter_info.vfsmount_mark =
+               iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
                        fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
        }
 
index 22a3d0471feed3480210606ac8207b149c4d79a7..6a408ab3169dd31e5ce71bd86731caad97ee1428 100644 (file)
@@ -485,10 +485,10 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
                                    struct fsnotify_group *group)
 {
        struct inotify_inode_mark *i_mark;
-       struct fsnotify_iter_info iter_info = {
-               .inode_mark = fsn_mark,
-               .report_mask = FSNOTIFY_OBJ_TYPE_INODE_FL,
-       };
+       struct fsnotify_iter_info iter_info = { };
+
+       fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE,
+                                          fsn_mark);
 
        /* Queue ignore event for the watch */
        inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL,
index ef44808b28ca347233d482c0b778526bd2b9901e..61f4c5fa34c7c8129f1e76963b96422de72f4141 100644 (file)
@@ -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)
 {
-       /* This can fail if mark is being removed */
-       if (!fsnotify_get_mark_safe(iter_info->inode_mark))
-               return false;
-       if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) {
-               fsnotify_put_mark_wake(iter_info->inode_mark);
-               return false;
+       int type;
+
+       fsnotify_foreach_obj_type(type) {
+               /* This can fail if mark is being removed */
+               if (!fsnotify_get_mark_safe(iter_info->marks[type]))
+                       goto fail;
        }
 
        /*
@@ -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);
 
        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)
 {
+       int type;
+
        iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
-       fsnotify_put_mark_wake(iter_info->inode_mark);
-       fsnotify_put_mark_wake(iter_info->vfsmount_mark);
+       fsnotify_foreach_obj_type(type)
+               fsnotify_put_mark_wake(iter_info->marks[type]);
 }
 
 /*
index 9da5edf4ac0f5f893a493296e1b21caf4297bfe4..763423bfa3d6e8339a267ce539f1bd1fb80a17ba 100644 (file)
@@ -211,23 +211,45 @@ enum fsnotify_obj_type {
 #define FSNOTIFY_OBJ_ALL_TYPES_MASK    ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
 
 struct fsnotify_iter_info {
-       struct fsnotify_mark *inode_mark;
-       struct fsnotify_mark *vfsmount_mark;
+       struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT];
        unsigned int report_mask;
        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) \
 static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \
                struct fsnotify_iter_info *iter_info) \
 { \
        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(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
  * the inode / vfsmount. The reference to inode / vfsmount is held by this