mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
super: massage wait event mechanism
We're currently using two separate helpers wait_born() and wait_dead() when we can just all do it in a single helper super_load_flags(). We're also acquiring the lock before we check whether this superblock is even a viable candidate. If it's already dying we don't even need to bother with the lock. Link: https://lore.kernel.org/r/20231127-vfs-super-massage-wait-v1-1-9ab277bfd01a@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
afde134b5b
commit
b30850c58b
51
fs/super.c
51
fs/super.c
@ -81,16 +81,13 @@ static inline void super_unlock_shared(struct super_block *sb)
|
|||||||
super_unlock(sb, false);
|
super_unlock(sb, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool wait_born(struct super_block *sb)
|
static bool super_flags(const struct super_block *sb, unsigned int flags)
|
||||||
{
|
{
|
||||||
unsigned int flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pairs with smp_store_release() in super_wake() and ensures
|
* Pairs with smp_store_release() in super_wake() and ensures
|
||||||
* that we see SB_BORN or SB_DYING after we're woken.
|
* that we see @flags after we're woken.
|
||||||
*/
|
*/
|
||||||
flags = smp_load_acquire(&sb->s_flags);
|
return smp_load_acquire(&sb->s_flags) & flags;
|
||||||
return flags & (SB_BORN | SB_DYING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,10 +108,15 @@ static inline bool wait_born(struct super_block *sb)
|
|||||||
*/
|
*/
|
||||||
static __must_check bool super_lock(struct super_block *sb, bool excl)
|
static __must_check bool super_lock(struct super_block *sb, bool excl)
|
||||||
{
|
{
|
||||||
|
|
||||||
lockdep_assert_not_held(&sb->s_umount);
|
lockdep_assert_not_held(&sb->s_umount);
|
||||||
|
|
||||||
relock:
|
/* wait until the superblock is ready or dying */
|
||||||
|
wait_var_event(&sb->s_flags, super_flags(sb, SB_BORN | SB_DYING));
|
||||||
|
|
||||||
|
/* Don't pointlessly acquire s_umount. */
|
||||||
|
if (super_flags(sb, SB_DYING))
|
||||||
|
return false;
|
||||||
|
|
||||||
__super_lock(sb, excl);
|
__super_lock(sb, excl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -127,20 +129,8 @@ relock:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Has called ->get_tree() successfully. */
|
WARN_ON_ONCE(!(sb->s_flags & SB_BORN));
|
||||||
if (sb->s_flags & SB_BORN)
|
return true;
|
||||||
return true;
|
|
||||||
|
|
||||||
super_unlock(sb, excl);
|
|
||||||
|
|
||||||
/* wait until the superblock is ready or dying */
|
|
||||||
wait_var_event(&sb->s_flags, wait_born(sb));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Neither SB_BORN nor SB_DYING are ever unset so we never loop.
|
|
||||||
* Just reacquire @sb->s_umount for the caller.
|
|
||||||
*/
|
|
||||||
goto relock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait and try to acquire read-side of @sb->s_umount */
|
/* wait and try to acquire read-side of @sb->s_umount */
|
||||||
@ -523,18 +513,6 @@ void deactivate_super(struct super_block *s)
|
|||||||
|
|
||||||
EXPORT_SYMBOL(deactivate_super);
|
EXPORT_SYMBOL(deactivate_super);
|
||||||
|
|
||||||
static inline bool wait_dead(struct super_block *sb)
|
|
||||||
{
|
|
||||||
unsigned int flags;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pairs with memory barrier in super_wake() and ensures
|
|
||||||
* that we see SB_DEAD after we're woken.
|
|
||||||
*/
|
|
||||||
flags = smp_load_acquire(&sb->s_flags);
|
|
||||||
return flags & SB_DEAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* grab_super - acquire an active reference to a superblock
|
* grab_super - acquire an active reference to a superblock
|
||||||
* @sb: superblock to acquire
|
* @sb: superblock to acquire
|
||||||
@ -561,7 +539,7 @@ static bool grab_super(struct super_block *sb)
|
|||||||
}
|
}
|
||||||
super_unlock_excl(sb);
|
super_unlock_excl(sb);
|
||||||
}
|
}
|
||||||
wait_var_event(&sb->s_flags, wait_dead(sb));
|
wait_var_event(&sb->s_flags, super_flags(sb, SB_DEAD));
|
||||||
put_super(sb);
|
put_super(sb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -908,8 +886,7 @@ static void __iterate_supers(void (*f)(struct super_block *))
|
|||||||
|
|
||||||
spin_lock(&sb_lock);
|
spin_lock(&sb_lock);
|
||||||
list_for_each_entry(sb, &super_blocks, s_list) {
|
list_for_each_entry(sb, &super_blocks, s_list) {
|
||||||
/* Pairs with memory marrier in super_wake(). */
|
if (super_flags(sb, SB_DYING))
|
||||||
if (smp_load_acquire(&sb->s_flags) & SB_DYING)
|
|
||||||
continue;
|
continue;
|
||||||
sb->s_count++;
|
sb->s_count++;
|
||||||
spin_unlock(&sb_lock);
|
spin_unlock(&sb_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user