Add function activate_super() for grabbing an active reference on a super block. Fails if the filesystem is already shutting down. Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> --- fs/super.c | 19 +++++++++++++++++++ include/linux/fs.h | 1 + 2 files changed, 20 insertions(+) diff --git a/fs/super.c b/fs/super.c index 8d39e4f11cfa..051241cf408b 100644 --- a/fs/super.c +++ b/fs/super.c @@ -393,6 +393,25 @@ static int grab_super(struct super_block *s) __releases(sb_lock) return 0; } +/** + * activate_super - try to grab an active reference on the superblock + * @sb: reference we are trying to grab + * + * Try to grab an active reference on the superblock to prevent filesystem + * shutdown. Fails if the filesystem is already shutting down (see + * deactivate_locked_super()). + */ +bool activate_super(struct super_block *sb) +{ + if (atomic_inc_not_zero(&sb->s_active)) { + smp_mb__after_atomic(); + BUG_ON(!(sb->s_flags & SB_BORN)); + return true; + } + return false; +} +EXPORT_SYMBOL(activate_super); + /* * trylock_super - try to grab ->s_umount shared * @sb: reference we are trying to grab diff --git a/include/linux/fs.h b/include/linux/fs.h index e654435f1651..84c609123a25 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2573,6 +2573,7 @@ void generic_shutdown_super(struct super_block *sb); void kill_block_super(struct super_block *sb); void kill_anon_super(struct super_block *sb); void kill_litter_super(struct super_block *sb); +bool activate_super(struct super_block *sb); void deactivate_super(struct super_block *sb); void deactivate_locked_super(struct super_block *sb); int set_anon_super(struct super_block *s, void *data); -- 2.38.1