On Tue, 27 Feb 2024 11:00:01 +0800 Gao Xiang <hsiangkao@xxxxxxxxxxxxxxxxx> wrote: > Hi Yue, > > On 2024/2/27 10:22, Yue Hu wrote: > > From: Gao Xiang <hsiangkao@xxxxxxxxxxxxxxxxx> > > > > [ Upstream commit efb4fb02cef3ab410b603c8f0e1c67f61d55f542 ] > > > > Move erofs_load_compr_cfgs() into decompressor.c as well as introduce > > a callback instead of a hard-coded switch for each algorithm for > > simplicity. > > > > Reviewed-by: Chao Yu <chao@xxxxxxxxxx> > > Signed-off-by: Gao Xiang <hsiangkao@xxxxxxxxxxxxxxxxx> > > Link: https://lore.kernel.org/r/20231022130957.11398-1-xiang@xxxxxxxxxx > > Stable-dep-of: 118a8cf504d7 ("erofs: fix inconsistent per-file compression format") > > Signed-off-by: Yue Hu <huyue2@xxxxxxxxxxx> > > where is the real fix [patch 2/2]? It's needed to be posted > here too. Already sent. > > Thanks, > Gao Xiang > > > --- > > fs/erofs/compress.h | 4 ++ > > fs/erofs/decompressor.c | 60 ++++++++++++++++++++++++++++-- > > fs/erofs/decompressor_lzma.c | 4 +- > > fs/erofs/internal.h | 28 ++------------ > > fs/erofs/super.c | 72 +++++------------------------------- > > 5 files changed, 76 insertions(+), 92 deletions(-) > > > > diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h > > index 26fa170090b8..c4a3187bdb8f 100644 > > --- a/fs/erofs/compress.h > > +++ b/fs/erofs/compress.h > > @@ -21,6 +21,8 @@ struct z_erofs_decompress_req { > > }; > > > > struct z_erofs_decompressor { > > + int (*config)(struct super_block *sb, struct erofs_super_block *dsb, > > + void *data, int size); > > int (*decompress)(struct z_erofs_decompress_req *rq, > > struct page **pagepool); > > char *name; > > @@ -93,6 +95,8 @@ int z_erofs_decompress(struct z_erofs_decompress_req *rq, > > struct page **pagepool); > > > > /* prototypes for specific algorithms */ > > +int z_erofs_load_lzma_config(struct super_block *sb, > > + struct erofs_super_block *dsb, void *data, int size); > > int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, > > struct page **pagepool); > > #endif > > diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c > > index 0cfad74374ca..ae3cfd018d99 100644 > > --- a/fs/erofs/decompressor.c > > +++ b/fs/erofs/decompressor.c > > @@ -24,11 +24,11 @@ struct z_erofs_lz4_decompress_ctx { > > unsigned int oend; > > }; > > > > -int z_erofs_load_lz4_config(struct super_block *sb, > > - struct erofs_super_block *dsb, > > - struct z_erofs_lz4_cfgs *lz4, int size) > > +static int z_erofs_load_lz4_config(struct super_block *sb, > > + struct erofs_super_block *dsb, void *data, int size) > > { > > struct erofs_sb_info *sbi = EROFS_SB(sb); > > + struct z_erofs_lz4_cfgs *lz4 = data; > > u16 distance; > > > > if (lz4) { > > @@ -374,17 +374,71 @@ static struct z_erofs_decompressor decompressors[] = { > > .name = "interlaced" > > }, > > [Z_EROFS_COMPRESSION_LZ4] = { > > + .config = z_erofs_load_lz4_config, > > .decompress = z_erofs_lz4_decompress, > > .name = "lz4" > > }, > > #ifdef CONFIG_EROFS_FS_ZIP_LZMA > > [Z_EROFS_COMPRESSION_LZMA] = { > > + .config = z_erofs_load_lzma_config, > > .decompress = z_erofs_lzma_decompress, > > .name = "lzma" > > }, > > #endif > > }; > > > > +int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb) > > +{ > > + struct erofs_sb_info *sbi = EROFS_SB(sb); > > + struct erofs_buf buf = __EROFS_BUF_INITIALIZER; > > + unsigned int algs, alg; > > + erofs_off_t offset; > > + int size, ret = 0; > > + > > + if (!erofs_sb_has_compr_cfgs(sbi)) { > > + sbi->available_compr_algs = Z_EROFS_COMPRESSION_LZ4; > > + return z_erofs_load_lz4_config(sb, dsb, NULL, 0); > > + } > > + > > + sbi->available_compr_algs = le16_to_cpu(dsb->u1.available_compr_algs); > > + if (sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS) { > > + erofs_err(sb, "unidentified algorithms %x, please upgrade kernel", > > + sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS); > > + return -EOPNOTSUPP; > > + } > > + > > + offset = EROFS_SUPER_OFFSET + sbi->sb_size; > > + alg = 0; > > + for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) { > > + void *data; > > + > > + if (!(algs & 1)) > > + continue; > > + > > + data = erofs_read_metadata(sb, &buf, &offset, &size); > > + if (IS_ERR(data)) { > > + ret = PTR_ERR(data); > > + break; > > + } > > + > > + if (alg >= ARRAY_SIZE(decompressors) || > > + !decompressors[alg].config) { > > + erofs_err(sb, "algorithm %d isn't enabled on this kernel", > > + alg); > > + ret = -EOPNOTSUPP; > > + } else { > > + ret = decompressors[alg].config(sb, > > + dsb, data, size); > > + } > > + > > + kfree(data); > > + if (ret) > > + break; > > + } > > + erofs_put_metabuf(&buf); > > + return ret; > > +} > > + > > int z_erofs_decompress(struct z_erofs_decompress_req *rq, > > struct page **pagepool) > > { > > diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c > > index 49addc345aeb..970464c4b676 100644 > > --- a/fs/erofs/decompressor_lzma.c > > +++ b/fs/erofs/decompressor_lzma.c > > @@ -72,10 +72,10 @@ int z_erofs_lzma_init(void) > > } > > > > int z_erofs_load_lzma_config(struct super_block *sb, > > - struct erofs_super_block *dsb, > > - struct z_erofs_lzma_cfgs *lzma, int size) > > + struct erofs_super_block *dsb, void *data, int size) > > { > > static DEFINE_MUTEX(lzma_resize_mutex); > > + struct z_erofs_lzma_cfgs *lzma = data; > > unsigned int dict_size, i; > > struct z_erofs_lzma *strm, *head = NULL; > > int err; > > diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h > > index d8d09fc3ed65..79a7a5815ea6 100644 > > --- a/fs/erofs/internal.h > > +++ b/fs/erofs/internal.h > > @@ -471,6 +471,8 @@ struct erofs_map_dev { > > > > /* data.c */ > > extern const struct file_operations erofs_file_fops; > > +void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf, > > + erofs_off_t *offset, int *lengthp); > > void erofs_unmap_metabuf(struct erofs_buf *buf); > > void erofs_put_metabuf(struct erofs_buf *buf); > > void *erofs_bread(struct erofs_buf *buf, struct inode *inode, > > @@ -565,9 +567,7 @@ void z_erofs_exit_zip_subsystem(void); > > int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, > > struct erofs_workgroup *egrp); > > int erofs_try_to_free_cached_page(struct page *page); > > -int z_erofs_load_lz4_config(struct super_block *sb, > > - struct erofs_super_block *dsb, > > - struct z_erofs_lz4_cfgs *lz4, int len); > > +int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb); > > #else > > static inline void erofs_shrinker_register(struct super_block *sb) {} > > static inline void erofs_shrinker_unregister(struct super_block *sb) {} > > @@ -575,36 +575,14 @@ static inline int erofs_init_shrinker(void) { return 0; } > > static inline void erofs_exit_shrinker(void) {} > > static inline int z_erofs_init_zip_subsystem(void) { return 0; } > > static inline void z_erofs_exit_zip_subsystem(void) {} > > -static inline int z_erofs_load_lz4_config(struct super_block *sb, > > - struct erofs_super_block *dsb, > > - struct z_erofs_lz4_cfgs *lz4, int len) > > -{ > > - if (lz4 || dsb->u1.lz4_max_distance) { > > - erofs_err(sb, "lz4 algorithm isn't enabled"); > > - return -EINVAL; > > - } > > - return 0; > > -} > > #endif /* !CONFIG_EROFS_FS_ZIP */ > > > > #ifdef CONFIG_EROFS_FS_ZIP_LZMA > > int z_erofs_lzma_init(void); > > void z_erofs_lzma_exit(void); > > -int z_erofs_load_lzma_config(struct super_block *sb, > > - struct erofs_super_block *dsb, > > - struct z_erofs_lzma_cfgs *lzma, int size); > > #else > > static inline int z_erofs_lzma_init(void) { return 0; } > > static inline int z_erofs_lzma_exit(void) { return 0; } > > -static inline int z_erofs_load_lzma_config(struct super_block *sb, > > - struct erofs_super_block *dsb, > > - struct z_erofs_lzma_cfgs *lzma, int size) { > > - if (lzma) { > > - erofs_err(sb, "lzma algorithm isn't enabled"); > > - return -EINVAL; > > - } > > - return 0; > > -} > > #endif /* !CONFIG_EROFS_FS_ZIP */ > > > > /* flags for erofs_fscache_register_cookie() */ > > diff --git a/fs/erofs/super.c b/fs/erofs/super.c > > index bd8bf8fc2f5d..f2647126cb2f 100644 > > --- a/fs/erofs/super.c > > +++ b/fs/erofs/super.c > > @@ -126,8 +126,8 @@ static bool check_layout_compatibility(struct super_block *sb, > > > > #ifdef CONFIG_EROFS_FS_ZIP > > /* read variable-sized metadata, offset will be aligned by 4-byte */ > > -static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf, > > - erofs_off_t *offset, int *lengthp) > > +void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf, > > + erofs_off_t *offset, int *lengthp) > > { > > u8 *buffer, *ptr; > > int len, i, cnt; > > @@ -159,64 +159,15 @@ static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf, > > } > > return buffer; > > } > > - > > -static int erofs_load_compr_cfgs(struct super_block *sb, > > - struct erofs_super_block *dsb) > > -{ > > - struct erofs_sb_info *sbi = EROFS_SB(sb); > > - struct erofs_buf buf = __EROFS_BUF_INITIALIZER; > > - unsigned int algs, alg; > > - erofs_off_t offset; > > - int size, ret = 0; > > - > > - sbi->available_compr_algs = le16_to_cpu(dsb->u1.available_compr_algs); > > - if (sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS) { > > - erofs_err(sb, "try to load compressed fs with unsupported algorithms %x", > > - sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS); > > - return -EINVAL; > > - } > > - > > - offset = EROFS_SUPER_OFFSET + sbi->sb_size; > > - alg = 0; > > - for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) { > > - void *data; > > - > > - if (!(algs & 1)) > > - continue; > > - > > - data = erofs_read_metadata(sb, &buf, &offset, &size); > > - if (IS_ERR(data)) { > > - ret = PTR_ERR(data); > > - break; > > - } > > - > > - switch (alg) { > > - case Z_EROFS_COMPRESSION_LZ4: > > - ret = z_erofs_load_lz4_config(sb, dsb, data, size); > > - break; > > - case Z_EROFS_COMPRESSION_LZMA: > > - ret = z_erofs_load_lzma_config(sb, dsb, data, size); > > - break; > > - default: > > - DBG_BUGON(1); > > - ret = -EFAULT; > > - } > > - kfree(data); > > - if (ret) > > - break; > > - } > > - erofs_put_metabuf(&buf); > > - return ret; > > -} > > #else > > -static int erofs_load_compr_cfgs(struct super_block *sb, > > - struct erofs_super_block *dsb) > > +static int z_erofs_parse_cfgs(struct super_block *sb, > > + struct erofs_super_block *dsb) > > { > > - if (dsb->u1.available_compr_algs) { > > - erofs_err(sb, "try to load compressed fs when compression is disabled"); > > - return -EINVAL; > > - } > > - return 0; > > + if (!dsb->u1.available_compr_algs) > > + return 0; > > + > > + erofs_err(sb, "compression disabled, unable to mount compressed EROFS"); > > + return -EOPNOTSUPP; > > } > > #endif > > > > @@ -398,10 +349,7 @@ static int erofs_read_superblock(struct super_block *sb) > > } > > > > /* parse on-disk compression configurations */ > > - if (erofs_sb_has_compr_cfgs(sbi)) > > - ret = erofs_load_compr_cfgs(sb, dsb); > > - else > > - ret = z_erofs_load_lz4_config(sb, dsb, NULL, 0); > > + ret = z_erofs_parse_cfgs(sb, dsb); > > if (ret < 0) > > goto out; > >