Commit b947cc5b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'erofs-for-6.9-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs

Pull erofs fixes from Gao Xiang:
 "Three fixes related to EROFS fscache mode. The most important two
  patches fix calling kill_block_super() in bdev-based mode instead of
  kill_anon_super(). The remaining patch is an informative one.

  Summary:

   - Better error message when prepare_ondemand_read failed

   - Fix unmount of bdev-based mode if CONFIG_EROFS_FS_ONDEMAND is on"

* tag 'erofs-for-6.9-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
  erofs: reliably distinguish block based and fscache mode
  erofs: get rid of erofs_fs_context
  erofs: modify the error message when prepare_ondemand_read failed
parents 5af385f5 7af2ae1b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ static int erofs_fscache_read_io_async(struct fscache_cookie *cookie,
		if (WARN_ON(len == 0))
			source = NETFS_INVALID_READ;
		if (source != NETFS_READ_FROM_CACHE) {
			erofs_err(NULL, "prepare_read failed (source %d)", source);
			erofs_err(NULL, "prepare_ondemand_read failed (source %d)", source);
			return -EIO;
		}

+0 −7
Original line number Diff line number Diff line
@@ -84,13 +84,6 @@ struct erofs_dev_context {
	bool flatdev;
};

struct erofs_fs_context {
	struct erofs_mount_opts opt;
	struct erofs_dev_context *devs;
	char *fsid;
	char *domain_id;
};

/* all filesystem-wide lz4 configurations */
struct erofs_sb_lz4_info {
	/* # of pages needed for EROFS lz4 rolling decompression */
+55 −69
Original line number Diff line number Diff line
@@ -370,18 +370,18 @@ static int erofs_read_superblock(struct super_block *sb)
	return ret;
}

static void erofs_default_options(struct erofs_fs_context *ctx)
static void erofs_default_options(struct erofs_sb_info *sbi)
{
#ifdef CONFIG_EROFS_FS_ZIP
	ctx->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
	ctx->opt.max_sync_decompress_pages = 3;
	ctx->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
	sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
	sbi->opt.max_sync_decompress_pages = 3;
	sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
#endif
#ifdef CONFIG_EROFS_FS_XATTR
	set_opt(&ctx->opt, XATTR_USER);
	set_opt(&sbi->opt, XATTR_USER);
#endif
#ifdef CONFIG_EROFS_FS_POSIX_ACL
	set_opt(&ctx->opt, POSIX_ACL);
	set_opt(&sbi->opt, POSIX_ACL);
#endif
}

@@ -426,16 +426,16 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
{
#ifdef CONFIG_FS_DAX
	struct erofs_fs_context *ctx = fc->fs_private;
	struct erofs_sb_info *sbi = fc->s_fs_info;

	switch (mode) {
	case EROFS_MOUNT_DAX_ALWAYS:
		set_opt(&ctx->opt, DAX_ALWAYS);
		clear_opt(&ctx->opt, DAX_NEVER);
		set_opt(&sbi->opt, DAX_ALWAYS);
		clear_opt(&sbi->opt, DAX_NEVER);
		return true;
	case EROFS_MOUNT_DAX_NEVER:
		set_opt(&ctx->opt, DAX_NEVER);
		clear_opt(&ctx->opt, DAX_ALWAYS);
		set_opt(&sbi->opt, DAX_NEVER);
		clear_opt(&sbi->opt, DAX_ALWAYS);
		return true;
	default:
		DBG_BUGON(1);
@@ -450,7 +450,7 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
static int erofs_fc_parse_param(struct fs_context *fc,
				struct fs_parameter *param)
{
	struct erofs_fs_context *ctx = fc->fs_private;
	struct erofs_sb_info *sbi = fc->s_fs_info;
	struct fs_parse_result result;
	struct erofs_device_info *dif;
	int opt, ret;
@@ -463,9 +463,9 @@ static int erofs_fc_parse_param(struct fs_context *fc,
	case Opt_user_xattr:
#ifdef CONFIG_EROFS_FS_XATTR
		if (result.boolean)
			set_opt(&ctx->opt, XATTR_USER);
			set_opt(&sbi->opt, XATTR_USER);
		else
			clear_opt(&ctx->opt, XATTR_USER);
			clear_opt(&sbi->opt, XATTR_USER);
#else
		errorfc(fc, "{,no}user_xattr options not supported");
#endif
@@ -473,16 +473,16 @@ static int erofs_fc_parse_param(struct fs_context *fc,
	case Opt_acl:
#ifdef CONFIG_EROFS_FS_POSIX_ACL
		if (result.boolean)
			set_opt(&ctx->opt, POSIX_ACL);
			set_opt(&sbi->opt, POSIX_ACL);
		else
			clear_opt(&ctx->opt, POSIX_ACL);
			clear_opt(&sbi->opt, POSIX_ACL);
#else
		errorfc(fc, "{,no}acl options not supported");
#endif
		break;
	case Opt_cache_strategy:
#ifdef CONFIG_EROFS_FS_ZIP
		ctx->opt.cache_strategy = result.uint_32;
		sbi->opt.cache_strategy = result.uint_32;
#else
		errorfc(fc, "compression not supported, cache_strategy ignored");
#endif
@@ -504,27 +504,27 @@ static int erofs_fc_parse_param(struct fs_context *fc,
			kfree(dif);
			return -ENOMEM;
		}
		down_write(&ctx->devs->rwsem);
		ret = idr_alloc(&ctx->devs->tree, dif, 0, 0, GFP_KERNEL);
		up_write(&ctx->devs->rwsem);
		down_write(&sbi->devs->rwsem);
		ret = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
		up_write(&sbi->devs->rwsem);
		if (ret < 0) {
			kfree(dif->path);
			kfree(dif);
			return ret;
		}
		++ctx->devs->extra_devices;
		++sbi->devs->extra_devices;
		break;
#ifdef CONFIG_EROFS_FS_ONDEMAND
	case Opt_fsid:
		kfree(ctx->fsid);
		ctx->fsid = kstrdup(param->string, GFP_KERNEL);
		if (!ctx->fsid)
		kfree(sbi->fsid);
		sbi->fsid = kstrdup(param->string, GFP_KERNEL);
		if (!sbi->fsid)
			return -ENOMEM;
		break;
	case Opt_domain_id:
		kfree(ctx->domain_id);
		ctx->domain_id = kstrdup(param->string, GFP_KERNEL);
		if (!ctx->domain_id)
		kfree(sbi->domain_id);
		sbi->domain_id = kstrdup(param->string, GFP_KERNEL);
		if (!sbi->domain_id)
			return -ENOMEM;
		break;
#else
@@ -581,8 +581,7 @@ static const struct export_operations erofs_export_ops = {
static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
{
	struct inode *inode;
	struct erofs_sb_info *sbi;
	struct erofs_fs_context *ctx = fc->fs_private;
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	int err;

	sb->s_magic = EROFS_SUPER_MAGIC;
@@ -590,19 +589,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
	sb->s_maxbytes = MAX_LFS_FILESIZE;
	sb->s_op = &erofs_sops;

	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;

	sb->s_fs_info = sbi;
	sbi->opt = ctx->opt;
	sbi->devs = ctx->devs;
	ctx->devs = NULL;
	sbi->fsid = ctx->fsid;
	ctx->fsid = NULL;
	sbi->domain_id = ctx->domain_id;
	ctx->domain_id = NULL;

	sbi->blkszbits = PAGE_SHIFT;
	if (erofs_is_fscache_mode(sb)) {
		sb->s_blocksize = PAGE_SIZE;
@@ -706,9 +692,9 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)

static int erofs_fc_get_tree(struct fs_context *fc)
{
	struct erofs_fs_context *ctx = fc->fs_private;
	struct erofs_sb_info *sbi = fc->s_fs_info;

	if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && ctx->fsid)
	if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
		return get_tree_nodev(fc, erofs_fc_fill_super);

	return get_tree_bdev(fc, erofs_fc_fill_super);
@@ -718,19 +704,19 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
{
	struct super_block *sb = fc->root->d_sb;
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	struct erofs_fs_context *ctx = fc->fs_private;
	struct erofs_sb_info *new_sbi = fc->s_fs_info;

	DBG_BUGON(!sb_rdonly(sb));

	if (ctx->fsid || ctx->domain_id)
	if (new_sbi->fsid || new_sbi->domain_id)
		erofs_info(sb, "ignoring reconfiguration for fsid|domain_id.");

	if (test_opt(&ctx->opt, POSIX_ACL))
	if (test_opt(&new_sbi->opt, POSIX_ACL))
		fc->sb_flags |= SB_POSIXACL;
	else
		fc->sb_flags &= ~SB_POSIXACL;

	sbi->opt = ctx->opt;
	sbi->opt = new_sbi->opt;

	fc->sb_flags |= SB_RDONLY;
	return 0;
@@ -761,12 +747,15 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs)

static void erofs_fc_free(struct fs_context *fc)
{
	struct erofs_fs_context *ctx = fc->fs_private;
	struct erofs_sb_info *sbi = fc->s_fs_info;

	erofs_free_dev_context(ctx->devs);
	kfree(ctx->fsid);
	kfree(ctx->domain_id);
	kfree(ctx);
	if (!sbi)
		return;

	erofs_free_dev_context(sbi->devs);
	kfree(sbi->fsid);
	kfree(sbi->domain_id);
	kfree(sbi);
}

static const struct fs_context_operations erofs_context_ops = {
@@ -778,38 +767,35 @@ static const struct fs_context_operations erofs_context_ops = {

static int erofs_init_fs_context(struct fs_context *fc)
{
	struct erofs_fs_context *ctx;
	struct erofs_sb_info *sbi;

	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	ctx->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
	if (!ctx->devs) {
		kfree(ctx);

	sbi->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
	if (!sbi->devs) {
		kfree(sbi);
		return -ENOMEM;
	}
	fc->fs_private = ctx;
	fc->s_fs_info = sbi;

	idr_init(&ctx->devs->tree);
	init_rwsem(&ctx->devs->rwsem);
	erofs_default_options(ctx);
	idr_init(&sbi->devs->tree);
	init_rwsem(&sbi->devs->rwsem);
	erofs_default_options(sbi);
	fc->ops = &erofs_context_ops;
	return 0;
}

static void erofs_kill_sb(struct super_block *sb)
{
	struct erofs_sb_info *sbi;
	struct erofs_sb_info *sbi = EROFS_SB(sb);

	if (erofs_is_fscache_mode(sb))
	if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
		kill_anon_super(sb);
	else
		kill_block_super(sb);

	sbi = EROFS_SB(sb);
	if (!sbi)
		return;

	erofs_free_dev_context(sbi->devs);
	fs_put_dax(sbi->dax_dev, NULL);
	erofs_fscache_unregister_fs(sb);