diff options
Diffstat (limited to 'fs/super.c')
| -rw-r--r-- | fs/super.c | 33 | 
1 files changed, 31 insertions, 2 deletions
diff --git a/fs/super.c b/fs/super.c index 4fca6657f442..734ed584a946 100644 --- a/fs/super.c +++ b/fs/super.c @@ -423,6 +423,35 @@ bool trylock_super(struct super_block *sb)  }  /** + *	retire_super	-	prevents superblock from being reused + *	@sb: superblock to retire + * + *	The function marks superblock to be ignored in superblock test, which + *	prevents it from being reused for any new mounts.  If the superblock has + *	a private bdi, it also unregisters it, but doesn't reduce the refcount + *	of the superblock to prevent potential races.  The refcount is reduced + *	by generic_shutdown_super().  The function can not be called + *	concurrently with generic_shutdown_super().  It is safe to call the + *	function multiple times, subsequent calls have no effect. + * + *	The marker will affect the re-use only for block-device-based + *	superblocks.  Other superblocks will still get marked if this function + *	is used, but that will not affect their reusability. + */ +void retire_super(struct super_block *sb) +{ +	WARN_ON(!sb->s_bdev); +	down_write(&sb->s_umount); +	if (sb->s_iflags & SB_I_PERSB_BDI) { +		bdi_unregister(sb->s_bdi); +		sb->s_iflags &= ~SB_I_PERSB_BDI; +	} +	sb->s_iflags |= SB_I_RETIRED; +	up_write(&sb->s_umount); +} +EXPORT_SYMBOL(retire_super); + +/**   *	generic_shutdown_super	-	common helper for ->kill_sb()   *	@sb: superblock to kill   * @@ -1216,7 +1245,7 @@ static int set_bdev_super_fc(struct super_block *s, struct fs_context *fc)  static int test_bdev_super_fc(struct super_block *s, struct fs_context *fc)  { -	return s->s_bdev == fc->sget_key; +	return !(s->s_iflags & SB_I_RETIRED) && s->s_bdev == fc->sget_key;  }  /** @@ -1309,7 +1338,7 @@ EXPORT_SYMBOL(get_tree_bdev);  static int test_bdev_super(struct super_block *s, void *data)  { -	return (void *)s->s_bdev == data; +	return !(s->s_iflags & SB_I_RETIRED) && (void *)s->s_bdev == data;  }  struct dentry *mount_bdev(struct file_system_type *fs_type,  |