staging: erofs: fix some issues and clean up codes
v2 cover staging: erofs: fix some issues and clean up codes
From: Chao Yu <[email protected]>
This patchset mainly adds error handing code for erofs xattr subsystem. In addition, some code cleanups are also included in this patchset.
P.S. Some other patches are still previewing in the linux-erofs mailing list, which will be posted in the 2nd part later.
[changelog]
v1 -> v2:
[PATCH 2/9] staging: erofs: separate erofs_get_meta_page
- Put err_out stuff at the bottom of the function.
- Drop the question mark in the "truncated by others?". Pointed out by Dan Carpenter <dan.carpenter at oracle.com>
- fix `PTR_ERR applied after initialization to constant'. Reported by kbuild test robot <lkp at intel.com>
- fix compilation error (erofs is bypassed by BROKEN...).
[PATCH 3/9] staging: erofs: add error handling for xattr submodule
- drop all likely/unlikely hints in this patch.
- fix bare use of 'unsigned *' at drivers/staging/erofs/xattr.c:168. Pointed out by Dan Carpenter <dan.carpenter at oracle.com>
[PATCH 6/9] staging: erofs: fix vle_decompressed_index_clusterofs
- don't make functions inline
Pointed out by Dan Carpenter <dan.carpenter at oracle.com>
[PATCH 9/9] staging: erofs: fix potential overflow in erofs_grab_bio()
- in addition, we add one more patch above to fix potential overflow in this series.
Chao Yu (1):
staging: erofs: fix potential overflow in erofs_grab_bio()
Gao Xiang (8):
staging: erofs: introduce erofs_grab_bio
staging: erofs: separate erofs_get_meta_page
staging: erofs: add error handling for xattr submodule
staging: erofs: cleanup z_erofs_vle_work_{lookup, register}
staging: erofs: rearrange vle clustertype definitions
staging: erofs: fix vle_decompressed_index_clusterofs
staging: erofs: fix integer overflow on 32-bit platform
staging: erofs: fix compression mapping beyond EOF
drivers/staging/erofs/Kconfig | 9 ++ drivers/staging/erofs/data.c | 68 +++++++++----- drivers/staging/erofs/erofs_fs.h | 11 +++ drivers/staging/erofs/internal.h | 66 ++++++++----- drivers/staging/erofs/unzip_vle.c | 149 +++++++++++++++--------------- drivers/staging/erofs/xattr.c | 127 +++++++++++++++++-------- 6 files changed, 273 insertions(+), 157 deletions(-)
Signature · 1 line
2.18.0
PATCH v2 1/9 staging: erofs: introduce erofs_grab_bio
From: Gao Xiang <[email protected]>
this patch renames prepare_bio to erofs_grab_bio, and adds a nofail option in order to retry in the bio allocator under memory pressure.
--- drivers/staging/erofs/data.c | 12 +++++++++-- drivers/staging/erofs/internal.h | 36 +++++++++++++++---------------- drivers/staging/erofs/unzip_vle.c | 4 ++-- 3 files changed, 30 insertions(+), 22 deletions(-)
drivers/staging/erofs/data.c +10 -2
@@ -60,7 +60,8 @@ struct page *erofs_get_meta_page(struct super_block *sb,struct bio *bio;int err; - bio =prepare_bio (sb, blkaddr,1 , read_endio); + bio =erofs_grab_bio (sb, blkaddr,1 , read_endio, true); + err =bio_add_page (bio, page,PAGE_SIZE ,0 );BUG_ON (err !=PAGE_SIZE );
@@ -278,7 +279,14 @@ static inline struct bio *erofs_read_raw_page(if (nblocks >BIO_MAX_PAGES ) nblocks =BIO_MAX_PAGES ; - bio =prepare_bio (inode->i_sb, blknr, nblocks, read_endio); + bio =erofs_grab_bio (inode->i_sb, + blknr, nblocks, read_endio, false); + +if (IS_ERR (bio)) { + err =PTR_ERR (bio); + bio =NULL ; + goto err_out; + } } err =bio_add_page (bio, page,PAGE_SIZE ,0 );
drivers/staging/erofs/internal.h +18 -18
@@ -420,26 +420,26 @@ struct erofs_map_blocks {#define EROFS_GET_BLOCKS_RAW 0x0001/* data.c */ -static inline struct bio *prepare_bio ( -struct super_block *sb, -erofs_blk_t blkaddr,unsigned nr_pages, -bio_end_io_t endio) +static inline struct bio * +erofs_grab_bio (struct super_block *sb, +erofs_blk_t blkaddr,unsigned int nr_pages, +bio_end_io_t endio,bool nofail) { -gfp_t gfp =GFP_NOIO ; -struct bio *bio =bio_alloc (gfp, nr_pages); - -if (unlikely (bio ==NULL ) && - (current->flags &PF_MEMALLOC )) { -do { - nr_pages /=2 ; -if (unlikely (!nr_pages)) { - bio =bio_alloc (gfp | __GFP_NOFAIL,1 ); -BUG_ON (bio ==NULL ); -break ; +const gfp_t gfp =GFP_NOIO ; +struct bio *bio; + +do { +if (nr_pages ==1 ) { + bio =bio_alloc (gfp | (nofail ? __GFP_NOFAIL :0 ),1 ); +if (unlikely (bio ==NULL )) { +DBG_BUGON (nofail); +return ERR_PTR (-ENOMEM ); } - bio =bio_alloc (gfp, nr_pages); - }while (bio ==NULL ); - } +break ; + } + bio =bio_alloc (gfp, nr_pages); + nr_pages /=2 ; + }while (unlikely (bio ==NULL )); bio->bi_end_io = endio;bio_set_dev (bio, sb->s_bdev);
drivers/staging/erofs/unzip_vle.c +2 -2
@@ -1213,8 +1213,8 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, }if (bio ==NULL ) { - bio =prepare_bio (sb, first_index + i, -BIO_MAX_PAGES , z_erofs_vle_read_endio); + bio =erofs_grab_bio (sb, first_index + i, +BIO_MAX_PAGES , z_erofs_vle_read_endio, true); bio->bi_private =tagptr_cast_ptr (bi_private); ++nr_bios;
Signature · 1 line
2.18.0
PATCH v2 2/9 staging: erofs: separate erofs_get_meta_page
In reply to Chao YuFrom: Gao Xiang <[email protected]>
This patch separates 'erofs_get_meta_page' into 'erofs_get_meta_page' and 'erofs_get_meta_page_nofail'. The second one ensures that it should not fail under memory pressure and should make best efforts if IO errors occur.
It also adds auxiliary variables in order to fulfill 80 character limit.
--- drivers/staging/erofs/Kconfig | 9 +++++ drivers/staging/erofs/data.c | 58 ++++++++++++++++++++----------- drivers/staging/erofs/internal.h | 30 +++++++++++++--- drivers/staging/erofs/unzip_vle.c | 12 ++++--- drivers/staging/erofs/xattr.c | 23 +++++++----- 5 files changed, 93 insertions(+), 39 deletions(-)
drivers/staging/erofs/Kconfig +9 -0
@@ -78,6 +78,15 @@ config EROFS_FAULT_INJECTION Test EROFS to inject faults such as ENOMEM, EIO, and so on. If unsure, say N. +config EROFS_FS_IO_MAX_RETRIES + int "EROFS IO Maximum Retries" + depends on EROFS_FS + default "5" + help + Maximum retry count of IO Errors. + + If unsure, leave the default value (5 retries, 6 IOs at most). + config EROFS_FS_ZIP bool "EROFS Data Compresssion Support" depends on EROFS_FS
drivers/staging/erofs/data.c +38 -20
90 lines not on this page · raw message
drivers/staging/erofs/internal.h +25 -5
@@ -453,8 +453,27 @@ static inline void __submit_bio(struct bio *bio, unsigned op, unsigned op_flags)submit_bio (bio); } -extern struct page *erofs_get_meta_page (struct super_block *sb, -erofs_blk_t blkaddr,bool prio); +#ifndef CONFIG_EROFS_FS_IO_MAX_RETRIES +#define EROFS_IO_MAX_RETRIES_NOFAIL 0 +#else +#define EROFS_IO_MAX_RETRIES_NOFAIL CONFIG_EROFS_FS_IO_MAX_RETRIES +#endif + +extern struct page *__erofs_get_meta_page (struct super_block *sb, +erofs_blk_t blkaddr,bool prio,bool nofail); + +static inline struct page *erofs_get_meta_page (struct super_block *sb, +erofs_blk_t blkaddr,bool prio) +{ +return __erofs_get_meta_page (sb, blkaddr, prio, false); +} + +static inline struct page *erofs_get_meta_page_nofail (struct super_block *sb, +erofs_blk_t blkaddr,bool prio) +{ +return __erofs_get_meta_page (sb, blkaddr, prio, true); +} +extern int erofs_map_blocks (struct inode *,struct erofs_map_blocks *,int );extern int erofs_map_blocks_iter (struct inode *,struct erofs_map_blocks *,struct page **,int );
@@ -465,10 +484,11 @@ struct erofs_map_blocks_iter { }; -static inline struct page *erofs_get_inline_page (struct inode *inode, -erofs_blk_t blkaddr) +static inline struct page * +erofs_get_inline_page_nofail (struct inode *inode, +erofs_blk_t blkaddr) { -return erofs_get_meta_page (inode->i_sb, +return erofs_get_meta_page_nofail (inode->i_sb, blkaddr,S_ISDIR (inode->i_mode)); }
drivers/staging/erofs/unzip_vle.c +7 -5
@@ -1488,7 +1488,8 @@ static erofs_off_t vle_get_logical_extent_head(erofs_blk_t blkaddr =vle_extent_blkaddr (inode, lcn);struct z_erofs_vle_decompressed_index *di;unsigned long long ofs; -const unsigned int clusterbits =EROFS_SB (inode->i_sb)->clusterbits; +struct super_block *const sb = inode->i_sb; +const unsigned int clusterbits =EROFS_SB (sb)->clusterbits;const unsigned int clustersize =1 << clusterbits;if (page->index != blkaddr) {
@@ -1496,8 +1497,8 @@ static erofs_off_t vle_get_logical_extent_head(unlock_page (page);put_page (page); - *page_iter = page =erofs_get_meta_page (inode->i_sb, - blkaddr, false); + page =erofs_get_meta_page_nofail (sb, blkaddr, false); + *page_iter = page; *kaddr_iter =kmap_atomic (page); }
@@ -1538,7 +1539,8 @@ int z_erofs_map_blocks_iter(struct inode *inode,struct page *mpage = *mpage_ret;void *kaddr;bool initial; -const unsigned int clusterbits =EROFS_SB (inode->i_sb)->clusterbits; +struct super_block *const sb = inode->i_sb; +const unsigned int clusterbits =EROFS_SB (sb)->clusterbits;const unsigned int clustersize =1 << clusterbits;int err =0 ;
@@ -1569,7 +1571,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,if (mpage !=NULL )put_page (mpage); - mpage =erofs_get_meta_page (inode->i_sb, e_blkaddr, false); + mpage =erofs_get_meta_page_nofail (sb, e_blkaddr, false); *mpage_ret = mpage; }else {lock_page (mpage);
drivers/staging/erofs/xattr.c +14 -9
@@ -38,6 +38,7 @@ static void init_inode_xattrs(struct inode *inode)struct xattr_iter it;unsigned i;struct erofs_xattr_ibody_header *ih; +struct super_block *sb;struct erofs_sb_info *sbi;struct erofs_vnode *vi;bool atomic_map;
@@ -48,11 +49,12 @@ static void init_inode_xattrs(struct inode *inode) vi =EROFS_V (inode);BUG_ON (!vi->xattr_isize); - sbi =EROFS_I_SB (inode); + sb = inode->i_sb; + sbi =EROFS_SB (sb); it.blkaddr =erofs_blknr (iloc (sbi, vi->nid) + vi->inode_isize); it.ofs =erofs_blkoff (iloc (sbi, vi->nid) + vi->inode_isize); - it.page =erofs_get_inline_page (inode, it.blkaddr); + it.page =erofs_get_inline_page_nofail (inode, it.blkaddr);BUG_ON (IS_ERR (it.page));/* read in shared xattr array (non-atomic, see kmalloc below) */
@@ -75,7 +77,7 @@ static void init_inode_xattrs(struct inode *inode)BUG_ON (it.ofs !=EROFS_BLKSIZ );xattr_iter_end (&it, atomic_map); - it.page =erofs_get_meta_page (inode->i_sb, + it.page =erofs_get_meta_page_nofail (sb, ++it.blkaddr,S_ISDIR (inode->i_mode));BUG_ON (IS_ERR (it.page));
@@ -105,7 +107,8 @@ static void xattr_iter_fixup(struct xattr_iter *it)xattr_iter_end (it, true); it->blkaddr +=erofs_blknr (it->ofs); - it->page =erofs_get_meta_page (it->sb, it->blkaddr, false); + it->page =erofs_get_meta_page_nofail (it->sb, + it->blkaddr, false);BUG_ON (IS_ERR (it->page)); it->kaddr =kmap_atomic (it->page);
@@ -131,7 +134,7 @@ static int inline_xattr_iter_begin(struct xattr_iter *it, it->blkaddr =erofs_blknr (iloc (sbi, vi->nid) + inline_xattr_ofs); it->ofs =erofs_blkoff (iloc (sbi, vi->nid) + inline_xattr_ofs); - it->page =erofs_get_inline_page (inode, it->blkaddr); + it->page =erofs_get_inline_page_nofail (inode, it->blkaddr);BUG_ON (IS_ERR (it->page)); it->kaddr =kmap_atomic (it->page);
@@ -300,7 +303,8 @@ static int inline_getxattr(struct inode *inode, struct getxattr_iter *it)static int shared_getxattr (struct inode *inode,struct getxattr_iter *it) {struct erofs_vnode *const vi =EROFS_V (inode); -struct erofs_sb_info *const sbi =EROFS_SB (inode->i_sb); +struct super_block *const sb = inode->i_sb; +struct erofs_sb_info *const sbi =EROFS_SB (sb);unsigned i;int ret = -ENOATTR ;
@@ -314,7 +318,7 @@ static int shared_getxattr(struct inode *inode, struct getxattr_iter *it)if (i)xattr_iter_end (&it->it, true); - it->it.page =erofs_get_meta_page (inode->i_sb, + it->it.page =erofs_get_meta_page_nofail (sb, blkaddr, false);BUG_ON (IS_ERR (it->it.page)); it->it.kaddr =kmap_atomic (it->it.page);
@@ -524,7 +528,8 @@ static int shared_listxattr(struct listxattr_iter *it) {struct inode *const inode =d_inode (it->dentry);struct erofs_vnode *const vi =EROFS_V (inode); -struct erofs_sb_info *const sbi =EROFS_I_SB (inode); +struct super_block *const sb = inode->i_sb; +struct erofs_sb_info *const sbi =EROFS_SB (sb);unsigned i;int ret =0 ;
@@ -537,7 +542,7 @@ static int shared_listxattr(struct listxattr_iter *it)if (i)xattr_iter_end (&it->it, true); - it->it.page =erofs_get_meta_page (inode->i_sb, + it->it.page =erofs_get_meta_page_nofail (sb, blkaddr, false);BUG_ON (IS_ERR (it->it.page)); it->it.kaddr =kmap_atomic (it->it.page);
Signature · 1 line
2.18.0
PATCH v2 3/9 staging: erofs: add error handling for xattr submodule
In reply to Chao YuFrom: Gao Xiang <[email protected]>
This patch enhances the missing error handling code for xattr submodule, which improves the stability for the rare cases.
--- drivers/staging/erofs/internal.h | 6 +- drivers/staging/erofs/xattr.c | 122 +++++++++++++++++++++---------- 2 files changed, 85 insertions(+), 43 deletions(-)
drivers/staging/erofs/internal.h +3 -3
@@ -485,10 +485,10 @@ struct erofs_map_blocks_iter {static inline struct page * -erofs_get_inline_page_nofail (struct inode *inode, -erofs_blk_t blkaddr) +erofs_get_inline_page (struct inode *inode, +erofs_blk_t blkaddr) { -return erofs_get_meta_page_nofail (inode->i_sb, +return erofs_get_meta_page (inode->i_sb, blkaddr,S_ISDIR (inode->i_mode)); }
drivers/staging/erofs/xattr.c +82 -40
269 lines not on this page · raw message
Signature · 1 line
2.18.0
PATCH v2 4/9 staging: erofs: cleanup z_erofs_vle_work_{lookup, register}
In reply to Chao YuFrom: Gao Xiang <[email protected]>
This patch introduces 'struct z_erofs_vle_work_finder' to clean up arguments of z_erofs_vle_work_lookup and z_erofs_vle_work_register.
--- drivers/staging/erofs/unzip_vle.c | 89 ++++++++++++++++--------------- 1 file changed, 47 insertions(+), 42 deletions(-)
drivers/staging/erofs/unzip_vle.c +47 -42
@@ -271,36 +271,42 @@ static inline bool try_to_claim_workgroup(return true;/* lucky, I am the followee :) */ } +struct z_erofs_vle_work_finder { +struct super_block *sb; +pgoff_t idx; +unsigned pageofs; + +struct z_erofs_vle_workgroup **grp_ret; +enum z_erofs_vle_work_role *role; +z_erofs_vle_owned_workgrp_t *owned_head; +bool *hosted; +}; +static struct z_erofs_vle_work * -z_erofs_vle_work_lookup (struct super_block *sb, -pgoff_t idx,unsigned pageofs, -struct z_erofs_vle_workgroup **grp_ret, -enum z_erofs_vle_work_role *role, -z_erofs_vle_owned_workgrp_t *owned_head, -bool *hosted) +z_erofs_vle_work_lookup (const struct z_erofs_vle_work_finder *f) {bool tag, primary;struct erofs_workgroup *egrp;struct z_erofs_vle_workgroup *grp;struct z_erofs_vle_work *work; - egrp =erofs_find_workgroup (sb, idx, &tag); + egrp =erofs_find_workgroup (f->sb, f->idx, &tag);if (egrp ==NULL ) { - *grp_ret =NULL ; + *f->grp_ret =NULL ;return NULL ; } - *grp_ret = grp =container_of (egrp, - struct z_erofs_vle_workgroup, obj); + grp = container_of(egrp, struct z_erofs_vle_workgroup, obj); + *f->grp_ret = grp;#ifndef CONFIG_EROFS_FS_ZIP_MULTIREF - work =z_erofs_vle_grab_work (grp, pageofs); + work =z_erofs_vle_grab_work (grp, f->pageofs); primary = true;#else BUG ();#endif -DBG_BUGON (work->pageofs != pageofs); +DBG_BUGON (work->pageofs != f->pageofs);/* * lock must be taken first to avoid grp->next == NIL between
@@ -340,29 +346,24 @@ z_erofs_vle_work_lookup(struct super_block *sb,*/ mutex_lock (&work->lock); - *hosted = false; + *f->hosted = false;if (!primary) - *role =Z_EROFS_VLE_WORK_SECONDARY ; + *f->role =Z_EROFS_VLE_WORK_SECONDARY ;/* claim the workgroup if possible */ -else if (try_to_claim_workgroup (grp, owned_head, hosted)) - *role =Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED ; +else if (try_to_claim_workgroup (grp, f->owned_head, f->hosted)) + *f->role =Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED ;else - *role =Z_EROFS_VLE_WORK_PRIMARY ; + *f->role =Z_EROFS_VLE_WORK_PRIMARY ;return work; }static struct z_erofs_vle_work * -z_erofs_vle_work_register (struct super_block *sb, -struct z_erofs_vle_workgroup **grp_ret, -struct erofs_map_blocks *map, -pgoff_t index,unsigned pageofs, -enum z_erofs_vle_work_role *role, -z_erofs_vle_owned_workgrp_t *owned_head, -bool *hosted) +z_erofs_vle_work_register (const struct z_erofs_vle_work_finder *f, +struct erofs_map_blocks *map) { -bool newgrp = false; -struct z_erofs_vle_workgroup *grp = *grp_ret; +bool gnew = false; +struct z_erofs_vle_workgroup *grp = *f->grp_ret;struct z_erofs_vle_work *work;#ifndef CONFIG_EROFS_FS_ZIP_MULTIREF
@@ -376,7 +377,7 @@ z_erofs_vle_work_register(struct super_block *sb,if (unlikely (grp ==NULL ))return ERR_PTR (-ENOMEM ); - grp->obj.index = index; + grp->obj.index = f->idx; grp->llen = map->m_llen; z_erofs_vle_set_workgrp_fmt(grp,
@@ -386,13 +387,13 @@ z_erofs_vle_work_register(struct super_block *sb,atomic_set (&grp->obj.refcount,1 );/* new workgrps have been claimed as type 1 */ -WRITE_ONCE (grp->next, *owned_head); +WRITE_ONCE (grp->next, *f->owned_head);/* primary and followed work for all new workgrps */ - *role =Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED ; + *f->role =Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED ;/* it should be submitted by ourselves */ - *hosted = true; + *f->hosted = true; - newgrp = true; + gnew = true;#ifdef CONFIG_EROFS_FS_ZIP_MULTIREF skip:/* currently unimplemented */
@@ -400,12 +401,12 @@ z_erofs_vle_work_register(struct super_block *sb,#else work =z_erofs_vle_grab_primary_work (grp);#endif - work->pageofs = pageofs; + work->pageofs = f->pageofs;mutex_init (&work->lock); -if (newgrp) { -int err =erofs_register_workgroup (sb, &grp->obj,0 ); +if (gnew) { +int err =erofs_register_workgroup (f->sb, &grp->obj,0 );if (err) {kmem_cache_free (z_erofs_workgroup_cachep, grp);
@@ -413,7 +414,7 @@ z_erofs_vle_work_register(struct super_block *sb, } } - *owned_head = *grp_ret = grp; + *f->owned_head = *f->grp_ret = grp;mutex_lock (&work->lock);return work;
@@ -440,9 +441,16 @@ static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, z_erofs_vle_owned_workgrp_t *owned_head) {const unsigned clusterpages =erofs_clusterpages (EROFS_SB (sb)); -const erofs_blk_t index =erofs_blknr (map->m_pa); -const unsigned pageofs = map->m_la & ~PAGE_MASK ;struct z_erofs_vle_workgroup *grp; +const struct z_erofs_vle_work_finder finder = { + .sb = sb, + .idx =erofs_blknr (map->m_pa), + .pageofs = map->m_la & ~PAGE_MASK , + .grp_ret = &grp, + .role = &builder->role, + .owned_head = owned_head, + .hosted = &builder->hosted + };struct z_erofs_vle_work *work;DBG_BUGON (builder->work !=NULL );
@@ -454,16 +462,13 @@ static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder,DBG_BUGON (erofs_blkoff (map->m_pa)); repeat: - work =z_erofs_vle_work_lookup (sb, index, - pageofs, &grp, &builder->role, owned_head, &builder->hosted); + work =z_erofs_vle_work_lookup (&finder);if (work !=NULL ) {__update_workgrp_llen (grp, map->m_llen); goto got_it; } - work =z_erofs_vle_work_register (sb, &grp, map, index, pageofs, - &builder->role, owned_head, &builder->hosted); - + work =z_erofs_vle_work_register (&finder, map);if (unlikely (work ==ERR_PTR (-EAGAIN ))) goto repeat;
Signature · 1 line
2.18.0
PATCH v2 5/9 staging: erofs: rearrange vle clustertype definitions
In reply to Chao YuFrom: Gao Xiang <[email protected]>
This patch moves vle clustertype definitions to erofs_fs.h since they are part of on-disk format.
It also adds compile time check for Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS
--- drivers/staging/erofs/erofs_fs.h | 11 +++++++++++ drivers/staging/erofs/unzip_vle.c | 8 -------- 2 files changed, 11 insertions(+), 8 deletions(-)
drivers/staging/erofs/erofs_fs.h +11 -0
@@ -202,6 +202,14 @@ struct erofs_extent_header {* di_u.delta[1] = distance to its corresponding tail cluster * (di_advise could be 0, 1 or 2) */ +enum { +Z_EROFS_VLE_CLUSTER_TYPE_PLAIN , +Z_EROFS_VLE_CLUSTER_TYPE_HEAD , +Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD , +Z_EROFS_VLE_CLUSTER_TYPE_RESERVED , +Z_EROFS_VLE_CLUSTER_TYPE_MAX +}; +#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0
@@ -260,6 +268,9 @@ static inline void erofs_check_ondisk_layout_definitions(void)BUILD_BUG_ON (sizeof (struct erofs_extent_header ) !=16 );BUILD_BUG_ON (sizeof (struct z_erofs_vle_decompressed_index ) !=8 );BUILD_BUG_ON (sizeof (struct erofs_dirent ) !=12 ); + +BUILD_BUG_ON (BIT (Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS ) < + Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1); }#endif
drivers/staging/erofs/unzip_vle.c +0 -8
@@ -1416,14 +1416,6 @@ const struct address_space_operations z_erofs_vle_normalaccess_aops = {#define __vle_cluster_type (advise) __vle_cluster_advise(advise, \ Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT, Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) -enum { -Z_EROFS_VLE_CLUSTER_TYPE_PLAIN , -Z_EROFS_VLE_CLUSTER_TYPE_HEAD , -Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD , -Z_EROFS_VLE_CLUSTER_TYPE_RESERVED , -Z_EROFS_VLE_CLUSTER_TYPE_MAX -}; -#define vle_cluster_type (di) \ __vle_cluster_type((di)->di_advise)
Signature · 1 line
2.18.0
PATCH v2 6/9 staging: erofs: fix vle_decompressed_index_clusterofs
In reply to Chao YuFrom: Gao Xiang <[email protected]>
This patch adds error handing code, and fixes a missing endian conversion in vle_decompressed_index_clusterofs.
--- drivers/staging/erofs/unzip_vle.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-)
drivers/staging/erofs/unzip_vle.c +15 -11
@@ -1419,24 +1419,24 @@ const struct address_space_operations z_erofs_vle_normalaccess_aops = {#define vle_cluster_type (di) \ __vle_cluster_type((di)->di_advise) -static inline unsigned -vle_compressed_index_clusterofs (unsigned clustersize, -struct z_erofs_vle_decompressed_index *di) +static int +vle_decompressed_index_clusterofs (unsigned int *clusterofs, +unsigned int clustersize, +struct z_erofs_vle_decompressed_index *di) { -debugln ("%s, vle=%pK, advise=%x (type %u), clusterofs=%x blkaddr=%x" , - __func__, di, di->di_advise,vle_cluster_type (di), - di->di_clusterofs, di->di_u.blkaddr); -switch (vle_cluster_type (di)) {case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD : + *clusterofs = clustersize;break ;case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN :case Z_EROFS_VLE_CLUSTER_TYPE_HEAD : -return di->di_clusterofs; + *clusterofs =le16_to_cpu (di->di_clusterofs); +break ;default : -BUG_ON (1 ); +DBG_BUGON (1 ); +return -EIO ; } -return clustersize; +return 0 ; } static inline erofs_blk_t
@@ -1581,7 +1581,11 @@ int z_erofs_map_blocks_iter(struct inode *inode,debugln ("%s, lcn %u e_blkaddr %u e_blkoff %u" , __func__, lcn, e_blkaddr,vle_extent_blkoff (inode, lcn)); - logical_cluster_ofs =vle_compressed_index_clusterofs (clustersize, di); + err =vle_decompressed_index_clusterofs (&logical_cluster_ofs, + clustersize, di); +if (unlikely (err)) + goto unmap_out; +if (!initial) {/* [walking mode] 'map' has been already initialized */ map->m_llen += logical_cluster_ofs;
Signature · 1 line
2.18.0
PATCH v2 7/9 staging: erofs: fix integer overflow on 32-bit platform
In reply to Chao YuFrom: Gao Xiang <[email protected]>
This patch fixes integer overflow on multiplication of 32-bit `lcn' in z_erofs_map_blocks_iter.
--- drivers/staging/erofs/unzip_vle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/staging/erofs/unzip_vle.c +4 -4
@@ -1513,7 +1513,7 @@ static erofs_off_t vle_get_logical_extent_head( *flags ^=EROFS_MAP_ZIPPED ;case Z_EROFS_VLE_CLUSTER_TYPE_HEAD :/* clustersize should be a power of two */ - ofs = ((unsigned long long )lcn << clusterbits) + + ofs = ((u64 )lcn << clusterbits) + (le16_to_cpu (di->di_clusterofs) & (clustersize -1 )); *pcn =le32_to_cpu (di->di_u.blkaddr);break ;
@@ -1595,7 +1595,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,/* by default, compressed */ map->m_flags |=EROFS_MAP_ZIPPED ; - end = (u64)(lcn +1 ) * clustersize; + end = ((u64 )lcn +1 ) * clustersize; cluster_type =vle_cluster_type (di);
@@ -1611,7 +1611,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, }if (ofs_rem > logical_cluster_ofs) { - ofs = lcn * clustersize | logical_cluster_ofs; + ofs = (u64 )lcn * clustersize | logical_cluster_ofs; pcn =le32_to_cpu (di->di_u.blkaddr);break ; }
@@ -1623,7 +1623,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, err = -EIO ; goto unmap_out; } - end = (lcn-- * clustersize) | logical_cluster_ofs; + end = ((u64 )lcn-- * clustersize) | logical_cluster_ofs;/* fallthrough */ case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD :/* get the correspoinding first chunk */
Signature · 1 line
2.18.0
PATCH v2 8/9 staging: erofs: fix compression mapping beyond EOF
In reply to Chao YuFrom: Gao Xiang <[email protected]>
Logical address of EOF LTP mapping should start at inode->i_size' rather than inode->i_size - 1' to `m_la(in)', fix it.
--- drivers/staging/erofs/unzip_vle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/erofs/unzip_vle.c +1 -1
@@ -1548,7 +1548,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,if (unlikely (map->m_la >= inode->i_size)) {BUG_ON (!initial); map->m_llen = map->m_la +1 - inode->i_size; - map->m_la = inode->i_size -1 ; + map->m_la = inode->i_size; map->m_flags =0 ; goto out; }
Signature · 1 line
2.18.0
PATCH v2 9/9 staging: erofs: fix potential overflow in erofs_grab_bio()
In reply to Chao YuFrom: Chao Yu <[email protected]>
As Dan reported in LKP's mailing list:
https://lists.01.org/pipermail/kbuild-all/2018-August/051419.html
New smatch warnings:drivers/staging/erofs/internal.h:446 erofs_grab_bio() warn: should 'blkaddr << (12 - 9)' be a 64 bit type? drivers/staging/erofs/data.c:78 __erofs_get_meta_page() error: 'bio' dereferencing possible ERR_PTR() drivers/staging/erofs/internal.h:446 erofs_grab_bio() warn: should 'blkaddr << (12 - 9)' be a 64 bit type?
Old smatch warnings:drivers/staging/erofs/unzip_vle.c:989 z_erofs_vle_unzip() error: double unlock 'mutex:&z_pagemap_global_lock' drivers/staging/erofs/unzip_vle.c:1318 z_erofs_vle_normalaccess_readpage() warn: should 'page->index << 12' be a 64 bit type? drivers/staging/erofs/unzip_vle.c:1351 __z_erofs_vle_normalaccess_readpages() warn: should '()->index << 12' be a 64 bit type?
It needs to cast varable's type to sector_t before left shifting.
--- drivers/staging/erofs/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/erofs/internal.h +1 -1
@@ -443,7 +443,7 @@ erofs_grab_bio(struct super_block *sb, bio->bi_end_io = endio;bio_set_dev (bio, sb->s_bdev); - bio->bi_iter.bi_sector = blkaddr <<LOG_SECTORS_PER_BLOCK ; + bio->bi_iter.bi_sector = (sector_t )blkaddr <<LOG_SECTORS_PER_BLOCK ;return bio; }
Signature · 1 line
2.18.0