summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fdinfo.c5
-rw-r--r--fs/notify/fsnotify.c8
-rw-r--r--fs/notify/fsnotify.h11
-rw-r--r--fs/notify/mark.c4
-rw-r--r--fs/super.c2
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/fsnotify_backend.h17
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)
131 131
132 seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", 132 seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",
133 mnt->mnt_id, mflags, mark->mask, mark->ignored_mask); 133 mnt->mnt_id, mflags, mark->mask, mark->ignored_mask);
134 } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_SB) {
135 struct super_block *sb = fsnotify_conn_sb(mark->connector);
136
137 seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n",
138 sb->s_dev, mflags, mark->mask, mark->ignored_mask);
134 } 139 }
135} 140}
136 141
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index ababdbfab537..2971803d151c 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -48,7 +48,7 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
48 * Called during unmount with no locks held, so needs to be safe against 48 * Called during unmount with no locks held, so needs to be safe against
49 * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block. 49 * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block.
50 */ 50 */
51void fsnotify_unmount_inodes(struct super_block *sb) 51static void fsnotify_unmount_inodes(struct super_block *sb)
52{ 52{
53 struct inode *inode, *iput_inode = NULL; 53 struct inode *inode, *iput_inode = NULL;
54 54
@@ -98,6 +98,12 @@ void fsnotify_unmount_inodes(struct super_block *sb)
98 iput(iput_inode); 98 iput(iput_inode);
99} 99}
100 100
101void fsnotify_sb_delete(struct super_block *sb)
102{
103 fsnotify_unmount_inodes(sb);
104 fsnotify_clear_marks_by_sb(sb);
105}
106
101/* 107/*
102 * Given an inode, first check if we care what happens to our children. Inotify 108 * Given an inode, first check if we care what happens to our children. Inotify
103 * and dnotify both tell their parents about events. If we care about any event 109 * 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(
21 return container_of(conn->obj, struct mount, mnt_fsnotify_marks); 21 return container_of(conn->obj, struct mount, mnt_fsnotify_marks);
22} 22}
23 23
24static inline struct super_block *fsnotify_conn_sb(
25 struct fsnotify_mark_connector *conn)
26{
27 return container_of(conn->obj, struct super_block, s_fsnotify_marks);
28}
29
24/* destroy all events sitting in this groups notification queue */ 30/* destroy all events sitting in this groups notification queue */
25extern void fsnotify_flush_notify(struct fsnotify_group *group); 31extern void fsnotify_flush_notify(struct fsnotify_group *group);
26 32
@@ -43,6 +49,11 @@ static inline void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
43{ 49{
44 fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify_marks); 50 fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify_marks);
45} 51}
52/* run the list of all marks associated with sb and destroy them */
53static inline void fsnotify_clear_marks_by_sb(struct super_block *sb)
54{
55 fsnotify_destroy_marks(&sb->s_fsnotify_marks);
56}
46/* Wait until all marks queued for destruction are destroyed */ 57/* Wait until all marks queued for destruction are destroyed */
47extern void fsnotify_wait_marks_destroyed(void); 58extern void fsnotify_wait_marks_destroyed(void);
48 59
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)
115 return &fsnotify_conn_inode(conn)->i_fsnotify_mask; 115 return &fsnotify_conn_inode(conn)->i_fsnotify_mask;
116 else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) 116 else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT)
117 return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask; 117 return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask;
118 else if (conn->type == FSNOTIFY_OBJ_TYPE_SB)
119 return &fsnotify_conn_sb(conn)->s_fsnotify_mask;
118 return NULL; 120 return NULL;
119} 121}
120 122
@@ -192,6 +194,8 @@ static struct inode *fsnotify_detach_connector_from_object(
192 inode->i_fsnotify_mask = 0; 194 inode->i_fsnotify_mask = 0;
193 } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { 195 } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
194 fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; 196 fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0;
197 } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) {
198 fsnotify_conn_sb(conn)->s_fsnotify_mask = 0;
195 } 199 }
196 200
197 rcu_assign_pointer(*(conn->obj), NULL); 201 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)
442 sync_filesystem(sb); 442 sync_filesystem(sb);
443 sb->s_flags &= ~SB_ACTIVE; 443 sb->s_flags &= ~SB_ACTIVE;
444 444
445 fsnotify_unmount_inodes(sb); 445 fsnotify_sb_delete(sb);
446 cgroup_writeback_umount(); 446 cgroup_writeback_umount();
447 447
448 evict_inodes(sb); 448 evict_inodes(sb);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 33322702c910..2c14801d0aa3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1464,6 +1464,11 @@ struct super_block {
1464 1464
1465 spinlock_t s_inode_wblist_lock; 1465 spinlock_t s_inode_wblist_lock;
1466 struct list_head s_inodes_wb; /* writeback inodes */ 1466 struct list_head s_inodes_wb; /* writeback inodes */
1467
1468#ifdef CONFIG_FSNOTIFY
1469 __u32 s_fsnotify_mask;
1470 struct fsnotify_mark_connector __rcu *s_fsnotify_marks;
1471#endif
1467} __randomize_layout; 1472} __randomize_layout;
1468 1473
1469/* Helper functions so that in most cases filesystems will 1474/* 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 {
206enum fsnotify_obj_type { 206enum fsnotify_obj_type {
207 FSNOTIFY_OBJ_TYPE_INODE, 207 FSNOTIFY_OBJ_TYPE_INODE,
208 FSNOTIFY_OBJ_TYPE_VFSMOUNT, 208 FSNOTIFY_OBJ_TYPE_VFSMOUNT,
209 FSNOTIFY_OBJ_TYPE_SB,
209 FSNOTIFY_OBJ_TYPE_COUNT, 210 FSNOTIFY_OBJ_TYPE_COUNT,
210 FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT 211 FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT
211}; 212};
212 213
213#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) 214#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE)
214#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) 215#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT)
216#define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB)
215#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) 217#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
216 218
217static inline bool fsnotify_valid_obj_type(unsigned int type) 219static inline bool fsnotify_valid_obj_type(unsigned int type)
@@ -255,6 +257,7 @@ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \
255 257
256FSNOTIFY_ITER_FUNCS(inode, INODE) 258FSNOTIFY_ITER_FUNCS(inode, INODE)
257FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) 259FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT)
260FSNOTIFY_ITER_FUNCS(sb, SB)
258 261
259#define fsnotify_foreach_obj_type(type) \ 262#define fsnotify_foreach_obj_type(type) \
260 for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) 263 for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++)
@@ -267,8 +270,8 @@ struct fsnotify_mark_connector;
267typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; 270typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
268 271
269/* 272/*
270 * Inode / vfsmount point to this structure which tracks all marks attached to 273 * Inode/vfsmount/sb point to this structure which tracks all marks attached to
271 * the inode / vfsmount. The reference to inode / vfsmount is held by this 274 * the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this
272 * structure. We destroy this structure when there are no more marks attached 275 * structure. We destroy this structure when there are no more marks attached
273 * to it. The structure is protected by fsnotify_mark_srcu. 276 * to it. The structure is protected by fsnotify_mark_srcu.
274 */ 277 */
@@ -335,6 +338,7 @@ extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int dat
335extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask); 338extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask);
336extern void __fsnotify_inode_delete(struct inode *inode); 339extern void __fsnotify_inode_delete(struct inode *inode);
337extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); 340extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
341extern void fsnotify_sb_delete(struct super_block *sb);
338extern u32 fsnotify_get_cookie(void); 342extern u32 fsnotify_get_cookie(void);
339 343
340static inline int fsnotify_inode_watches_children(struct inode *inode) 344static 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
455{ 459{
456 fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL); 460 fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL);
457} 461}
462/* run all the marks in a group, and clear all of the sn marks */
463static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group)
464{
465 fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_SB_FL);
466}
458extern void fsnotify_get_mark(struct fsnotify_mark *mark); 467extern void fsnotify_get_mark(struct fsnotify_mark *mark);
459extern void fsnotify_put_mark(struct fsnotify_mark *mark); 468extern void fsnotify_put_mark(struct fsnotify_mark *mark);
460extern void fsnotify_unmount_inodes(struct super_block *sb);
461extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); 469extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
462extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); 470extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);
463 471
@@ -484,6 +492,9 @@ static inline void __fsnotify_inode_delete(struct inode *inode)
484static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) 492static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
485{} 493{}
486 494
495static inline void fsnotify_sb_delete(struct super_block *sb)
496{}
497
487static inline void fsnotify_update_flags(struct dentry *dentry) 498static inline void fsnotify_update_flags(struct dentry *dentry)
488{} 499{}
489 500