mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Saner locking around deactivate_super()
Make sure that s_umount is acquired *before* we drop the final active reference; we still have the fast path (atomic_dec_unless) and we have gotten rid of the window between the moment when s_active hits zero and s_umount is acquired. Which simplifies the living hell out of grab_super() and inotify pin_to_kill() stuff. Signed-off-by: Al Viro <[email protected]>
This commit is contained in:
parent
b20bd1a5e7
commit
1712ac8fda
2 changed files with 30 additions and 91 deletions
57
fs/super.c
57
fs/super.c
|
|
@ -177,39 +177,16 @@ void put_super(struct super_block *sb)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* deactivate_super - drop an active reference to superblock
|
||||
* @s: superblock to deactivate
|
||||
*
|
||||
* Drops an active reference to superblock, acquiring a temprory one if
|
||||
* there is no active references left. In that case we lock superblock,
|
||||
* tell fs driver to shut it down and drop the temporary reference we
|
||||
* had just acquired.
|
||||
*/
|
||||
void deactivate_super(struct super_block *s)
|
||||
{
|
||||
struct file_system_type *fs = s->s_type;
|
||||
if (atomic_dec_and_test(&s->s_active)) {
|
||||
vfs_dq_off(s, 0);
|
||||
down_write(&s->s_umount);
|
||||
fs->kill_sb(s);
|
||||
put_filesystem(fs);
|
||||
put_super(s);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(deactivate_super);
|
||||
|
||||
/**
|
||||
* deactivate_locked_super - drop an active reference to superblock
|
||||
* @s: superblock to deactivate
|
||||
*
|
||||
* Equivalent of up_write(&s->s_umount); deactivate_super(s);, except that
|
||||
* it does not unlock it until it's all over. As the result, it's safe to
|
||||
* use to dispose of new superblock on ->get_sb() failure exits - nobody
|
||||
* will see the sucker until it's all over. Equivalent using up_write +
|
||||
* deactivate_super is safe for that purpose only if superblock is either
|
||||
* safe to use or has NULL ->s_root when we unlock.
|
||||
* Drops an active reference to superblock, converting it into a temprory
|
||||
* one if there is no other active references left. In that case we
|
||||
* tell fs driver to shut it down and drop the temporary reference we
|
||||
* had just acquired.
|
||||
*
|
||||
* Caller holds exclusive lock on superblock; that lock is released.
|
||||
*/
|
||||
void deactivate_locked_super(struct super_block *s)
|
||||
{
|
||||
|
|
@ -226,6 +203,24 @@ void deactivate_locked_super(struct super_block *s)
|
|||
|
||||
EXPORT_SYMBOL(deactivate_locked_super);
|
||||
|
||||
/**
|
||||
* deactivate_super - drop an active reference to superblock
|
||||
* @s: superblock to deactivate
|
||||
*
|
||||
* Variant of deactivate_locked_super(), except that superblock is *not*
|
||||
* locked by caller. If we are going to drop the final active reference,
|
||||
* lock will be acquired prior to that.
|
||||
*/
|
||||
void deactivate_super(struct super_block *s)
|
||||
{
|
||||
if (!atomic_add_unless(&s->s_active, -1, 1)) {
|
||||
down_write(&s->s_umount);
|
||||
deactivate_locked_super(s);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(deactivate_super);
|
||||
|
||||
/**
|
||||
* grab_super - acquire an active reference
|
||||
* @s: reference we are trying to make active
|
||||
|
|
@ -247,12 +242,10 @@ static int grab_super(struct super_block *s) __releases(sb_lock)
|
|||
/* it's going away */
|
||||
s->s_count++;
|
||||
spin_unlock(&sb_lock);
|
||||
/* usually that'll be enough for it to die... */
|
||||
/* wait for it to die */
|
||||
down_write(&s->s_umount);
|
||||
up_write(&s->s_umount);
|
||||
put_super(s);
|
||||
/* ... but in case it wasn't, let's at least yield() */
|
||||
yield();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue