aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLino Sanfilippo <LinoSanfilippo@gmx.de>2011-06-14 11:29:48 -0400
committerEric Paris <eparis@redhat.com>2012-12-11 13:29:45 -0500
commit104d06f08ea59247cb0e7e548c5a5d22d21dcfd5 (patch)
tree91f380d7fd26cbcab88635327c99524e9164d36f /fs
parent23e964c284ca0a767b80a30482bd53b059d30391 (diff)
fsnotify: take groups mark_lock before mark lock
Race-free addition and removal of a mark to a groups mark list would be easier if we could lock the mark list of group before we lock the specific mark. This patch changes the order used to add/remove marks to/from mark lists from 1. mark->lock 2. group->mark_lock 3. inode->i_lock to 1. group->mark_lock 2. mark->lock 3. inode->i_lock Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/notify/mark.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 3c7a1699df3d..32447dc06c07 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -127,20 +127,27 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
127 struct inode *inode = NULL; 127 struct inode *inode = NULL;
128 128
129 spin_lock(&mark->lock); 129 spin_lock(&mark->lock);
130 130 /* dont get the group from a mark that is not alive yet */
131 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
132 spin_unlock(&mark->lock);
133 return;
134 }
131 fsnotify_get_group(mark->group); 135 fsnotify_get_group(mark->group);
132 group = mark->group; 136 group = mark->group;
137 spin_unlock(&mark->lock);
138
139 spin_lock(&group->mark_lock);
140 spin_lock(&mark->lock);
133 141
134 /* something else already called this function on this mark */ 142 /* something else already called this function on this mark */
135 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { 143 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
136 spin_unlock(&mark->lock); 144 spin_unlock(&mark->lock);
145 spin_unlock(&group->mark_lock);
137 goto put_group; 146 goto put_group;
138 } 147 }
139 148
140 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; 149 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
141 150
142 spin_lock(&group->mark_lock);
143
144 if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { 151 if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
145 inode = mark->i.inode; 152 inode = mark->i.inode;
146 fsnotify_destroy_inode_mark(mark); 153 fsnotify_destroy_inode_mark(mark);
@@ -151,8 +158,8 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
151 158
152 list_del_init(&mark->g_list); 159 list_del_init(&mark->g_list);
153 160
154 spin_unlock(&group->mark_lock);
155 spin_unlock(&mark->lock); 161 spin_unlock(&mark->lock);
162 spin_unlock(&group->mark_lock);
156 163
157 spin_lock(&destroy_lock); 164 spin_lock(&destroy_lock);
158 list_add(&mark->destroy_list, &destroy_list); 165 list_add(&mark->destroy_list, &destroy_list);
@@ -225,13 +232,13 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
225 232
226 /* 233 /*
227 * LOCKING ORDER!!!! 234 * LOCKING ORDER!!!!
228 * mark->lock
229 * group->mark_lock 235 * group->mark_lock
236 * mark->lock
230 * inode->i_lock 237 * inode->i_lock
231 */ 238 */
232 spin_lock(&mark->lock);
233 spin_lock(&group->mark_lock); 239 spin_lock(&group->mark_lock);
234 240
241 spin_lock(&mark->lock);
235 mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE; 242 mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
236 243
237 fsnotify_get_group(group); 244 fsnotify_get_group(group);
@@ -252,13 +259,12 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
252 BUG(); 259 BUG();
253 } 260 }
254 261
255 spin_unlock(&group->mark_lock);
256
257 /* this will pin the object if appropriate */ 262 /* this will pin the object if appropriate */
258 fsnotify_set_mark_mask_locked(mark, mark->mask); 263 fsnotify_set_mark_mask_locked(mark, mark->mask);
259
260 spin_unlock(&mark->lock); 264 spin_unlock(&mark->lock);
261 265
266 spin_unlock(&group->mark_lock);
267
262 if (inode) 268 if (inode)
263 __fsnotify_update_child_dentry_flags(inode); 269 __fsnotify_update_child_dentry_flags(inode);
264 270
@@ -270,8 +276,8 @@ err:
270 mark->group = NULL; 276 mark->group = NULL;
271 atomic_dec(&group->num_marks); 277 atomic_dec(&group->num_marks);
272 278
273 spin_unlock(&group->mark_lock);
274 spin_unlock(&mark->lock); 279 spin_unlock(&mark->lock);
280 spin_unlock(&group->mark_lock);
275 281
276 spin_lock(&destroy_lock); 282 spin_lock(&destroy_lock);
277 list_add(&mark->destroy_list, &destroy_list); 283 list_add(&mark->destroy_list, &destroy_list);