aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/inotify/inotify.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-03-22 08:53:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-05-21 18:31:14 -0400
commitb20bd1a5e78af267dc4b6e1ffed48d5d776302c5 (patch)
treed50982ee42500712d9add489435d4455580b9cac /fs/notify/inotify/inotify.c
parent389b8be6ef419397e4f176652927ebad6ebb4b77 (diff)
get rid of S_BIAS
use atomic_inc_not_zero(&sb->s_active) instead of playing games with checking ->s_count > S_BIAS Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/notify/inotify/inotify.c')
-rw-r--r--fs/notify/inotify/inotify.c32
1 files changed, 13 insertions, 19 deletions
diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c
index 40b1cf914ccb..441ef136af22 100644
--- a/fs/notify/inotify/inotify.c
+++ b/fs/notify/inotify/inotify.c
@@ -110,14 +110,10 @@ EXPORT_SYMBOL_GPL(get_inotify_watch);
110int pin_inotify_watch(struct inotify_watch *watch) 110int pin_inotify_watch(struct inotify_watch *watch)
111{ 111{
112 struct super_block *sb = watch->inode->i_sb; 112 struct super_block *sb = watch->inode->i_sb;
113 spin_lock(&sb_lock); 113 if (atomic_inc_not_zero(&sb->s_active)) {
114 if (sb->s_count >= S_BIAS) {
115 atomic_inc(&sb->s_active);
116 spin_unlock(&sb_lock);
117 atomic_inc(&watch->count); 114 atomic_inc(&watch->count);
118 return 1; 115 return 1;
119 } 116 }
120 spin_unlock(&sb_lock);
121 return 0; 117 return 0;
122} 118}
123 119
@@ -518,16 +514,16 @@ EXPORT_SYMBOL_GPL(inotify_init_watch);
518 * ->s_umount, which will almost certainly wait until the superblock is shut 514 * ->s_umount, which will almost certainly wait until the superblock is shut
519 * down and the watch in question is pining for fjords. That's fine, but 515 * down and the watch in question is pining for fjords. That's fine, but
520 * there is a problem - we might have hit the window between ->s_active 516 * there is a problem - we might have hit the window between ->s_active
521 * getting to 0 / ->s_count - below S_BIAS (i.e. the moment when superblock 517 * getting to 0 (i.e. the moment when superblock is past the point of no return
522 * is past the point of no return and is heading for shutdown) and the 518 * and is heading for shutdown) and the moment when deactivate_super() acquires
523 * moment when deactivate_super() acquires ->s_umount. We could just do 519 * ->s_umount. We could just do drop_super() yield() and retry, but that's
524 * drop_super() yield() and retry, but that's rather antisocial and this 520 * rather antisocial and this stuff is luser-triggerable. OTOH, having grabbed
525 * stuff is luser-triggerable. OTOH, having grabbed ->s_umount and having 521 * ->s_umount and having found that we'd got there first (i.e. that ->s_root is
526 * found that we'd got there first (i.e. that ->s_root is non-NULL) we know 522 * non-NULL) we know that we won't race with inotify_umount_inodes(). So we
527 * that we won't race with inotify_umount_inodes(). So we could grab a 523 * could grab a reference to watch and do the rest as above, just with
528 * reference to watch and do the rest as above, just with drop_super() instead 524 * drop_super() instead of deactivate_super(), right? Wrong. We had to drop
529 * of deactivate_super(), right? Wrong. We had to drop ih->mutex before we 525 * ih->mutex before we could grab ->s_umount. So the watch could've been gone
530 * could grab ->s_umount. So the watch could've been gone already. 526 * already.
531 * 527 *
532 * That still can be dealt with - we need to save watch->wd, do idr_find() 528 * That still can be dealt with - we need to save watch->wd, do idr_find()
533 * and compare its result with our pointer. If they match, we either have 529 * and compare its result with our pointer. If they match, we either have
@@ -565,14 +561,12 @@ static int pin_to_kill(struct inotify_handle *ih, struct inotify_watch *watch)
565 struct super_block *sb = watch->inode->i_sb; 561 struct super_block *sb = watch->inode->i_sb;
566 s32 wd = watch->wd; 562 s32 wd = watch->wd;
567 563
568 spin_lock(&sb_lock); 564 if (atomic_inc_not_zero(&sb->s_active)) {
569 if (sb->s_count >= S_BIAS) {
570 atomic_inc(&sb->s_active);
571 spin_unlock(&sb_lock);
572 get_inotify_watch(watch); 565 get_inotify_watch(watch);
573 mutex_unlock(&ih->mutex); 566 mutex_unlock(&ih->mutex);
574 return 1; /* the best outcome */ 567 return 1; /* the best outcome */
575 } 568 }
569 spin_lock(&sb_lock);
576 sb->s_count++; 570 sb->s_count++;
577 spin_unlock(&sb_lock); 571 spin_unlock(&sb_lock);
578 mutex_unlock(&ih->mutex); /* can't grab ->s_umount under it */ 572 mutex_unlock(&ih->mutex); /* can't grab ->s_umount under it */