diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 777de4ae3dd748f56cc393dda17dfa6529910f5b..20c806069161f386defd404505aa7559a6d0b5f4 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -56,7 +56,7 @@ void *__erofs_bread(struct super_block *sb, struct erofs_buf *buf, if (!page || page->index != index) { erofs_put_metabuf(buf); - if (sb && EROFS_SB(sb)->bootstrap) { + if (sb && erofs_is_rafsv6_mode(sb)) { unsigned int nofs_flag; nofs_flag = memalloc_nofs_save(); @@ -104,7 +104,7 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode, void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, erofs_blk_t blkaddr, enum erofs_kmap_type type) { - if (EROFS_SB(sb)->bootstrap) + if (erofs_is_rafsv6_mode(sb)) return __erofs_bread(sb, buf, EROFS_SB(sb)->bootstrap->f_inode, blkaddr, type); diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 4b3153fc626533e53ba17584e7acbe8099ffeb71..e38dd912818ec7d05edc94ada3107401f5e325f8 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -246,7 +246,6 @@ static int erofs_fill_inode(struct inode *inode) struct erofs_inode *vi = EROFS_I(inode); struct erofs_buf buf = __EROFS_BUF_INITIALIZER; struct super_block *sb = inode->i_sb; - struct erofs_sb_info *sbi = EROFS_SB(sb); void *kaddr; unsigned int ofs; int err = 0; @@ -265,7 +264,7 @@ static int erofs_fill_inode(struct inode *inode) if (erofs_inode_is_data_compressed(vi->datalayout)) { inode->i_fop = &generic_ro_fops; } else { - if (sbi->bootstrap) + if (erofs_is_rafsv6_mode(sb)) inode->i_fop = &rafs_v6_file_ro_fops; else inode->i_fop = &erofs_file_fops; @@ -301,15 +300,18 @@ static int erofs_fill_inode(struct inode *inode) err = -EOPNOTSUPP; goto out_unlock; } - if (sbi->bootstrap && !S_ISREG(inode->i_mode)) { - inode_nohighmem(inode); - inode->i_mapping->a_ops = &rafs_v6_aops; - } else if (inode->i_sb->s_bdev) { - inode->i_mapping->a_ops = &erofs_raw_access_aops; + + if (erofs_is_rafsv6_mode(sb)) { + if (!S_ISREG(inode->i_mode)) { + inode_nohighmem(inode); + inode->i_mapping->a_ops = &rafs_v6_aops; + } #ifdef CONFIG_EROFS_FS_ONDEMAND } else if (erofs_is_fscache_mode(inode->i_sb)) { inode->i_mapping->a_ops = &erofs_fscache_access_aops; #endif + } else { + inode->i_mapping->a_ops = &erofs_raw_access_aops; } out_unlock: @@ -425,7 +427,17 @@ static ssize_t rafs_v6_read_chunk(struct super_block *sb, pr_debug("pipe ret %ld off %llu size %llu read %ld\n", ret, off, size, read); if (ret <= 0) { - pr_err("%s: failed to read blob ret %ld\n", __func__, ret); + pr_err("%s: pipe failed to read blob ret %ld\n", __func__, ret); + return ret; + } + } else if (iov_iter_is_kvec(to)) { + iov_iter_kvec(&titer, READ, to->kvec, 1, size - read); + + ret = vfs_iter_read(mdev.m_fp, &titer, &off, 0); + pr_debug("kvec ret %ld off %llu size %llu read %ld\n", + ret, off, size, read); + if (ret <= 0) { + pr_err("%s: kvec failed to read blob ret %ld\n", __func__, ret); return ret; } } else { @@ -441,7 +453,7 @@ static ssize_t rafs_v6_read_chunk(struct super_block *sb, iov_iter_init(&titer, READ, &iovec, 1, iovec.iov_len); ret = vfs_iter_read(mdev.m_fp, &titer, &off, 0); if (ret <= 0) { - pr_err("%s: failed to read blob ret %ld\n", __func__, ret); + pr_err("%s: iovec failed to read blob ret %ld\n", __func__, ret); return ret; } else if (ret < iovec.iov_len) { return read; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 9ad9909cab54fce51db4ac5664137500a44ff0f6..f033443c7ebf6fd93f038f66a28794b65a6a92ec 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -179,9 +179,16 @@ struct erofs_sb_info { #define set_opt(opt, option) ((opt)->mount_opt |= EROFS_MOUNT_##option) #define test_opt(opt, option) ((opt)->mount_opt & EROFS_MOUNT_##option) +static inline bool erofs_is_rafsv6_mode(struct super_block *sb) +{ + return !sb->s_bdev && EROFS_SB(sb)->bootstrap_path; +} + static inline bool erofs_is_fscache_mode(struct super_block *sb) { - return IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && !sb->s_bdev; + /* to distinguish from rafsv6 which also works in nodev mode */ + return IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && !sb->s_bdev && + EROFS_SB(sb)->fsid; } enum { diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 4ce13a236c9d86b307ee45484756b72a9802c470..4c60da91c7c3c1c1365f1ec18185573514806f58 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -207,7 +207,7 @@ static int erofs_scan_devices(struct super_block *sb, if (!ondisk_extradevs) return 0; - if (!sbi->devs->extra_devices && !erofs_is_fscache_mode(sb)) + if (!sbi->devs->extra_devices && sb->s_bdev) sbi->devs->flatdev = true; sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1; @@ -574,16 +574,6 @@ static int erofs_fc_parse_param(struct fs_context *fc, return -ENOPARAM; } - if (ctx->blob_dir_path && !ctx->bootstrap_path) { - errorfc(fc, "bootstrap_path required in RAFS mode"); - return -EINVAL; - } - - if (ctx->bootstrap_path && ctx->fsid) { - errorfc(fc, "fscache/RAFS modes are mutually exclusive"); - return -EINVAL; - } - return 0; } @@ -757,10 +747,18 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) ctx->blob_dir_path = NULL; sbi->blkszbits = PAGE_SHIFT; - if (erofs_is_fscache_mode(sb)) { + if (!sb->s_bdev) { + /* fscache or rafsv6 mode */ sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; + } else { + if (!sb_set_blocksize(sb, PAGE_SIZE)) { + errorfc(fc, "failed to set initial blksize"); + return -EINVAL; + } + } + if (erofs_is_fscache_mode(sb)) { err = erofs_fscache_register_fs(sb); if (err) return err; @@ -768,13 +766,12 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) err = super_setup_bdi(sb); if (err) return err; - } else { - if (!sb_set_blocksize(sb, PAGE_SIZE)) { - errorfc(fc, "failed to set initial blksize"); - return -EINVAL; - } } + err = rafs_v6_fill_super(sb); + if (err) + return err; + err = erofs_read_superblock(sb); if (err) return err; @@ -793,10 +790,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) } } - err = rafs_v6_fill_super(sb); - if (err) - return err; - sb->s_time_gran = 1; sb->s_xattr = erofs_xattr_handlers; sb->s_export_op = &erofs_export_ops; @@ -855,6 +848,16 @@ static int erofs_fc_get_tree(struct fs_context *fc) { struct erofs_fs_context *ctx = fc->fs_private; + if (ctx->blob_dir_path && !ctx->bootstrap_path) { + errorfc(fc, "bootstrap_path required in RAFS mode"); + return -EINVAL; + } + + if (ctx->bootstrap_path && ctx->fsid) { + errorfc(fc, "fscache/RAFS modes are mutually exclusive"); + return -EINVAL; + } + if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && ctx->fsid) return get_tree_nodev(fc, erofs_fc_fill_super);