summaryrefslogtreecommitdiffstats
path: root/fs/notify
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2017-03-15 04:16:27 -0400
committerJan Kara <jack@suse.cz>2017-04-10 11:37:35 -0400
commita242677bb1e6faa9bd82bd33afb2621071258231 (patch)
tree853a675a0c61c182b834b1ced7d7e745c1eb3133 /fs/notify
parent0810b4f9f207910d90aee56d312d25f334796363 (diff)
fsnotify: Move locking into fsnotify_recalc_mask()
Move locking of locks protecting a list of marks into fsnotify_recalc_mask(). This reduces code churn in the following patch which changes the lock protecting the list of marks. Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/dnotify/dnotify.c3
-rw-r--r--fs/notify/fsnotify.h3
-rw-r--r--fs/notify/inode_mark.c18
-rw-r--r--fs/notify/mark.c40
-rw-r--r--fs/notify/vfsmount_mark.c13
5 files changed, 37 insertions, 40 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 5024729dba23..41b2a070761c 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -69,8 +69,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
69 if (old_mask == new_mask) 69 if (old_mask == new_mask)
70 return; 70 return;
71 71
72 if (fsn_mark->connector) 72 fsnotify_recalc_mask(fsn_mark->connector);
73 fsnotify_recalc_inode_mask(fsn_mark->connector->inode);
74} 73}
75 74
76/* 75/*
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
index 0354338aad78..96051780d50e 100644
--- a/fs/notify/fsnotify.h
+++ b/fs/notify/fsnotify.h
@@ -14,9 +14,6 @@ extern void fsnotify_flush_notify(struct fsnotify_group *group);
14/* protects reads of inode and vfsmount marks list */ 14/* protects reads of inode and vfsmount marks list */
15extern struct srcu_struct fsnotify_mark_srcu; 15extern struct srcu_struct fsnotify_mark_srcu;
16 16
17/* Calculate mask of events for a list of marks */
18extern u32 fsnotify_recalc_mask(struct fsnotify_mark_connector *conn);
19
20/* compare two groups for sorting of marks lists */ 17/* compare two groups for sorting of marks lists */
21extern int fsnotify_compare_groups(struct fsnotify_group *a, 18extern int fsnotify_compare_groups(struct fsnotify_group *a,
22 struct fsnotify_group *b); 19 struct fsnotify_group *b);
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index 87bef7d802db..9b2f4e6eb8eb 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -30,17 +30,9 @@
30 30
31#include "../internal.h" 31#include "../internal.h"
32 32
33/*
34 * Recalculate the inode->i_fsnotify_mask, or the mask of all FS_* event types
35 * any notifier is interested in hearing for this inode.
36 */
37void fsnotify_recalc_inode_mask(struct inode *inode) 33void fsnotify_recalc_inode_mask(struct inode *inode)
38{ 34{
39 spin_lock(&inode->i_lock); 35 fsnotify_recalc_mask(inode->i_fsnotify_marks);
40 inode->i_fsnotify_mask = fsnotify_recalc_mask(inode->i_fsnotify_marks);
41 spin_unlock(&inode->i_lock);
42
43 __fsnotify_update_child_dentry_flags(inode);
44} 36}
45 37
46struct inode *fsnotify_destroy_inode_mark(struct fsnotify_mark *mark) 38struct inode *fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
@@ -57,14 +49,10 @@ struct inode *fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
57 empty = hlist_empty(&mark->connector->list); 49 empty = hlist_empty(&mark->connector->list);
58 mark->connector = NULL; 50 mark->connector = NULL;
59 51
60 /*
61 * this mark is now off the inode->i_fsnotify_marks list and we
62 * hold the inode->i_lock, so this is the perfect time to update the
63 * inode->i_fsnotify_mask
64 */
65 inode->i_fsnotify_mask = fsnotify_recalc_mask(inode->i_fsnotify_marks);
66 spin_unlock(&inode->i_lock); 52 spin_unlock(&inode->i_lock);
67 53
54 fsnotify_recalc_mask(inode->i_fsnotify_marks);
55
68 return empty ? inode : NULL; 56 return empty ? inode : NULL;
69} 57}
70 58
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index b3f83ed6e8be..06faf166c7ae 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -105,18 +105,40 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
105 } 105 }
106} 106}
107 107
108/* Calculate mask of events for a list of marks */ 108static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
109u32 fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
110{ 109{
111 u32 new_mask = 0; 110 u32 new_mask = 0;
112 struct fsnotify_mark *mark; 111 struct fsnotify_mark *mark;
113 112
114 if (!conn)
115 return 0;
116
117 hlist_for_each_entry(mark, &conn->list, obj_list) 113 hlist_for_each_entry(mark, &conn->list, obj_list)
118 new_mask |= mark->mask; 114 new_mask |= mark->mask;
119 return new_mask; 115 if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
116 conn->inode->i_fsnotify_mask = new_mask;
117 else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT)
118 real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
119}
120
121/*
122 * Calculate mask of events for a list of marks. The caller must make sure
123 * connector cannot disappear under us (usually by holding a mark->lock or
124 * mark->group->mark_mutex for a mark on this list).
125 */
126void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
127{
128 if (!conn)
129 return;
130
131 if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
132 spin_lock(&conn->inode->i_lock);
133 else
134 spin_lock(&conn->mnt->mnt_root->d_lock);
135 __fsnotify_recalc_mask(conn);
136 if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) {
137 spin_unlock(&conn->inode->i_lock);
138 __fsnotify_update_child_dentry_flags(conn->inode);
139 } else {
140 spin_unlock(&conn->mnt->mnt_root->d_lock);
141 }
120} 142}
121 143
122/* 144/*
@@ -423,10 +445,8 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
423 if (ret) 445 if (ret)
424 goto err; 446 goto err;
425 447
426 if (inode) 448 if (mark->mask)
427 fsnotify_recalc_inode_mask(inode); 449 fsnotify_recalc_mask(mark->connector);
428 else
429 fsnotify_recalc_vfsmount_mask(mnt);
430 450
431 return ret; 451 return ret;
432err: 452err:
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c
index 49ccbdb74f82..ffe0d7098cba 100644
--- a/fs/notify/vfsmount_mark.c
+++ b/fs/notify/vfsmount_mark.c
@@ -34,17 +34,9 @@ void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group)
34 fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT); 34 fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT);
35} 35}
36 36
37/*
38 * Recalculate the mnt->mnt_fsnotify_mask, or the mask of all FS_* event types
39 * any notifier is interested in hearing for this mount point
40 */
41void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt) 37void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt)
42{ 38{
43 struct mount *m = real_mount(mnt); 39 fsnotify_recalc_mask(real_mount(mnt)->mnt_fsnotify_marks);
44
45 spin_lock(&mnt->mnt_root->d_lock);
46 m->mnt_fsnotify_mask = fsnotify_recalc_mask(m->mnt_fsnotify_marks);
47 spin_unlock(&mnt->mnt_root->d_lock);
48} 40}
49 41
50void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark) 42void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
@@ -60,8 +52,9 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
60 hlist_del_init_rcu(&mark->obj_list); 52 hlist_del_init_rcu(&mark->obj_list);
61 mark->connector = NULL; 53 mark->connector = NULL;
62 54
63 m->mnt_fsnotify_mask = fsnotify_recalc_mask(m->mnt_fsnotify_marks);
64 spin_unlock(&mnt->mnt_root->d_lock); 55 spin_unlock(&mnt->mnt_root->d_lock);
56
57 fsnotify_recalc_mask(m->mnt_fsnotify_marks);
65} 58}
66 59
67/* 60/*