aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/erofs
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/erofs')
-rw-r--r--drivers/staging/erofs/Documentation/filesystems/erofs.txt1
-rw-r--r--drivers/staging/erofs/data.c23
-rw-r--r--drivers/staging/erofs/dir.c45
-rw-r--r--drivers/staging/erofs/inode.c18
-rw-r--r--drivers/staging/erofs/internal.h19
-rw-r--r--drivers/staging/erofs/namei.c3
-rw-r--r--drivers/staging/erofs/super.c56
-rw-r--r--drivers/staging/erofs/unzip_pagevec.h6
-rw-r--r--drivers/staging/erofs/unzip_vle.c142
-rw-r--r--drivers/staging/erofs/unzip_vle_lz4.c7
-rw-r--r--drivers/staging/erofs/utils.c4
-rw-r--r--drivers/staging/erofs/xattr.c50
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;