aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify
diff options
context:
space:
mode:
authorLino Sanfilippo <LinoSanfilippo@gmx.de>2013-07-08 18:59:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 13:33:20 -0400
commit52f85729805b7a0ec5a7a70e2c814193929de2f0 (patch)
treecea36db4bfc807c0dfa357da02f5bb899df863a1 /fs/notify
parent5e9c070ca085439fbec9e9629dd6171ae325d4d8 (diff)
dnotify: replace dnotify_mark_mutex with mark mutex of dnotify_group
There is no need to use a special mutex to protect against the fcntl/close race (see dnotify.c for a description of this race). Instead the dnotify_groups mark mutex can be used. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Cc: Eric Paris <eparis@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/dnotify/dnotify.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 2bfe6dc413a0..1fedd5f7ccc4 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -31,7 +31,6 @@ int dir_notify_enable __read_mostly = 1;
31static struct kmem_cache *dnotify_struct_cache __read_mostly; 31static struct kmem_cache *dnotify_struct_cache __read_mostly;
32static struct kmem_cache *dnotify_mark_cache __read_mostly; 32static struct kmem_cache *dnotify_mark_cache __read_mostly;
33static struct fsnotify_group *dnotify_group __read_mostly; 33static struct fsnotify_group *dnotify_group __read_mostly;
34static DEFINE_MUTEX(dnotify_mark_mutex);
35 34
36/* 35/*
37 * dnotify will attach one of these to each inode (i_fsnotify_marks) which 36 * dnotify will attach one of these to each inode (i_fsnotify_marks) which
@@ -183,7 +182,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
183 return; 182 return;
184 dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); 183 dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
185 184
186 mutex_lock(&dnotify_mark_mutex); 185 mutex_lock(&dnotify_group->mark_mutex);
187 186
188 spin_lock(&fsn_mark->lock); 187 spin_lock(&fsn_mark->lock);
189 prev = &dn_mark->dn; 188 prev = &dn_mark->dn;
@@ -199,11 +198,12 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
199 198
200 spin_unlock(&fsn_mark->lock); 199 spin_unlock(&fsn_mark->lock);
201 200
202 /* nothing else could have found us thanks to the dnotify_mark_mutex */ 201 /* nothing else could have found us thanks to the dnotify_groups
202 mark_mutex */
203 if (dn_mark->dn == NULL) 203 if (dn_mark->dn == NULL)
204 fsnotify_destroy_mark(fsn_mark, dnotify_group); 204 fsnotify_destroy_mark_locked(fsn_mark, dnotify_group);
205 205
206 mutex_unlock(&dnotify_mark_mutex); 206 mutex_unlock(&dnotify_group->mark_mutex);
207 207
208 fsnotify_put_mark(fsn_mark); 208 fsnotify_put_mark(fsn_mark);
209} 209}
@@ -326,7 +326,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
326 new_dn_mark->dn = NULL; 326 new_dn_mark->dn = NULL;
327 327
328 /* this is needed to prevent the fcntl/close race described below */ 328 /* this is needed to prevent the fcntl/close race described below */
329 mutex_lock(&dnotify_mark_mutex); 329 mutex_lock(&dnotify_group->mark_mutex);
330 330
331 /* add the new_fsn_mark or find an old one. */ 331 /* add the new_fsn_mark or find an old one. */
332 fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode); 332 fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode);
@@ -334,7 +334,8 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
334 dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); 334 dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
335 spin_lock(&fsn_mark->lock); 335 spin_lock(&fsn_mark->lock);
336 } else { 336 } else {
337 fsnotify_add_mark(new_fsn_mark, dnotify_group, inode, NULL, 0); 337 fsnotify_add_mark_locked(new_fsn_mark, dnotify_group, inode,
338 NULL, 0);
338 spin_lock(&new_fsn_mark->lock); 339 spin_lock(&new_fsn_mark->lock);
339 fsn_mark = new_fsn_mark; 340 fsn_mark = new_fsn_mark;
340 dn_mark = new_dn_mark; 341 dn_mark = new_dn_mark;
@@ -348,9 +349,9 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
348 349
349 /* if (f != filp) means that we lost a race and another task/thread 350 /* if (f != filp) means that we lost a race and another task/thread
350 * actually closed the fd we are still playing with before we grabbed 351 * actually closed the fd we are still playing with before we grabbed
351 * the dnotify_mark_mutex and fsn_mark->lock. Since closing the fd is the 352 * the dnotify_groups mark_mutex and fsn_mark->lock. Since closing the
352 * only time we clean up the marks we need to get our mark off 353 * fd is the only time we clean up the marks we need to get our mark
353 * the list. */ 354 * off the list. */
354 if (f != filp) { 355 if (f != filp) {
355 /* if we added ourselves, shoot ourselves, it's possible that 356 /* if we added ourselves, shoot ourselves, it's possible that
356 * the flush actually did shoot this fsn_mark. That's fine too 357 * the flush actually did shoot this fsn_mark. That's fine too
@@ -385,9 +386,9 @@ out:
385 spin_unlock(&fsn_mark->lock); 386 spin_unlock(&fsn_mark->lock);
386 387
387 if (destroy) 388 if (destroy)
388 fsnotify_destroy_mark(fsn_mark, dnotify_group); 389 fsnotify_destroy_mark_locked(fsn_mark, dnotify_group);
389 390
390 mutex_unlock(&dnotify_mark_mutex); 391 mutex_unlock(&dnotify_group->mark_mutex);
391 fsnotify_put_mark(fsn_mark); 392 fsnotify_put_mark(fsn_mark);
392out_err: 393out_err:
393 if (new_fsn_mark) 394 if (new_fsn_mark)