On Thu 30-08-18 18:15:49, Amir Goldstein wrote: > Add the infrastructure to attach a mark to a super_block struct > and detach all attached marks when super block is destroyed. > > This is going to be used by fanotify backend to setup super block > marks. > > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> This patch looks OK to me. Honza > --- > fs/notify/fdinfo.c | 5 +++++ > fs/notify/fsnotify.c | 8 +++++++- > fs/notify/fsnotify.h | 11 +++++++++++ > fs/notify/mark.c | 4 ++++ > fs/super.c | 2 +- > include/linux/fs.h | 5 +++++ > include/linux/fsnotify_backend.h | 17 ++++++++++++++--- > 7 files changed, 47 insertions(+), 5 deletions(-) > > diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c > index 86fcf5814279..25385e336ac7 100644 > --- a/fs/notify/fdinfo.c > +++ b/fs/notify/fdinfo.c > @@ -131,6 +131,11 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) > > seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", > mnt->mnt_id, mflags, mark->mask, mark->ignored_mask); > + } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_SB) { > + struct super_block *sb = fsnotify_conn_sb(mark->connector); > + > + seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n", > + sb->s_dev, mflags, mark->mask, mark->ignored_mask); > } > } > > diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c > index f174397b63a0..775e731d3016 100644 > --- a/fs/notify/fsnotify.c > +++ b/fs/notify/fsnotify.c > @@ -48,7 +48,7 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt) > * Called during unmount with no locks held, so needs to be safe against > * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block. > */ > -void fsnotify_unmount_inodes(struct super_block *sb) > +static void fsnotify_unmount_inodes(struct super_block *sb) > { > struct inode *inode, *iput_inode = NULL; > > @@ -98,6 +98,12 @@ void fsnotify_unmount_inodes(struct super_block *sb) > iput(iput_inode); > } > > +void fsnotify_sb_delete(struct super_block *sb) > +{ > + fsnotify_unmount_inodes(sb); > + fsnotify_clear_marks_by_sb(sb); > +} > + > /* > * Given an inode, first check if we care what happens to our children. Inotify > * and dnotify both tell their parents about events. If we care about any event > diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h > index 7902653dd577..5a00121fb219 100644 > --- a/fs/notify/fsnotify.h > +++ b/fs/notify/fsnotify.h > @@ -21,6 +21,12 @@ static inline struct mount *fsnotify_conn_mount( > return container_of(conn->obj, struct mount, mnt_fsnotify_marks); > } > > +static inline struct super_block *fsnotify_conn_sb( > + struct fsnotify_mark_connector *conn) > +{ > + return container_of(conn->obj, struct super_block, s_fsnotify_marks); > +} > + > /* destroy all events sitting in this groups notification queue */ > extern void fsnotify_flush_notify(struct fsnotify_group *group); > > @@ -43,6 +49,11 @@ static inline void fsnotify_clear_marks_by_mount(struct vfsmount *mnt) > { > fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify_marks); > } > +/* run the list of all marks associated with sb and destroy them */ > +static inline void fsnotify_clear_marks_by_sb(struct super_block *sb) > +{ > + fsnotify_destroy_marks(&sb->s_fsnotify_marks); > +} > /* Wait until all marks queued for destruction are destroyed */ > extern void fsnotify_wait_marks_destroyed(void); > > diff --git a/fs/notify/mark.c b/fs/notify/mark.c > index 59cdb27826de..b5172ccb2e60 100644 > --- a/fs/notify/mark.c > +++ b/fs/notify/mark.c > @@ -115,6 +115,8 @@ static __u32 *fsnotify_conn_mask_p(struct fsnotify_mark_connector *conn) > return &fsnotify_conn_inode(conn)->i_fsnotify_mask; > else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) > return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask; > + else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) > + return &fsnotify_conn_sb(conn)->s_fsnotify_mask; > return NULL; > } > > @@ -192,6 +194,8 @@ static struct inode *fsnotify_detach_connector_from_object( > inode->i_fsnotify_mask = 0; > } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { > fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; > + } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) { > + fsnotify_conn_sb(conn)->s_fsnotify_mask = 0; > } > > rcu_assign_pointer(*(conn->obj), NULL); > diff --git a/fs/super.c b/fs/super.c > index f3a8c008e164..ca53a08497ed 100644 > --- a/fs/super.c > +++ b/fs/super.c > @@ -442,7 +442,7 @@ void generic_shutdown_super(struct super_block *sb) > sync_filesystem(sb); > sb->s_flags &= ~SB_ACTIVE; > > - fsnotify_unmount_inodes(sb); > + fsnotify_sb_delete(sb); > cgroup_writeback_umount(); > > evict_inodes(sb); > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 6c0b4a1c22ff..4f0a11d0d296 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -1464,6 +1464,11 @@ struct super_block { > > spinlock_t s_inode_wblist_lock; > struct list_head s_inodes_wb; /* writeback inodes */ > + > +#ifdef CONFIG_FSNOTIFY > + __u32 s_fsnotify_mask; > + struct fsnotify_mark_connector __rcu *s_fsnotify_marks; > +#endif > } __randomize_layout; > > /* Helper functions so that in most cases filesystems will > diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h > index b8f4182f42f1..81b88fc9df31 100644 > --- a/include/linux/fsnotify_backend.h > +++ b/include/linux/fsnotify_backend.h > @@ -206,12 +206,14 @@ struct fsnotify_group { > enum fsnotify_obj_type { > FSNOTIFY_OBJ_TYPE_INODE, > FSNOTIFY_OBJ_TYPE_VFSMOUNT, > + FSNOTIFY_OBJ_TYPE_SB, > FSNOTIFY_OBJ_TYPE_COUNT, > FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT > }; > > #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) > #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) > +#define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) > #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) > > static inline bool fsnotify_valid_obj_type(unsigned int type) > @@ -255,6 +257,7 @@ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ > > FSNOTIFY_ITER_FUNCS(inode, INODE) > FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) > +FSNOTIFY_ITER_FUNCS(sb, SB) > > #define fsnotify_foreach_obj_type(type) \ > for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) > @@ -267,8 +270,8 @@ struct fsnotify_mark_connector; > typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; > > /* > - * Inode / vfsmount point to this structure which tracks all marks attached to > - * the inode / vfsmount. The reference to inode / vfsmount is held by this > + * Inode/vfsmount/sb point to this structure which tracks all marks attached to > + * the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this > * structure. We destroy this structure when there are no more marks attached > * to it. The structure is protected by fsnotify_mark_srcu. > */ > @@ -335,6 +338,7 @@ extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int dat > extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask); > extern void __fsnotify_inode_delete(struct inode *inode); > extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); > +extern void fsnotify_sb_delete(struct super_block *sb); > extern u32 fsnotify_get_cookie(void); > > static inline int fsnotify_inode_watches_children(struct inode *inode) > @@ -455,9 +459,13 @@ static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *gr > { > fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL); > } > +/* run all the marks in a group, and clear all of the sn marks */ > +static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group) > +{ > + fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_SB_FL); > +} > extern void fsnotify_get_mark(struct fsnotify_mark *mark); > extern void fsnotify_put_mark(struct fsnotify_mark *mark); > -extern void fsnotify_unmount_inodes(struct super_block *sb); > extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); > extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); > > @@ -484,6 +492,9 @@ static inline void __fsnotify_inode_delete(struct inode *inode) > static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) > {} > > +static inline void fsnotify_sb_delete(struct super_block *sb) > +{} > + > static inline void fsnotify_update_flags(struct dentry *dentry) > {} > > -- > 2.7.4 > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR