diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-03-22 08:53:19 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-05-21 18:31:14 -0400 |
commit | b20bd1a5e78af267dc4b6e1ffed48d5d776302c5 (patch) | |
tree | d50982ee42500712d9add489435d4455580b9cac /fs/notify | |
parent | 389b8be6ef419397e4f176652927ebad6ebb4b77 (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')
-rw-r--r-- | fs/notify/inotify/inotify.c | 32 |
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); | |||
110 | int pin_inotify_watch(struct inotify_watch *watch) | 110 | int 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 */ |