diff options
Diffstat (limited to 'drivers/staging/erofs')
-rw-r--r-- | drivers/staging/erofs/Documentation/filesystems/erofs.txt | 1 | ||||
-rw-r--r-- | drivers/staging/erofs/data.c | 23 | ||||
-rw-r--r-- | drivers/staging/erofs/dir.c | 45 | ||||
-rw-r--r-- | drivers/staging/erofs/inode.c | 18 | ||||
-rw-r--r-- | drivers/staging/erofs/internal.h | 19 | ||||
-rw-r--r-- | drivers/staging/erofs/namei.c | 3 | ||||
-rw-r--r-- | drivers/staging/erofs/super.c | 56 | ||||
-rw-r--r-- | drivers/staging/erofs/unzip_pagevec.h | 6 | ||||
-rw-r--r-- | drivers/staging/erofs/unzip_vle.c | 142 | ||||
-rw-r--r-- | drivers/staging/erofs/unzip_vle_lz4.c | 7 | ||||
-rw-r--r-- | drivers/staging/erofs/utils.c | 4 | ||||
-rw-r--r-- | drivers/staging/erofs/xattr.c | 50 |
12 files changed, 205 insertions, 169 deletions
diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt index 961ec4da7705..74cf84ac48a3 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt @@ -60,6 +60,7 @@ fault_injection=%d Enable fault injection in all supported types with specified injection rate. Supported injection type: Type_Name Type_Value FAULT_KMALLOC 0x000000001 + FAULT_READ_IO 0x000000002 (no)user_xattr Setup Extended User Attributes. Note: xattr is enabled by default if CONFIG_EROFS_FS_XATTR is selected. (no)acl Setup POSIX Access Control List. Note: acl is enabled diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index 526e0dbea5b5..746685f90564 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -17,12 +17,17 @@ static inline void read_endio(struct bio *bio) { - int i; + struct super_block *const sb = bio->bi_private; struct bio_vec *bvec; - const blk_status_t err = bio->bi_status; + blk_status_t err = bio->bi_status; struct bvec_iter_all iter_all; - bio_for_each_segment_all(bvec, bio, i, iter_all) { + if (time_to_inject(EROFS_SB(sb), FAULT_READ_IO)) { + erofs_show_injection_info(FAULT_READ_IO); + err = BLK_STS_IOERR; + } + + bio_for_each_segment_all(bvec, bio, iter_all) { struct page *page = bvec->bv_page; /* page is already locked */ @@ -63,7 +68,7 @@ repeat: if (!PageUptodate(page)) { struct bio *bio; - bio = erofs_grab_bio(sb, blkaddr, 1, read_endio, nofail); + bio = erofs_grab_bio(sb, blkaddr, 1, sb, read_endio, nofail); if (IS_ERR(bio)) { DBG_BUGON(nofail); err = PTR_ERR(bio); @@ -188,7 +193,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, unsigned int nblocks, bool ra) { - struct inode *inode = mapping->host; + struct inode *const inode = mapping->host; + struct super_block *const sb = inode->i_sb; erofs_off_t current_block = (erofs_off_t)page->index; int err; @@ -280,9 +286,8 @@ submit_bio_retry: if (nblocks > BIO_MAX_PAGES) nblocks = BIO_MAX_PAGES; - bio = erofs_grab_bio(inode->i_sb, - blknr, nblocks, read_endio, false); - + bio = erofs_grab_bio(sb, blknr, nblocks, sb, + read_endio, false); if (IS_ERR(bio)) { err = PTR_ERR(bio); bio = NULL; @@ -298,7 +303,7 @@ submit_bio_retry: *last_block = current_block; /* shift in advance in case of it followed by too many gaps */ - if (unlikely(bio->bi_vcnt >= bio->bi_max_vecs)) { + if (bio->bi_iter.bi_size >= bio->bi_max_vecs * PAGE_SIZE) { /* err should reassign to 0 after submitting */ err = 0; goto submit_bio_out; diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index 829f7b12e0dc..9bbc68729c11 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -23,6 +23,21 @@ static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = { [EROFS_FT_SYMLINK] = DT_LNK, }; +static void debug_one_dentry(unsigned char d_type, const char *de_name, + unsigned int de_namelen) +{ +#ifdef CONFIG_EROFS_FS_DEBUG + /* since the on-disk name could not have the trailing '\0' */ + unsigned char dbg_namebuf[EROFS_NAME_LEN + 1]; + + memcpy(dbg_namebuf, de_name, de_namelen); + dbg_namebuf[de_namelen] = '\0'; + + debugln("found dirent %s de_len %u d_type %d", dbg_namebuf, + de_namelen, d_type); +#endif +} + static int erofs_fill_dentries(struct dir_context *ctx, void *dentry_blk, unsigned int *ofs, unsigned int nameoff, unsigned int maxsize) @@ -33,14 +48,10 @@ static int erofs_fill_dentries(struct dir_context *ctx, de = dentry_blk + *ofs; while (de < end) { const char *de_name; - int de_namelen; + unsigned int de_namelen; unsigned char d_type; -#ifdef CONFIG_EROFS_FS_DEBUG - unsigned int dbg_namelen; - unsigned char dbg_namebuf[EROFS_NAME_LEN]; -#endif - if (unlikely(de->file_type < EROFS_FT_MAX)) + if (de->file_type < EROFS_FT_MAX) d_type = erofs_filetype_table[de->file_type]; else d_type = DT_UNKNOWN; @@ -48,26 +59,20 @@ static int erofs_fill_dentries(struct dir_context *ctx, nameoff = le16_to_cpu(de->nameoff); de_name = (char *)dentry_blk + nameoff; - de_namelen = unlikely(de + 1 >= end) ? - /* last directory entry */ - strnlen(de_name, maxsize - nameoff) : - le16_to_cpu(de[1].nameoff) - nameoff; + /* the last dirent in the block? */ + if (de + 1 >= end) + de_namelen = strnlen(de_name, maxsize - nameoff); + else + de_namelen = le16_to_cpu(de[1].nameoff) - nameoff; /* a corrupted entry is found */ - if (unlikely(de_namelen < 0)) { + if (unlikely(nameoff + de_namelen > maxsize || + de_namelen > EROFS_NAME_LEN)) { DBG_BUGON(1); return -EIO; } -#ifdef CONFIG_EROFS_FS_DEBUG - dbg_namelen = min(EROFS_NAME_LEN - 1, de_namelen); - memcpy(dbg_namebuf, de_name, dbg_namelen); - dbg_namebuf[dbg_namelen] = '\0'; - - debugln("%s, found de_name %s de_len %d d_type %d", __func__, - dbg_namebuf, de_namelen, d_type); -#endif - + debug_one_dentry(d_type, de_name, de_namelen); if (!dir_emit(ctx, de_name, de_namelen, le64_to_cpu(de->nid), d_type)) /* stopped by some reason */ diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 924b8dfc7a8f..c7d3b815a798 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -25,7 +25,7 @@ static int read_inode(struct inode *inode, void *data) if (unlikely(vi->data_mapping_mode >= EROFS_INODE_LAYOUT_MAX)) { errln("unknown data mapping mode %u of nid %llu", - vi->data_mapping_mode, vi->nid); + vi->data_mapping_mode, vi->nid); DBG_BUGON(1); return -EIO; } @@ -38,7 +38,7 @@ static int read_inode(struct inode *inode, void *data) inode->i_mode = le16_to_cpu(v2->i_mode); if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { + S_ISLNK(inode->i_mode)) { vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { inode->i_rdev = @@ -68,7 +68,7 @@ static int read_inode(struct inode *inode, void *data) inode->i_mode = le16_to_cpu(v1->i_mode); if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { + S_ISLNK(inode->i_mode)) { vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { inode->i_rdev = @@ -92,7 +92,7 @@ static int read_inode(struct inode *inode, void *data) inode->i_size = le32_to_cpu(v1->i_size); } else { errln("unsupported on-disk inode version %u of nid %llu", - __inode_version(advise), vi->nid); + __inode_version(advise), vi->nid); DBG_BUGON(1); return -EIO; } @@ -129,7 +129,7 @@ static int fill_inline_data(struct inode *inode, void *data, if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) { char *lnk = erofs_kmalloc(sbi, inode->i_size + 1, GFP_KERNEL); - if (unlikely(lnk == NULL)) + if (unlikely(!lnk)) return -ENOMEM; m_pofs += vi->inode_isize + vi->xattr_isize; @@ -173,7 +173,7 @@ static int fill_inode(struct inode *inode, int isdir) if (IS_ERR(page)) { errln("failed to get inode (nid: %llu) page, err %ld", - vi->nid, PTR_ERR(page)); + vi->nid, PTR_ERR(page)); return PTR_ERR(page); } @@ -260,16 +260,18 @@ static inline struct inode *erofs_iget_locked(struct super_block *sb, } struct inode *erofs_iget(struct super_block *sb, - erofs_nid_t nid, bool isdir) + erofs_nid_t nid, + bool isdir) { struct inode *inode = erofs_iget_locked(sb, nid); - if (unlikely(inode == NULL)) + if (unlikely(!inode)) return ERR_PTR(-ENOMEM); if (inode->i_state & I_NEW) { int err; struct erofs_vnode *vi = EROFS_V(inode); + vi->nid = nid; err = fill_inode(inode, isdir); diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index e3bfde00c7d2..c47778b3fabd 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -44,11 +44,12 @@ enum { FAULT_KMALLOC, + FAULT_READ_IO, FAULT_MAX, }; #ifdef CONFIG_EROFS_FAULT_INJECTION -extern char *erofs_fault_name[FAULT_MAX]; +extern const char *erofs_fault_name[FAULT_MAX]; #define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type))) struct erofs_fault_info { @@ -268,8 +269,15 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page); #define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) +{ + return page->mapping == MNGD_MAPPING(sbi); +} #else #define MNGD_MAPPING(sbi) (NULL) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) { return false; } #endif #define DEFAULT_MAX_SYNC_DECOMPRESS_PAGES 3 @@ -460,7 +468,7 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, /* data.c */ static inline struct bio * erofs_grab_bio(struct super_block *sb, - erofs_blk_t blkaddr, unsigned int nr_pages, + erofs_blk_t blkaddr, unsigned int nr_pages, void *bi_private, bio_end_io_t endio, bool nofail) { const gfp_t gfp = GFP_NOIO; @@ -469,7 +477,7 @@ erofs_grab_bio(struct super_block *sb, do { if (nr_pages == 1) { bio = bio_alloc(gfp | (nofail ? __GFP_NOFAIL : 0), 1); - if (unlikely(bio == NULL)) { + if (unlikely(!bio)) { DBG_BUGON(nofail); return ERR_PTR(-ENOMEM); } @@ -477,11 +485,12 @@ erofs_grab_bio(struct super_block *sb, } bio = bio_alloc(gfp, nr_pages); nr_pages /= 2; - } while (unlikely(bio == NULL)); + } while (unlikely(!bio)); bio->bi_end_io = endio; bio_set_dev(bio, sb->s_bdev); bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK; + bio->bi_private = bi_private; return bio; } @@ -565,7 +574,7 @@ static inline void *erofs_vmap(struct page **pages, unsigned int count) while (1) { void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); /* retry two more times (totally 3 times) */ - if (addr != NULL || ++i >= 3) + if (addr || ++i >= 3) return addr; vm_unmap_aliases(); } diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index 3f4fa52c10fa..d8d9dc9dab43 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -211,7 +211,8 @@ int erofs_namei(struct inode *dir, /* NOTE: i_mutex is already held by vfs */ static struct dentry *erofs_lookup(struct inode *dir, - struct dentry *dentry, unsigned int flags) + struct dentry *dentry, + unsigned int flags) { int err; erofs_nid_t nid; diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 15c784fba879..399847d21146 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -33,10 +33,11 @@ static void init_once(void *ptr) static int __init erofs_init_inode_cache(void) { erofs_inode_cachep = kmem_cache_create("erofs_inode", - sizeof(struct erofs_vnode), 0, - SLAB_RECLAIM_ACCOUNT, init_once); + sizeof(struct erofs_vnode), 0, + SLAB_RECLAIM_ACCOUNT, + init_once); - return erofs_inode_cachep != NULL ? 0 : -ENOMEM; + return erofs_inode_cachep ? 0 : -ENOMEM; } static void erofs_exit_inode_cache(void) @@ -49,7 +50,7 @@ static struct inode *alloc_inode(struct super_block *sb) struct erofs_vnode *vi = kmem_cache_alloc(erofs_inode_cachep, GFP_KERNEL); - if (vi == NULL) + if (!vi) return NULL; /* zero out everything except vfs_inode */ @@ -57,9 +58,8 @@ static struct inode *alloc_inode(struct super_block *sb) return &vi->vfs_inode; } -static void i_callback(struct rcu_head *head) +static void free_inode(struct inode *inode) { - struct inode *inode = container_of(head, struct inode, i_rcu); struct erofs_vnode *vi = EROFS_V(inode); /* be careful RCU symlink path (see ext4_inode_info->i_data)! */ @@ -71,11 +71,6 @@ static void i_callback(struct rcu_head *head) kmem_cache_free(erofs_inode_cachep, vi); } -static void destroy_inode(struct inode *inode) -{ - call_rcu(&inode->i_rcu, i_callback); -} - static int superblock_read(struct super_block *sb) { struct erofs_sb_info *sbi; @@ -86,7 +81,7 @@ static int superblock_read(struct super_block *sb) bh = sb_bread(sb, 0); - if (bh == NULL) { + if (!bh) { errln("cannot read erofs superblock"); return -EIO; } @@ -105,7 +100,7 @@ static int superblock_read(struct super_block *sb) /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ if (unlikely(blkszbits != LOG_BLOCK_SIZE)) { errln("blksize %u isn't supported on this platform", - 1 << blkszbits); + 1 << blkszbits); goto out; } @@ -121,7 +116,7 @@ static int superblock_read(struct super_block *sb) if (1 << (sbi->clusterbits - PAGE_SHIFT) > Z_EROFS_CLUSTER_MAX_PAGES) errln("clusterbits %u is not supported on this kernel", - sbi->clusterbits); + sbi->clusterbits); #endif sbi->root_nid = le16_to_cpu(layout->root_nid); @@ -132,7 +127,7 @@ static int superblock_read(struct super_block *sb) memcpy(&sb->s_uuid, layout->uuid, sizeof(layout->uuid)); memcpy(sbi->volume_name, layout->volume_name, - sizeof(layout->volume_name)); + sizeof(layout->volume_name)); ret = 0; out: @@ -141,8 +136,9 @@ out: } #ifdef CONFIG_EROFS_FAULT_INJECTION -char *erofs_fault_name[FAULT_MAX] = { +const char *erofs_fault_name[FAULT_MAX] = { [FAULT_KMALLOC] = "kmalloc", + [FAULT_READ_IO] = "read IO error", }; static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, @@ -239,7 +235,7 @@ static int parse_options(struct super_block *sb, char *options) if (!options) return 0; - while ((p = strsep(&options, ",")) != NULL) { + while ((p = strsep(&options, ","))) { int token; if (!*p) @@ -313,7 +309,8 @@ static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask) } static void managed_cache_invalidatepage(struct page *page, - unsigned int offset, unsigned int length) + unsigned int offset, + unsigned int length) { const unsigned int stop = length + offset; @@ -336,7 +333,7 @@ static struct inode *erofs_init_managed_cache(struct super_block *sb) { struct inode *inode = new_inode(sb); - if (unlikely(inode == NULL)) + if (unlikely(!inode)) return ERR_PTR(-ENOMEM); set_nlink(inode, 1); @@ -352,7 +349,8 @@ static struct inode *erofs_init_managed_cache(struct super_block *sb) #endif static int erofs_read_super(struct super_block *sb, - const char *dev_name, void *data, int silent) + const char *dev_name, + void *data, int silent) { struct inode *inode; struct erofs_sb_info *sbi; @@ -367,7 +365,7 @@ static int erofs_read_super(struct super_block *sb, } sbi = kzalloc(sizeof(struct erofs_sb_info), GFP_KERNEL); - if (unlikely(sbi == NULL)) { + if (unlikely(!sbi)) { err = -ENOMEM; goto err; } @@ -424,21 +422,21 @@ static int erofs_read_super(struct super_block *sb, if (!S_ISDIR(inode->i_mode)) { errln("rootino(nid %llu) is not a directory(i_mode %o)", - ROOT_NID(sbi), inode->i_mode); + ROOT_NID(sbi), inode->i_mode); err = -EINVAL; iput(inode); goto err_iget; } sb->s_root = d_make_root(inode); - if (sb->s_root == NULL) { + if (!sb->s_root) { err = -ENOMEM; goto err_iget; } /* save the device name to sbi */ sbi->dev_name = __getname(); - if (sbi->dev_name == NULL) { + if (!sbi->dev_name) { err = -ENOMEM; goto err_devname; } @@ -450,7 +448,7 @@ static int erofs_read_super(struct super_block *sb, if (!silent) infoln("mounted on %s with opts: %s.", dev_name, - (char *)data); + (char *)data); return 0; /* * please add a label for each exit point and use @@ -481,7 +479,7 @@ static void erofs_put_super(struct super_block *sb) struct erofs_sb_info *sbi = EROFS_SB(sb); /* for cases which are failed in "read_super" */ - if (sbi == NULL) + if (!sbi) return; WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); @@ -515,7 +513,7 @@ struct erofs_mount_private { /* support mount_bdev() with options */ static int erofs_fill_super(struct super_block *sb, - void *_priv, int silent) + void *_priv, int silent) { struct erofs_mount_private *priv = _priv; @@ -635,7 +633,7 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root) #endif if (test_opt(sbi, FAULT_INJECTION)) seq_printf(seq, ",fault_injection=%u", - erofs_get_fault_rate(sbi)); + erofs_get_fault_rate(sbi)); return 0; } @@ -668,7 +666,7 @@ out: const struct super_operations erofs_sops = { .put_super = erofs_put_super, .alloc_inode = alloc_inode, - .destroy_inode = destroy_inode, + .free_inode = free_inode, .statfs = erofs_statfs, .show_options = erofs_show_options, .remount_fs = erofs_remount, diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/unzip_pagevec.h index 23856ba2742d..f37d8fd14771 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/drivers/staging/erofs/unzip_pagevec.h @@ -43,7 +43,7 @@ struct z_erofs_pagevec_ctor { static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, bool atomic) { - if (ctor->curr == NULL) + if (!ctor->curr) return; if (atomic) @@ -59,7 +59,7 @@ z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, unsigned index; /* keep away from occupied pages */ - if (ctor->next != NULL) + if (ctor->next) return ctor->next; for (index = 0; index < nr; ++index) { @@ -121,7 +121,7 @@ z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, bool *occupied) { *occupied = false; - if (unlikely(ctor->next == NULL && type)) + if (unlikely(!ctor->next && type)) if (ctor->index + 1 == ctor->nr) return false; diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index 8715bc50e09c..9ecaa872bae8 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -313,12 +313,12 @@ static int z_erofs_vle_work_add_page( /* give priority for the compressed data storage */ if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY && - type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && - try_to_reuse_as_compressed_page(builder, page)) + type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && + try_to_reuse_as_compressed_page(builder, page)) return 0; ret = z_erofs_pagevec_ctor_enqueue(&builder->vector, - page, type, &occupied); + page, type, &occupied); builder->work->vcnt += (unsigned int)ret; return ret ? 0 : -EAGAIN; @@ -464,10 +464,9 @@ z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f, grp->obj.index = f->idx; grp->llen = map->m_llen; - z_erofs_vle_set_workgrp_fmt(grp, - (map->m_flags & EROFS_MAP_ZIPPED) ? - Z_EROFS_VLE_WORKGRP_FMT_LZ4 : - Z_EROFS_VLE_WORKGRP_FMT_PLAIN); + z_erofs_vle_set_workgrp_fmt(grp, (map->m_flags & EROFS_MAP_ZIPPED) ? + Z_EROFS_VLE_WORKGRP_FMT_LZ4 : + Z_EROFS_VLE_WORKGRP_FMT_PLAIN); /* new workgrps have been claimed as type 1 */ WRITE_ONCE(grp->next, *f->owned_head); @@ -554,7 +553,8 @@ repeat: return PTR_ERR(work); got_it: z_erofs_pagevec_ctor_init(&builder->vector, - Z_EROFS_VLE_INLINE_PAGEVECS, work->pagevec, work->vcnt); + Z_EROFS_VLE_INLINE_PAGEVECS, + work->pagevec, work->vcnt); if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { /* enable possibly in-place decompression */ @@ -594,8 +594,9 @@ void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) call_rcu(&work->rcu, z_erofs_rcu_callback); } -static void __z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, - struct z_erofs_vle_work *work __maybe_unused) +static void +__z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, + struct z_erofs_vle_work *work __maybe_unused) { erofs_workgroup_put(&grp->obj); } @@ -715,7 +716,7 @@ repeat: /* lucky, within the range of the current map_blocks */ if (offset + cur >= map->m_la && - offset + cur < map->m_la + map->m_llen) { + offset + cur < map->m_la + map->m_llen) { /* didn't get a valid unzip work previously (very rare) */ if (!builder->work) goto restart_now; @@ -781,8 +782,8 @@ retry: struct page *const newpage = __stagingpage_alloc(page_pool, GFP_NOFS); - err = z_erofs_vle_work_add_page(builder, - newpage, Z_EROFS_PAGE_TYPE_EXCLUSIVE); + err = z_erofs_vle_work_add_page(builder, newpage, + Z_EROFS_PAGE_TYPE_EXCLUSIVE); if (likely(!err)) goto retry; } @@ -843,35 +844,30 @@ static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) static inline void z_erofs_vle_read_endio(struct bio *bio) { - const blk_status_t err = bio->bi_status; - unsigned int i; + struct erofs_sb_info *sbi = NULL; + blk_status_t err = bio->bi_status; struct bio_vec *bvec; -#ifdef EROFS_FS_HAS_MANAGED_CACHE - struct address_space *mc = NULL; -#endif struct bvec_iter_all iter_all; - bio_for_each_segment_all(bvec, bio, i, iter_all) { + bio_for_each_segment_all(bvec, bio, iter_all) { struct page *page = bvec->bv_page; bool cachemngd = false; DBG_BUGON(PageUptodate(page)); DBG_BUGON(!page->mapping); -#ifdef EROFS_FS_HAS_MANAGED_CACHE - if (unlikely(!mc && !z_erofs_is_stagingpage(page))) { - struct inode *const inode = page->mapping->host; - struct super_block *const sb = inode->i_sb; + if (unlikely(!sbi && !z_erofs_is_stagingpage(page))) { + sbi = EROFS_SB(page->mapping->host->i_sb); - mc = MNGD_MAPPING(EROFS_SB(sb)); + if (time_to_inject(sbi, FAULT_READ_IO)) { + erofs_show_injection_info(FAULT_READ_IO); + err = BLK_STS_IOERR; + } } - /* - * If mc has not gotten, it equals NULL, - * however, page->mapping never be NULL if working properly. - */ - cachemngd = (page->mapping == mc); -#endif + /* sbi should already be gotten if the page is managed */ + if (sbi) + cachemngd = erofs_page_is_managed(sbi, page); if (unlikely(err)) SetPageError(page); @@ -890,8 +886,8 @@ static struct page *z_pagemap_global[Z_EROFS_VLE_VMAP_GLOBAL_PAGES]; static DEFINE_MUTEX(z_pagemap_global_lock); static int z_erofs_vle_unzip(struct super_block *sb, - struct z_erofs_vle_workgroup *grp, - struct list_head *page_pool) + struct z_erofs_vle_workgroup *grp, + struct list_head *page_pool) { struct erofs_sb_info *const sbi = EROFS_SB(sb); const unsigned int clusterpages = erofs_clusterpages(sbi); @@ -919,12 +915,12 @@ static int z_erofs_vle_unzip(struct super_block *sb, if (likely(nr_pages <= Z_EROFS_VLE_VMAP_ONSTACK_PAGES)) pages = pages_onstack; else if (nr_pages <= Z_EROFS_VLE_VMAP_GLOBAL_PAGES && - mutex_trylock(&z_pagemap_global_lock)) + mutex_trylock(&z_pagemap_global_lock)) pages = z_pagemap_global; else { repeat: - pages = kvmalloc_array(nr_pages, - sizeof(struct page *), GFP_KERNEL); + pages = kvmalloc_array(nr_pages, sizeof(struct page *), + GFP_KERNEL); /* fallback to global pagemap for the lowmem scenario */ if (unlikely(!pages)) { @@ -940,8 +936,8 @@ repeat: for (i = 0; i < nr_pages; ++i) pages[i] = NULL; - z_erofs_pagevec_ctor_init(&ctor, - Z_EROFS_VLE_INLINE_PAGEVECS, work->pagevec, 0); + z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_VLE_INLINE_PAGEVECS, + work->pagevec, 0); for (i = 0; i < work->vcnt; ++i) { unsigned int pagenr; @@ -972,6 +968,7 @@ repeat: overlapped = false; compressed_pages = grp->compressed_pages; + err = 0; for (i = 0; i < clusterpages; ++i) { unsigned int pagenr; @@ -981,31 +978,42 @@ repeat: DBG_BUGON(!page); DBG_BUGON(!page->mapping); - if (z_erofs_is_stagingpage(page)) - continue; -#ifdef EROFS_FS_HAS_MANAGED_CACHE - if (page->mapping == MNGD_MAPPING(sbi)) { - DBG_BUGON(!PageUptodate(page)); - continue; - } -#endif + if (!z_erofs_is_stagingpage(page)) { + if (erofs_page_is_managed(sbi, page)) { + if (unlikely(!PageUptodate(page))) + err = -EIO; + continue; + } - /* only non-head page could be reused as a compressed page */ - pagenr = z_erofs_onlinepage_index(page); + /* + * only if non-head page can be selected + * for inplace decompression + */ + pagenr = z_erofs_onlinepage_index(page); - DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); - ++sparsemem_pages; - pages[pagenr] = page; + DBG_BUGON(pagenr >= nr_pages); + DBG_BUGON(pages[pagenr]); + ++sparsemem_pages; + pages[pagenr] = page; + + overlapped = true; + } - overlapped = true; + /* PG_error needs checking for inplaced and staging pages */ + if (unlikely(PageError(page))) { + DBG_BUGON(PageUptodate(page)); + err = -EIO; + } } + if (unlikely(err)) + goto out; + llen = (nr_pages << PAGE_SHIFT) - work->pageofs; if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) { err = z_erofs_vle_plain_copy(compressed_pages, clusterpages, - pages, nr_pages, work->pageofs); + pages, nr_pages, work->pageofs); goto out; } @@ -1029,9 +1037,13 @@ repeat: skip_allocpage: vout = erofs_vmap(pages, nr_pages); + if (!vout) { + err = -ENOMEM; + goto out; + } - err = z_erofs_vle_unzip_vmap(compressed_pages, - clusterpages, vout, llen, work->pageofs, overlapped); + err = z_erofs_vle_unzip_vmap(compressed_pages, clusterpages, vout, + llen, work->pageofs, overlapped); erofs_vunmap(vout, nr_pages); @@ -1040,10 +1052,9 @@ out: for (i = 0; i < clusterpages; ++i) { page = compressed_pages[i]; -#ifdef EROFS_FS_HAS_MANAGED_CACHE - if (page->mapping == MNGD_MAPPING(sbi)) + if (erofs_page_is_managed(sbi, page)) continue; -#endif + /* recycle all individual staging pages */ (void)z_erofs_gather_if_stagingpage(page_pool, page); @@ -1194,6 +1205,7 @@ repeat: if (page->mapping == mc) { WRITE_ONCE(grp->compressed_pages[nr], page); + ClearPageError(page); if (!PagePrivate(page)) { /* * impossible to be !PagePrivate(page) for @@ -1427,10 +1439,8 @@ submit_bio_retry: if (!bio) { bio = erofs_grab_bio(sb, first_index + i, - BIO_MAX_PAGES, + BIO_MAX_PAGES, bi_private, z_erofs_vle_read_endio, true); - bio->bi_private = bi_private; - ++nr_bios; } @@ -1567,7 +1577,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct erofs_vnode *vi = EROFS_V(inode); errln("%s, readahead error at page %lu of nid %llu", - __func__, page->index, vi->nid); + __func__, page->index, vi->nid); } put_page(page); @@ -1722,8 +1732,8 @@ vle_get_logical_extent_head(const struct vle_map_blocks_iter_ctx *ctx, } int z_erofs_map_blocks_iter(struct inode *inode, - struct erofs_map_blocks *map, - int flags) + struct erofs_map_blocks *map, + int flags) { void *kaddr; const struct vle_map_blocks_iter_ctx ctx = { @@ -1830,7 +1840,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, /* logical cluster number should be >= 1 */ if (unlikely(!lcn)) { errln("invalid logical cluster 0 at nid %llu", - EROFS_V(inode)->nid); + EROFS_V(inode)->nid); err = -EIO; goto unmap_out; } @@ -1850,7 +1860,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, break; default: errln("unknown cluster type %u at offset %llu of nid %llu", - cluster_type, ofs, EROFS_V(inode)->nid); + cluster_type, ofs, EROFS_V(inode)->nid); err = -EIO; goto unmap_out; } diff --git a/drivers/staging/erofs/unzip_vle_lz4.c b/drivers/staging/erofs/unzip_vle_lz4.c index 48b263a2731a..0daac9b984a8 100644 --- a/drivers/staging/erofs/unzip_vle_lz4.c +++ b/drivers/staging/erofs/unzip_vle_lz4.c @@ -136,10 +136,13 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages, nr_pages = DIV_ROUND_UP(outlen + pageofs, PAGE_SIZE); - if (clusterpages == 1) + if (clusterpages == 1) { vin = kmap_atomic(compressed_pages[0]); - else + } else { vin = erofs_vmap(compressed_pages, clusterpages); + if (!vin) + return -ENOMEM; + } preempt_disable(); vout = erofs_pcpubuf[smp_processor_id()].data; diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 5f61f99f4c10..3e7d30b6de1d 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -61,7 +61,7 @@ struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, repeat: rcu_read_lock(); grp = radix_tree_lookup(&sbi->workstn_tree, index); - if (grp != NULL) { + if (grp) { *tag = xa_pointer_tag(grp); grp = xa_untag_pointer(grp); @@ -221,7 +221,7 @@ repeat: erofs_workstn_lock(sbi); found = radix_tree_gang_lookup(&sbi->workstn_tree, - batch, first_index, PAGEVEC_SIZE); + batch, first_index, PAGEVEC_SIZE); for (i = 0; i < found; ++i) { struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index f716ab0446e5..df40654b9fbb 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -36,7 +36,7 @@ static inline void xattr_iter_end(struct xattr_iter *it, bool atomic) static inline void xattr_iter_end_final(struct xattr_iter *it) { - if (it->page == NULL) + if (!it->page) return; xattr_iter_end(it, true); @@ -107,7 +107,7 @@ static int init_inode_xattrs(struct inode *inode) vi->xattr_shared_count = ih->h_shared_count; vi->xattr_shared_xattrs = kmalloc_array(vi->xattr_shared_count, sizeof(uint), GFP_KERNEL); - if (vi->xattr_shared_xattrs == NULL) { + if (!vi->xattr_shared_xattrs) { xattr_iter_end(&it, atomic_map); ret = -ENOMEM; goto out_unlock; @@ -122,8 +122,8 @@ static int init_inode_xattrs(struct inode *inode) BUG_ON(it.ofs != EROFS_BLKSIZ); xattr_iter_end(&it, atomic_map); - it.page = erofs_get_meta_page(sb, - ++it.blkaddr, S_ISDIR(inode->i_mode)); + it.page = erofs_get_meta_page(sb, ++it.blkaddr, + S_ISDIR(inode->i_mode)); if (IS_ERR(it.page)) { kfree(vi->xattr_shared_xattrs); vi->xattr_shared_xattrs = NULL; @@ -187,7 +187,7 @@ static inline int xattr_iter_fixup(struct xattr_iter *it) } static int inline_xattr_iter_begin(struct xattr_iter *it, - struct inode *inode) + struct inode *inode) { struct erofs_vnode *const vi = EROFS_V(inode); struct erofs_sb_info *const sbi = EROFS_SB(inode->i_sb); @@ -217,7 +217,8 @@ static int inline_xattr_iter_begin(struct xattr_iter *it, * `ofs' pointing to the next xattr item rather than an arbitrary position. */ static int xattr_foreach(struct xattr_iter *it, - const struct xattr_iter_handlers *op, unsigned int *tlimit) + const struct xattr_iter_handlers *op, + unsigned int *tlimit) { struct erofs_xattr_entry entry; unsigned int value_sz, processed, slice; @@ -234,7 +235,7 @@ static int xattr_foreach(struct xattr_iter *it, * therefore entry should be in the page */ entry = *(struct erofs_xattr_entry *)(it->kaddr + it->ofs); - if (tlimit != NULL) { + if (tlimit) { unsigned int entry_sz = EROFS_XATTR_ENTRY_SIZE(&entry); BUG_ON(*tlimit < entry_sz); @@ -281,7 +282,7 @@ static int xattr_foreach(struct xattr_iter *it, /* 3. handle xattr value */ processed = 0; - if (op->alloc_buffer != NULL) { + if (op->alloc_buffer) { err = op->alloc_buffer(it, value_sz); if (err) { it->ofs += value_sz; @@ -321,7 +322,7 @@ struct getxattr_iter { }; static int xattr_entrymatch(struct xattr_iter *_it, - struct erofs_xattr_entry *entry) + struct erofs_xattr_entry *entry) { struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); @@ -330,7 +331,7 @@ static int xattr_entrymatch(struct xattr_iter *_it, } static int xattr_namematch(struct xattr_iter *_it, - unsigned int processed, char *buf, unsigned int len) + unsigned int processed, char *buf, unsigned int len) { struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); @@ -338,17 +339,18 @@ static int xattr_namematch(struct xattr_iter *_it, } static int xattr_checkbuffer(struct xattr_iter *_it, - unsigned int value_sz) + unsigned int value_sz) { struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); int err = it->buffer_size < value_sz ? -ERANGE : 0; it->buffer_size = value_sz; - return it->buffer == NULL ? 1 : err; + return !it->buffer ? 1 : err; } static void xattr_copyvalue(struct xattr_iter *_it, - unsigned int processed, char *buf, unsigned int len) + unsigned int processed, + char *buf, unsigned int len) { struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); @@ -429,13 +431,13 @@ static bool erofs_xattr_trusted_list(struct dentry *dentry) } int erofs_getxattr(struct inode *inode, int index, - const char *name, - void *buffer, size_t buffer_size) + const char *name, + void *buffer, size_t buffer_size) { int ret; struct getxattr_iter it; - if (unlikely(name == NULL)) + if (unlikely(!name)) return -EINVAL; ret = init_inode_xattrs(inode); @@ -460,8 +462,8 @@ int erofs_getxattr(struct inode *inode, int index, } static int erofs_xattr_generic_get(const struct xattr_handler *handler, - struct dentry *unused, struct inode *inode, - const char *name, void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { struct erofs_sb_info *const sbi = EROFS_I_SB(inode); @@ -527,7 +529,7 @@ struct listxattr_iter { }; static int xattr_entrylist(struct xattr_iter *_it, - struct erofs_xattr_entry *entry) + struct erofs_xattr_entry *entry) { struct listxattr_iter *it = container_of(_it, struct listxattr_iter, it); @@ -537,13 +539,13 @@ static int xattr_entrylist(struct xattr_iter *_it, const struct xattr_handler *h = erofs_xattr_handler(entry->e_name_index); - if (h == NULL || (h->list != NULL && !h->list(it->dentry))) + if (!h || (h->list && !h->list(it->dentry))) return 1; prefix = xattr_prefix(h); prefix_len = strlen(prefix); - if (it->buffer == NULL) { + if (!it->buffer) { it->buffer_ofs += prefix_len + entry->e_name_len + 1; return 1; } @@ -558,7 +560,7 @@ static int xattr_entrylist(struct xattr_iter *_it, } static int xattr_namelist(struct xattr_iter *_it, - unsigned int processed, char *buf, unsigned int len) + unsigned int processed, char *buf, unsigned int len) { struct listxattr_iter *it = container_of(_it, struct listxattr_iter, it); @@ -569,7 +571,7 @@ static int xattr_namelist(struct xattr_iter *_it, } static int xattr_skipvalue(struct xattr_iter *_it, - unsigned int value_sz) + unsigned int value_sz) { struct listxattr_iter *it = container_of(_it, struct listxattr_iter, it); @@ -641,7 +643,7 @@ static int shared_listxattr(struct listxattr_iter *it) } ssize_t erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) + char *buffer, size_t buffer_size) { int ret; struct listxattr_iter it; |