From nobody Wed Jul 1 05:28:18 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF696C433F5 for ; Wed, 29 Dec 2021 04:14:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238655AbhL2EOU (ORCPT ); Tue, 28 Dec 2021 23:14:20 -0500 Received: from out4436.biz.mail.alibaba.com ([47.88.44.36]:38932 "EHLO out4436.biz.mail.alibaba.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238641AbhL2EOS (ORCPT ); Tue, 28 Dec 2021 23:14:18 -0500 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R211e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04400;MF=hsiangkao@linux.alibaba.com;NM=1;PH=DS;RN=5;SR=0;TI=SMTPD_---0V0Bi34J_1640751246; Received: from e18g06460.et15sqa.tbsite.net(mailfrom:hsiangkao@linux.alibaba.com fp:SMTPD_---0V0Bi34J_1640751246) by smtp.aliyun-inc.com(127.0.0.1); Wed, 29 Dec 2021 12:14:16 +0800 From: Gao Xiang To: linux-erofs@lists.ozlabs.org, Chao Yu , Liu Bo Cc: LKML , Gao Xiang Subject: [PATCH 1/5] erofs: introduce meta buffer operations Date: Wed, 29 Dec 2021 12:14:01 +0800 Message-Id: <20211229041405.45921-2-hsiangkao@linux.alibaba.com> X-Mailer: git-send-email 2.24.4 In-Reply-To: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> References: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" In order to support subpage and folio for all uncompressed files, introduce meta buffer descriptors, which can be effectively stored on stack, in place of meta page operations. This converts the uncompressed data path to meta buffers. Signed-off-by: Gao Xiang --- fs/erofs/data.c | 97 +++++++++++++++++++++++++++++++++++---------- fs/erofs/internal.h | 13 ++++++ 2 files changed, 89 insertions(+), 21 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 4f98c76ec043..6495e16a50a9 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -22,6 +22,56 @@ struct page *erofs_get_meta_page(struct super_block *sb,= erofs_blk_t blkaddr) return page; } =20 +void erofs_unmap_metabuf(struct erofs_buf *buf) +{ + if (buf->kmap_type =3D=3D EROFS_KMAP) + kunmap(buf->page); + else if (buf->kmap_type =3D=3D EROFS_KMAP_ATOMIC) + kunmap_atomic(buf->base); + buf->kmap_type =3D EROFS_NO_KMAP; +} + +void erofs_put_metabuf(struct erofs_buf *buf) +{ + if (!buf->page) + return; + erofs_unmap_metabuf(buf); + put_page(buf->page); + buf->page =3D NULL; +} + +void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, + erofs_blk_t blkaddr, enum erofs_kmap_type type) +{ + struct address_space *const mapping =3D sb->s_bdev->bd_inode->i_mapping; + erofs_off_t offset =3D blknr_to_addr(blkaddr); + pgoff_t index =3D offset >> PAGE_SHIFT; + struct page *page =3D buf->page; + + if (!page || page->index !=3D index) { + erofs_put_metabuf(buf); + page =3D read_cache_page_gfp(mapping, index, + mapping_gfp_constraint(mapping, ~__GFP_FS)); + if (IS_ERR(page)) + return page; + /* should already be PageUptodate, no need to lock page */ + buf->page =3D page; + } + if (buf->kmap_type =3D=3D EROFS_NO_KMAP) { + if (type =3D=3D EROFS_KMAP) + buf->base =3D kmap(page); + else if (type =3D=3D EROFS_KMAP_ATOMIC) + buf->base =3D kmap_atomic(page); + buf->kmap_type =3D type; + } else if (buf->kmap_type !=3D type) { + DBG_BUGON(1); + return ERR_PTR(-EFAULT); + } + if (type =3D=3D EROFS_NO_KMAP) + return NULL; + return buf->base + (offset & ~PAGE_MASK); +} + static int erofs_map_blocks_flatmode(struct inode *inode, struct erofs_map_blocks *map, int flags) @@ -31,7 +81,7 @@ static int erofs_map_blocks_flatmode(struct inode *inode, struct erofs_inode *vi =3D EROFS_I(inode); bool tailendpacking =3D (vi->datalayout =3D=3D EROFS_INODE_FLAT_INLINE); =20 - nblocks =3D DIV_ROUND_UP(inode->i_size, PAGE_SIZE); + nblocks =3D DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); lastblk =3D nblocks - tailendpacking; =20 /* there is no hole in flatmode */ @@ -72,10 +122,11 @@ static int erofs_map_blocks(struct inode *inode, struct super_block *sb =3D inode->i_sb; struct erofs_inode *vi =3D EROFS_I(inode); struct erofs_inode_chunk_index *idx; - struct page *page; + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; u64 chunknr; unsigned int unit; erofs_off_t pos; + void *kaddr; int err =3D 0; =20 trace_erofs_map_blocks_enter(inode, map, flags); @@ -101,9 +152,9 @@ static int erofs_map_blocks(struct inode *inode, pos =3D ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + vi->xattr_isize, unit) + unit * chunknr; =20 - page =3D erofs_get_meta_page(inode->i_sb, erofs_blknr(pos)); - if (IS_ERR(page)) { - err =3D PTR_ERR(page); + kaddr =3D erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP); + if (IS_ERR(kaddr)) { + err =3D PTR_ERR(kaddr); goto out; } map->m_la =3D chunknr << vi->chunkbits; @@ -112,7 +163,7 @@ static int erofs_map_blocks(struct inode *inode, =20 /* handle block map */ if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) { - __le32 *blkaddr =3D page_address(page) + erofs_blkoff(pos); + __le32 *blkaddr =3D kaddr + erofs_blkoff(pos); =20 if (le32_to_cpu(*blkaddr) =3D=3D EROFS_NULL_ADDR) { map->m_flags =3D 0; @@ -123,7 +174,7 @@ static int erofs_map_blocks(struct inode *inode, goto out_unlock; } /* parse chunk indexes */ - idx =3D page_address(page) + erofs_blkoff(pos); + idx =3D kaddr + erofs_blkoff(pos); switch (le32_to_cpu(idx->blkaddr)) { case EROFS_NULL_ADDR: map->m_flags =3D 0; @@ -136,8 +187,7 @@ static int erofs_map_blocks(struct inode *inode, break; } out_unlock: - unlock_page(page); - put_page(page); + erofs_put_metabuf(&buf); out: if (!err) map->m_llen =3D map->m_plen; @@ -226,16 +276,16 @@ static int erofs_iomap_begin(struct inode *inode, lof= f_t offset, loff_t length, } =20 if (map.m_flags & EROFS_MAP_META) { - struct page *ipage; + void *ptr; + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; =20 iomap->type =3D IOMAP_INLINE; - ipage =3D erofs_get_meta_page(inode->i_sb, - erofs_blknr(mdev.m_pa)); - if (IS_ERR(ipage)) - return PTR_ERR(ipage); - iomap->inline_data =3D page_address(ipage) + - erofs_blkoff(mdev.m_pa); - iomap->private =3D ipage; + ptr =3D erofs_read_metabuf(&buf, inode->i_sb, + erofs_blknr(mdev.m_pa), EROFS_KMAP); + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + iomap->inline_data =3D ptr + erofs_blkoff(mdev.m_pa); + iomap->private =3D buf.base; } else { iomap->type =3D IOMAP_MAPPED; iomap->addr =3D mdev.m_pa; @@ -246,12 +296,17 @@ static int erofs_iomap_begin(struct inode *inode, lof= f_t offset, loff_t length, static int erofs_iomap_end(struct inode *inode, loff_t pos, loff_t length, ssize_t written, unsigned int flags, struct iomap *iomap) { - struct page *ipage =3D iomap->private; + void *ptr =3D iomap->private; + + if (ptr) { + struct erofs_buf buf =3D { + .page =3D kmap_to_page(ptr), + .base =3D ptr, + .kmap_type =3D EROFS_KMAP, + }; =20 - if (ipage) { DBG_BUGON(iomap->type !=3D IOMAP_INLINE); - unlock_page(ipage); - put_page(ipage); + erofs_put_metabuf(&buf); } else { DBG_BUGON(iomap->type =3D=3D IOMAP_INLINE); } diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index fca3747d97be..7053f1c4171d 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -251,6 +251,19 @@ static inline int erofs_wait_on_workgroup_freezed(stru= ct erofs_workgroup *grp) #error erofs cannot be used in this platform #endif =20 +enum erofs_kmap_type { + EROFS_NO_KMAP, /* don't map the buffer */ + EROFS_KMAP, /* use kmap() to map the buffer */ + EROFS_KMAP_ATOMIC, /* use kmap_atomic() to map the buffer */ +}; + +struct erofs_buf { + struct page *page; + void *base; + enum erofs_kmap_type kmap_type; +}; +#define __EROFS_BUF_INITIALIZER ((struct erofs_buf){ .page =3D NULL }) + #define ROOT_NID(sb) ((sb)->root_nid) =20 #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) --=20 2.24.4 From nobody Wed Jul 1 05:28:18 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03798C433FE for ; Wed, 29 Dec 2021 04:14:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238664AbhL2EOV (ORCPT ); Tue, 28 Dec 2021 23:14:21 -0500 Received: from out30-131.freemail.mail.aliyun.com ([115.124.30.131]:48361 "EHLO out30-131.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238645AbhL2EOT (ORCPT ); Tue, 28 Dec 2021 23:14:19 -0500 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R851e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04426;MF=hsiangkao@linux.alibaba.com;NM=1;PH=DS;RN=5;SR=0;TI=SMTPD_---0V0Bi34J_1640751246; Received: from e18g06460.et15sqa.tbsite.net(mailfrom:hsiangkao@linux.alibaba.com fp:SMTPD_---0V0Bi34J_1640751246) by smtp.aliyun-inc.com(127.0.0.1); Wed, 29 Dec 2021 12:14:17 +0800 From: Gao Xiang To: linux-erofs@lists.ozlabs.org, Chao Yu , Liu Bo Cc: LKML , Gao Xiang Subject: [PATCH 2/5] erofs: use meta buffers for inode operations Date: Wed, 29 Dec 2021 12:14:02 +0800 Message-Id: <20211229041405.45921-3-hsiangkao@linux.alibaba.com> X-Mailer: git-send-email 2.24.4 In-Reply-To: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> References: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Get rid of old erofs_get_meta_page() within inode operations by using on-stack meta buffers in order to prepare subpage and folio features. Signed-off-by: Gao Xiang Reviewed-by: Yue Hu --- fs/erofs/inode.c | 68 +++++++++++++++++++++------------------------ fs/erofs/internal.h | 3 ++ 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 2345f1de438e..ff62f84f47d3 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -13,8 +13,8 @@ * the inode payload page if it's an extended inode) in order to fill * inline data if possible. */ -static struct page *erofs_read_inode(struct inode *inode, - unsigned int *ofs) +static void *erofs_read_inode(struct erofs_buf *buf, + struct inode *inode, unsigned int *ofs) { struct super_block *sb =3D inode->i_sb; struct erofs_sb_info *sbi =3D EROFS_SB(sb); @@ -22,7 +22,7 @@ static struct page *erofs_read_inode(struct inode *inode, const erofs_off_t inode_loc =3D iloc(sbi, vi->nid); =20 erofs_blk_t blkaddr, nblks =3D 0; - struct page *page; + void *kaddr; struct erofs_inode_compact *dic; struct erofs_inode_extended *die, *copied =3D NULL; unsigned int ifmt; @@ -34,14 +34,14 @@ static struct page *erofs_read_inode(struct inode *inod= e, erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u", __func__, vi->nid, *ofs, blkaddr); =20 - page =3D erofs_get_meta_page(sb, blkaddr); - if (IS_ERR(page)) { + kaddr =3D erofs_read_metabuf(buf, sb, blkaddr, EROFS_KMAP); + if (IS_ERR(kaddr)) { erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld", - vi->nid, PTR_ERR(page)); - return page; + vi->nid, PTR_ERR(kaddr)); + return kaddr; } =20 - dic =3D page_address(page) + *ofs; + dic =3D kaddr + *ofs; ifmt =3D le16_to_cpu(dic->i_format); =20 if (ifmt & ~EROFS_I_ALL) { @@ -62,12 +62,12 @@ static struct page *erofs_read_inode(struct inode *inod= e, switch (erofs_inode_version(ifmt)) { case EROFS_INODE_LAYOUT_EXTENDED: vi->inode_isize =3D sizeof(struct erofs_inode_extended); - /* check if the inode acrosses page boundary */ - if (*ofs + vi->inode_isize <=3D PAGE_SIZE) { + /* check if the extended inode acrosses block boundary */ + if (*ofs + vi->inode_isize <=3D EROFS_BLKSIZ) { *ofs +=3D vi->inode_isize; die =3D (struct erofs_inode_extended *)dic; } else { - const unsigned int gotten =3D PAGE_SIZE - *ofs; + const unsigned int gotten =3D EROFS_BLKSIZ - *ofs; =20 copied =3D kmalloc(vi->inode_isize, GFP_NOFS); if (!copied) { @@ -75,18 +75,16 @@ static struct page *erofs_read_inode(struct inode *inod= e, goto err_out; } memcpy(copied, dic, gotten); - unlock_page(page); - put_page(page); - - page =3D erofs_get_meta_page(sb, blkaddr + 1); - if (IS_ERR(page)) { - erofs_err(sb, "failed to get inode payload page (nid: %llu), err %ld", - vi->nid, PTR_ERR(page)); + kaddr =3D erofs_read_metabuf(buf, sb, blkaddr + 1, + EROFS_KMAP); + if (IS_ERR(kaddr)) { + erofs_err(sb, "failed to get inode payload block (nid: %llu), err %ld", + vi->nid, PTR_ERR(kaddr)); kfree(copied); - return page; + return kaddr; } *ofs =3D vi->inode_isize - gotten; - memcpy((u8 *)copied + gotten, page_address(page), *ofs); + memcpy((u8 *)copied + gotten, kaddr, *ofs); die =3D copied; } vi->xattr_isize =3D erofs_xattr_ibody_size(die->i_xattr_icount); @@ -200,7 +198,7 @@ static struct page *erofs_read_inode(struct inode *inod= e, inode->i_blocks =3D roundup(inode->i_size, EROFS_BLKSIZ) >> 9; else inode->i_blocks =3D nblks << LOG_SECTORS_PER_BLOCK; - return page; + return kaddr; =20 bogusimode: erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu", @@ -209,12 +207,11 @@ static struct page *erofs_read_inode(struct inode *in= ode, err_out: DBG_BUGON(1); kfree(copied); - unlock_page(page); - put_page(page); + erofs_put_metabuf(buf); return ERR_PTR(err); } =20 -static int erofs_fill_symlink(struct inode *inode, void *data, +static int erofs_fill_symlink(struct inode *inode, void *kaddr, unsigned int m_pofs) { struct erofs_inode *vi =3D EROFS_I(inode); @@ -222,7 +219,7 @@ static int erofs_fill_symlink(struct inode *inode, void= *data, =20 /* if it cannot be handled with fast symlink scheme */ if (vi->datalayout !=3D EROFS_INODE_FLAT_INLINE || - inode->i_size >=3D PAGE_SIZE) { + inode->i_size >=3D EROFS_BLKSIZ) { inode->i_op =3D &erofs_symlink_iops; return 0; } @@ -232,8 +229,8 @@ static int erofs_fill_symlink(struct inode *inode, void= *data, return -ENOMEM; =20 m_pofs +=3D vi->xattr_isize; - /* inline symlink data shouldn't cross page boundary as well */ - if (m_pofs + inode->i_size > PAGE_SIZE) { + /* inline symlink data shouldn't cross block boundary */ + if (m_pofs + inode->i_size > EROFS_BLKSIZ) { kfree(lnk); erofs_err(inode->i_sb, "inline data cross block boundary @ nid %llu", @@ -241,8 +238,7 @@ static int erofs_fill_symlink(struct inode *inode, void= *data, DBG_BUGON(1); return -EFSCORRUPTED; } - - memcpy(lnk, data + m_pofs, inode->i_size); + memcpy(lnk, kaddr + m_pofs, inode->i_size); lnk[inode->i_size] =3D '\0'; =20 inode->i_link =3D lnk; @@ -253,16 +249,17 @@ static int erofs_fill_symlink(struct inode *inode, vo= id *data, static int erofs_fill_inode(struct inode *inode, int isdir) { struct erofs_inode *vi =3D EROFS_I(inode); - struct page *page; + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; + void *kaddr; unsigned int ofs; int err =3D 0; =20 trace_erofs_fill_inode(inode, isdir); =20 /* read inode base data from disk */ - page =3D erofs_read_inode(inode, &ofs); - if (IS_ERR(page)) - return PTR_ERR(page); + kaddr =3D erofs_read_inode(&buf, inode, &ofs); + if (IS_ERR(kaddr)) + return PTR_ERR(kaddr); =20 /* setup the new inode */ switch (inode->i_mode & S_IFMT) { @@ -278,7 +275,7 @@ static int erofs_fill_inode(struct inode *inode, int is= dir) inode->i_fop =3D &erofs_dir_fops; break; case S_IFLNK: - err =3D erofs_fill_symlink(inode, page_address(page), ofs); + err =3D erofs_fill_symlink(inode, kaddr, ofs); if (err) goto out_unlock; inode_nohighmem(inode); @@ -302,8 +299,7 @@ static int erofs_fill_inode(struct inode *inode, int is= dir) inode->i_mapping->a_ops =3D &erofs_raw_access_aops; =20 out_unlock: - unlock_page(page); - put_page(page); + erofs_put_metabuf(&buf); return err; } =20 diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 7053f1c4171d..f1e4eb3025f6 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -475,6 +475,9 @@ struct erofs_map_dev { /* data.c */ extern const struct file_operations erofs_file_fops; struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkad= dr); +void erofs_put_metabuf(struct erofs_buf *buf); +void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, + erofs_blk_t blkaddr, enum erofs_kmap_type type); int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev); int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len); --=20 2.24.4 From nobody Wed Jul 1 05:28:18 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3A33C433EF for ; Wed, 29 Dec 2021 04:14:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238674AbhL2EOX (ORCPT ); Tue, 28 Dec 2021 23:14:23 -0500 Received: from out30-133.freemail.mail.aliyun.com ([115.124.30.133]:57322 "EHLO out30-133.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238648AbhL2EOU (ORCPT ); Tue, 28 Dec 2021 23:14:20 -0500 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R911e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04357;MF=hsiangkao@linux.alibaba.com;NM=1;PH=DS;RN=5;SR=0;TI=SMTPD_---0V0Bi34J_1640751246; Received: from e18g06460.et15sqa.tbsite.net(mailfrom:hsiangkao@linux.alibaba.com fp:SMTPD_---0V0Bi34J_1640751246) by smtp.aliyun-inc.com(127.0.0.1); Wed, 29 Dec 2021 12:14:18 +0800 From: Gao Xiang To: linux-erofs@lists.ozlabs.org, Chao Yu , Liu Bo Cc: LKML , Gao Xiang Subject: [PATCH 3/5] erofs: use meta buffers for super operations Date: Wed, 29 Dec 2021 12:14:03 +0800 Message-Id: <20211229041405.45921-4-hsiangkao@linux.alibaba.com> X-Mailer: git-send-email 2.24.4 In-Reply-To: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> References: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Get rid of old erofs_get_meta_page() within super operations by using on-stack meta buffers in order to prepare subpage and folio features. Signed-off-by: Gao Xiang --- fs/erofs/super.c | 105 ++++++++++++----------------------------------- 1 file changed, 26 insertions(+), 79 deletions(-) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 0724ad5fd6cf..38305fa2969b 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2017-2018 HUAWEI, Inc. * https://www.huawei.com/ + * Copyright (C) 2021, Alibaba Cloud */ #include #include @@ -124,80 +125,48 @@ static bool check_layout_compatibility(struct super_b= lock *sb, =20 #ifdef CONFIG_EROFS_FS_ZIP /* read variable-sized metadata, offset will be aligned by 4-byte */ -static void *erofs_read_metadata(struct super_block *sb, struct page **pag= ep, +static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf = *buf, erofs_off_t *offset, int *lengthp) { - struct page *page =3D *pagep; u8 *buffer, *ptr; int len, i, cnt; - erofs_blk_t blk; =20 *offset =3D round_up(*offset, 4); - blk =3D erofs_blknr(*offset); + ptr =3D erofs_read_metabuf(buf, sb, erofs_blknr(*offset), EROFS_KMAP); + if (IS_ERR(ptr)) + return ptr; =20 - if (!page || page->index !=3D blk) { - if (page) { - unlock_page(page); - put_page(page); - } - page =3D erofs_get_meta_page(sb, blk); - if (IS_ERR(page)) - goto err_nullpage; - } - - ptr =3D kmap(page); len =3D le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(*offset)]); if (!len) len =3D U16_MAX + 1; buffer =3D kmalloc(len, GFP_KERNEL); - if (!buffer) { - buffer =3D ERR_PTR(-ENOMEM); - goto out; - } + if (!buffer) + return ERR_PTR(-ENOMEM); *offset +=3D sizeof(__le16); *lengthp =3D len; =20 for (i =3D 0; i < len; i +=3D cnt) { cnt =3D min(EROFS_BLKSIZ - (int)erofs_blkoff(*offset), len - i); - blk =3D erofs_blknr(*offset); - - if (!page || page->index !=3D blk) { - if (page) { - kunmap(page); - unlock_page(page); - put_page(page); - } - page =3D erofs_get_meta_page(sb, blk); - if (IS_ERR(page)) { - kfree(buffer); - goto err_nullpage; - } - ptr =3D kmap(page); - } + ptr =3D erofs_read_metabuf(buf, sb, erofs_blknr(*offset), + EROFS_KMAP); + if (IS_ERR(ptr)) + return ptr; memcpy(buffer + i, ptr + erofs_blkoff(*offset), cnt); *offset +=3D cnt; } -out: - kunmap(page); - *pagep =3D page; return buffer; -err_nullpage: - *pagep =3D NULL; - return page; } =20 static int erofs_load_compr_cfgs(struct super_block *sb, struct erofs_super_block *dsb) { - struct erofs_sb_info *sbi; - struct page *page; + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; unsigned int algs, alg; erofs_off_t offset; - int size, ret; + int size, ret =3D 0; =20 - sbi =3D EROFS_SB(sb); sbi->available_compr_algs =3D le16_to_cpu(dsb->u1.available_compr_algs); - if (sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS) { erofs_err(sb, "try to load compressed fs with unsupported algorithms %x", sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS); @@ -205,21 +174,16 @@ static int erofs_load_compr_cfgs(struct super_block *= sb, } =20 offset =3D EROFS_SUPER_OFFSET + sbi->sb_size; - page =3D NULL; alg =3D 0; - ret =3D 0; - for (algs =3D sbi->available_compr_algs; algs; algs >>=3D 1, ++alg) { void *data; =20 if (!(algs & 1)) continue; =20 - data =3D erofs_read_metadata(sb, &page, &offset, &size); - if (IS_ERR(data)) { - ret =3D PTR_ERR(data); - goto err; - } + data =3D erofs_read_metadata(sb, &buf, &offset, &size); + if (IS_ERR(data)) + return PTR_ERR(data); =20 switch (alg) { case Z_EROFS_COMPRESSION_LZ4: @@ -234,13 +198,9 @@ static int erofs_load_compr_cfgs(struct super_block *s= b, } kfree(data); if (ret) - goto err; - } -err: - if (page) { - unlock_page(page); - put_page(page); + break; } + erofs_put_metabuf(&buf); return ret; } #else @@ -261,7 +221,7 @@ static int erofs_init_devices(struct super_block *sb, struct erofs_sb_info *sbi =3D EROFS_SB(sb); unsigned int ondisk_extradevs; erofs_off_t pos; - struct page *page =3D NULL; + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; struct erofs_device_info *dif; struct erofs_deviceslot *dis; void *ptr; @@ -285,22 +245,13 @@ static int erofs_init_devices(struct super_block *sb, pos =3D le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE; down_read(&sbi->devs->rwsem); idr_for_each_entry(&sbi->devs->tree, dif, id) { - erofs_blk_t blk =3D erofs_blknr(pos); struct block_device *bdev; =20 - if (!page || page->index !=3D blk) { - if (page) { - kunmap(page); - unlock_page(page); - put_page(page); - } - - page =3D erofs_get_meta_page(sb, blk); - if (IS_ERR(page)) { - up_read(&sbi->devs->rwsem); - return PTR_ERR(page); - } - ptr =3D kmap(page); + ptr =3D erofs_read_metabuf(&buf, sb, erofs_blknr(pos), + EROFS_KMAP); + if (IS_ERR(ptr)) { + up_read(&sbi->devs->rwsem); + return PTR_ERR(ptr); } dis =3D ptr + erofs_blkoff(pos); =20 @@ -320,11 +271,7 @@ static int erofs_init_devices(struct super_block *sb, } err_out: up_read(&sbi->devs->rwsem); - if (page) { - kunmap(page); - unlock_page(page); - put_page(page); - } + erofs_put_metabuf(&buf); return err; } =20 --=20 2.24.4 From nobody Wed Jul 1 05:28:18 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C232CC433FE for ; Wed, 29 Dec 2021 04:14:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238686AbhL2EOZ (ORCPT ); Tue, 28 Dec 2021 23:14:25 -0500 Received: from out30-133.freemail.mail.aliyun.com ([115.124.30.133]:50508 "EHLO out30-133.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238641AbhL2EOV (ORCPT ); Tue, 28 Dec 2021 23:14:21 -0500 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R171e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04400;MF=hsiangkao@linux.alibaba.com;NM=1;PH=DS;RN=5;SR=0;TI=SMTPD_---0V0Bi34J_1640751246; Received: from e18g06460.et15sqa.tbsite.net(mailfrom:hsiangkao@linux.alibaba.com fp:SMTPD_---0V0Bi34J_1640751246) by smtp.aliyun-inc.com(127.0.0.1); Wed, 29 Dec 2021 12:14:19 +0800 From: Gao Xiang To: linux-erofs@lists.ozlabs.org, Chao Yu , Liu Bo Cc: LKML , Gao Xiang Subject: [PATCH 4/5] erofs: use meta buffers for xattr operations Date: Wed, 29 Dec 2021 12:14:04 +0800 Message-Id: <20211229041405.45921-5-hsiangkao@linux.alibaba.com> X-Mailer: git-send-email 2.24.4 In-Reply-To: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> References: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Get rid of old erofs_get_meta_page() within xattr operations by using on-stack meta buffers in order to prepare subpage and folio features. Signed-off-by: Gao Xiang --- fs/erofs/xattr.c | 123 ++++++++++++++--------------------------------- 1 file changed, 37 insertions(+), 86 deletions(-) diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 01c581e93c5f..539c2aec20d3 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -8,33 +8,13 @@ =20 struct xattr_iter { struct super_block *sb; - struct page *page; + struct erofs_buf buf; void *kaddr; =20 erofs_blk_t blkaddr; unsigned int ofs; }; =20 -static inline void xattr_iter_end(struct xattr_iter *it, bool atomic) -{ - /* the only user of kunmap() is 'init_inode_xattrs' */ - if (!atomic) - kunmap(it->page); - else - kunmap_atomic(it->kaddr); - - unlock_page(it->page); - put_page(it->page); -} - -static inline void xattr_iter_end_final(struct xattr_iter *it) -{ - if (!it->page) - return; - - xattr_iter_end(it, true); -} - static int init_inode_xattrs(struct inode *inode) { struct erofs_inode *const vi =3D EROFS_I(inode); @@ -43,7 +23,6 @@ static int init_inode_xattrs(struct inode *inode) struct erofs_xattr_ibody_header *ih; struct super_block *sb; struct erofs_sb_info *sbi; - bool atomic_map; int ret =3D 0; =20 /* the most case is that xattrs of this inode are initialized. */ @@ -91,26 +70,23 @@ static int init_inode_xattrs(struct inode *inode) =20 sb =3D inode->i_sb; sbi =3D EROFS_SB(sb); + it.buf =3D __EROFS_BUF_INITIALIZER; it.blkaddr =3D erofs_blknr(iloc(sbi, vi->nid) + vi->inode_isize); it.ofs =3D erofs_blkoff(iloc(sbi, vi->nid) + vi->inode_isize); =20 - it.page =3D erofs_get_meta_page(sb, it.blkaddr); - if (IS_ERR(it.page)) { - ret =3D PTR_ERR(it.page); + /* read in shared xattr array (non-atomic, see kmalloc below) */ + it.kaddr =3D erofs_read_metabuf(&it.buf, sb, it.blkaddr, EROFS_KMAP); + if (IS_ERR(it.kaddr)) { + ret =3D PTR_ERR(it.kaddr); goto out_unlock; } =20 - /* read in shared xattr array (non-atomic, see kmalloc below) */ - it.kaddr =3D kmap(it.page); - atomic_map =3D false; - ih =3D (struct erofs_xattr_ibody_header *)(it.kaddr + it.ofs); - vi->xattr_shared_count =3D ih->h_shared_count; vi->xattr_shared_xattrs =3D kmalloc_array(vi->xattr_shared_count, sizeof(uint), GFP_KERNEL); if (!vi->xattr_shared_xattrs) { - xattr_iter_end(&it, atomic_map); + erofs_put_metabuf(&it.buf); ret =3D -ENOMEM; goto out_unlock; } @@ -122,25 +98,22 @@ static int init_inode_xattrs(struct inode *inode) if (it.ofs >=3D EROFS_BLKSIZ) { /* cannot be unaligned */ DBG_BUGON(it.ofs !=3D EROFS_BLKSIZ); - xattr_iter_end(&it, atomic_map); =20 - it.page =3D erofs_get_meta_page(sb, ++it.blkaddr); - if (IS_ERR(it.page)) { + it.kaddr =3D erofs_read_metabuf(&it.buf, sb, ++it.blkaddr, + EROFS_KMAP); + if (IS_ERR(it.kaddr)) { kfree(vi->xattr_shared_xattrs); vi->xattr_shared_xattrs =3D NULL; - ret =3D PTR_ERR(it.page); + ret =3D PTR_ERR(it.kaddr); goto out_unlock; } - - it.kaddr =3D kmap_atomic(it.page); - atomic_map =3D true; it.ofs =3D 0; } vi->xattr_shared_xattrs[i] =3D le32_to_cpu(*(__le32 *)(it.kaddr + it.ofs)); it.ofs +=3D sizeof(__le32); } - xattr_iter_end(&it, atomic_map); + erofs_put_metabuf(&it.buf); =20 /* paired with smp_mb() at the beginning of the function. */ smp_mb(); @@ -172,19 +145,11 @@ static inline int xattr_iter_fixup(struct xattr_iter = *it) if (it->ofs < EROFS_BLKSIZ) return 0; =20 - xattr_iter_end(it, true); - it->blkaddr +=3D erofs_blknr(it->ofs); - - it->page =3D erofs_get_meta_page(it->sb, it->blkaddr); - if (IS_ERR(it->page)) { - int err =3D PTR_ERR(it->page); - - it->page =3D NULL; - return err; - } - - it->kaddr =3D kmap_atomic(it->page); + it->kaddr =3D erofs_read_metabuf(&it->buf, it->sb, it->blkaddr, + EROFS_KMAP_ATOMIC); + if (IS_ERR(it->kaddr)) + return PTR_ERR(it->kaddr); it->ofs =3D erofs_blkoff(it->ofs); return 0; } @@ -207,11 +172,10 @@ static int inline_xattr_iter_begin(struct xattr_iter = *it, it->blkaddr =3D erofs_blknr(iloc(sbi, vi->nid) + inline_xattr_ofs); it->ofs =3D erofs_blkoff(iloc(sbi, vi->nid) + inline_xattr_ofs); =20 - it->page =3D erofs_get_meta_page(inode->i_sb, it->blkaddr); - if (IS_ERR(it->page)) - return PTR_ERR(it->page); - - it->kaddr =3D kmap_atomic(it->page); + it->kaddr =3D erofs_read_metabuf(&it->buf, inode->i_sb, it->blkaddr, + EROFS_KMAP_ATOMIC); + if (IS_ERR(it->kaddr)) + return PTR_ERR(it->kaddr); return vi->xattr_isize - xattr_header_sz; } =20 @@ -272,7 +236,7 @@ static int xattr_foreach(struct xattr_iter *it, it->ofs =3D 0; } =20 - slice =3D min_t(unsigned int, PAGE_SIZE - it->ofs, + slice =3D min_t(unsigned int, EROFS_BLKSIZ - it->ofs, entry.e_name_len - processed); =20 /* handle name */ @@ -307,7 +271,7 @@ static int xattr_foreach(struct xattr_iter *it, it->ofs =3D 0; } =20 - slice =3D min_t(unsigned int, PAGE_SIZE - it->ofs, + slice =3D min_t(unsigned int, EROFS_BLKSIZ - it->ofs, value_sz - processed); op->value(it, processed, it->kaddr + it->ofs, slice); it->ofs +=3D slice; @@ -386,8 +350,6 @@ static int inline_getxattr(struct inode *inode, struct = getxattr_iter *it) if (ret !=3D -ENOATTR) break; } - xattr_iter_end_final(&it->it); - return ret ? ret : it->buffer_size; } =20 @@ -405,15 +367,11 @@ static int shared_getxattr(struct inode *inode, struc= t getxattr_iter *it) =20 it->it.ofs =3D xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]); =20 - if (!i || blkaddr !=3D it->it.blkaddr) { - if (i) - xattr_iter_end(&it->it, true); - - it->it.page =3D erofs_get_meta_page(sb, blkaddr); - if (IS_ERR(it->it.page)) - return PTR_ERR(it->it.page); - - it->it.kaddr =3D kmap_atomic(it->it.page); + if (blkaddr !=3D it->it.blkaddr) { + it->it.kaddr =3D erofs_read_metabuf(&it->it.buf, sb, + blkaddr, EROFS_KMAP_ATOMIC); + if (IS_ERR(it->it.kaddr)) + return PTR_ERR(it->it.kaddr); it->it.blkaddr =3D blkaddr; } =20 @@ -421,9 +379,6 @@ static int shared_getxattr(struct inode *inode, struct = getxattr_iter *it) if (ret !=3D -ENOATTR) break; } - if (vi->xattr_shared_count) - xattr_iter_end_final(&it->it); - return ret ? ret : it->buffer_size; } =20 @@ -452,10 +407,11 @@ int erofs_getxattr(struct inode *inode, int index, return ret; =20 it.index =3D index; - it.name.len =3D strlen(name); if (it.name.len > EROFS_NAME_LEN) return -ERANGE; + + it.it.buf =3D __EROFS_BUF_INITIALIZER; it.name.name =3D name; =20 it.buffer =3D buffer; @@ -465,6 +421,7 @@ int erofs_getxattr(struct inode *inode, int index, ret =3D inline_getxattr(inode, &it); if (ret =3D=3D -ENOATTR) ret =3D shared_getxattr(inode, &it); + erofs_put_metabuf(&it.it.buf); return ret; } =20 @@ -607,7 +564,6 @@ static int inline_listxattr(struct listxattr_iter *it) if (ret) break; } - xattr_iter_end_final(&it->it); return ret ? ret : it->buffer_ofs; } =20 @@ -625,15 +581,11 @@ static int shared_listxattr(struct listxattr_iter *it) xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]); =20 it->it.ofs =3D xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]); - if (!i || blkaddr !=3D it->it.blkaddr) { - if (i) - xattr_iter_end(&it->it, true); - - it->it.page =3D erofs_get_meta_page(sb, blkaddr); - if (IS_ERR(it->it.page)) - return PTR_ERR(it->it.page); - - it->it.kaddr =3D kmap_atomic(it->it.page); + if (blkaddr !=3D it->it.blkaddr) { + it->it.kaddr =3D erofs_read_metabuf(&it->it.buf, sb, + blkaddr, EROFS_KMAP_ATOMIC); + if (IS_ERR(it->it.kaddr)) + return PTR_ERR(it->it.kaddr); it->it.blkaddr =3D blkaddr; } =20 @@ -641,9 +593,6 @@ static int shared_listxattr(struct listxattr_iter *it) if (ret) break; } - if (vi->xattr_shared_count) - xattr_iter_end_final(&it->it); - return ret ? ret : it->buffer_ofs; } =20 @@ -659,6 +608,7 @@ ssize_t erofs_listxattr(struct dentry *dentry, if (ret) return ret; =20 + it.it.buf =3D __EROFS_BUF_INITIALIZER; it.dentry =3D dentry; it.buffer =3D buffer; it.buffer_size =3D buffer_size; @@ -669,6 +619,7 @@ ssize_t erofs_listxattr(struct dentry *dentry, ret =3D inline_listxattr(&it); if (ret < 0 && ret !=3D -ENOATTR) return ret; + erofs_put_metabuf(&it.it.buf); return shared_listxattr(&it); } =20 --=20 2.24.4 From nobody Wed Jul 1 05:28:18 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3AACC433F5 for ; Wed, 29 Dec 2021 04:14:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238695AbhL2EO1 (ORCPT ); Tue, 28 Dec 2021 23:14:27 -0500 Received: from out30-130.freemail.mail.aliyun.com ([115.124.30.130]:40428 "EHLO out30-130.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238665AbhL2EOW (ORCPT ); Tue, 28 Dec 2021 23:14:22 -0500 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R121e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04407;MF=hsiangkao@linux.alibaba.com;NM=1;PH=DS;RN=5;SR=0;TI=SMTPD_---0V0Bi34J_1640751246; Received: from e18g06460.et15sqa.tbsite.net(mailfrom:hsiangkao@linux.alibaba.com fp:SMTPD_---0V0Bi34J_1640751246) by smtp.aliyun-inc.com(127.0.0.1); Wed, 29 Dec 2021 12:14:20 +0800 From: Gao Xiang To: linux-erofs@lists.ozlabs.org, Chao Yu , Liu Bo Cc: LKML , Gao Xiang Subject: [PATCH 5/5] erofs: use meta buffers for zmap operations Date: Wed, 29 Dec 2021 12:14:05 +0800 Message-Id: <20211229041405.45921-6-hsiangkao@linux.alibaba.com> X-Mailer: git-send-email 2.24.4 In-Reply-To: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> References: <20211229041405.45921-1-hsiangkao@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Get rid of old erofs_get_meta_page() within zmap operations by using on-stack meta buffers in order to prepare subpage and folio features. Finally, erofs_get_meta_page() is useless. Get rid of it! Signed-off-by: Gao Xiang --- fs/erofs/data.c | 13 ----------- fs/erofs/internal.h | 6 ++--- fs/erofs/zdata.c | 23 ++++++++----------- fs/erofs/zmap.c | 56 +++++++++++++-------------------------------- 4 files changed, 28 insertions(+), 70 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 6495e16a50a9..187f19f8a9a1 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -9,19 +9,6 @@ #include #include =20 -struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkad= dr) -{ - struct address_space *const mapping =3D sb->s_bdev->bd_inode->i_mapping; - struct page *page; - - page =3D read_cache_page_gfp(mapping, blkaddr, - mapping_gfp_constraint(mapping, ~__GFP_FS)); - /* should already be PageUptodate */ - if (!IS_ERR(page)) - lock_page(page); - return page; -} - void erofs_unmap_metabuf(struct erofs_buf *buf) { if (buf->kmap_type =3D=3D EROFS_KMAP) diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index f1e4eb3025f6..3db494a398b2 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -419,14 +419,14 @@ enum { #define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped) =20 struct erofs_map_blocks { + struct erofs_buf buf; + erofs_off_t m_pa, m_la; u64 m_plen, m_llen; =20 unsigned short m_deviceid; char m_algorithmformat; unsigned int m_flags; - - struct page *mpage; }; =20 /* Flags used by erofs_map_blocks_flatmode() */ @@ -474,7 +474,7 @@ struct erofs_map_dev { =20 /* data.c */ extern const struct file_operations erofs_file_fops; -struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkad= dr); +void erofs_unmap_metabuf(struct erofs_buf *buf); void erofs_put_metabuf(struct erofs_buf *buf); void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, erofs_blk_t blkaddr, enum erofs_kmap_type type); diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 49da3931b2e3..498b7666efe8 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -698,20 +698,18 @@ static int z_erofs_do_read_page(struct z_erofs_decomp= ress_frontend *fe, goto err_out; =20 if (z_erofs_is_inline_pcluster(clt->pcl)) { - struct page *mpage; + void *mp; =20 - mpage =3D erofs_get_meta_page(inode->i_sb, - erofs_blknr(map->m_pa)); - if (IS_ERR(mpage)) { - err =3D PTR_ERR(mpage); + mp =3D erofs_read_metabuf(&fe->map.buf, inode->i_sb, + erofs_blknr(map->m_pa), EROFS_NO_KMAP); + if (IS_ERR(mp)) { + err =3D PTR_ERR(mp); erofs_err(inode->i_sb, "failed to get inline page, err %d", err); goto err_out; } - /* TODO: new subpage feature will get rid of it */ - unlock_page(mpage); - - WRITE_ONCE(clt->pcl->compressed_pages[0], mpage); + get_page(fe->map.buf.page); + WRITE_ONCE(clt->pcl->compressed_pages[0], fe->map.buf.page); clt->mode =3D COLLECT_PRIMARY_FOLLOWED_NOINPLACE; } else { /* preload all compressed pages (can change mode if needed) */ @@ -1529,9 +1527,7 @@ static int z_erofs_readpage(struct file *file, struct= page *page) if (err) erofs_err(inode->i_sb, "failed to read, err [%d]", err); =20 - if (f.map.mpage) - put_page(f.map.mpage); - + erofs_put_metabuf(&f.map.buf); erofs_release_pages(&pagepool); return err; } @@ -1576,8 +1572,7 @@ static void z_erofs_readahead(struct readahead_contro= l *rac) =20 z_erofs_runqueue(inode->i_sb, &f, &pagepool, z_erofs_get_sync_decompress_policy(sbi, nr_pages)); - if (f.map.mpage) - put_page(f.map.mpage); + erofs_put_metabuf(&f.map.buf); erofs_release_pages(&pagepool); } =20 diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index 1037ac17b7a6..18d7fd1a5064 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -35,7 +35,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode) struct super_block *const sb =3D inode->i_sb; int err, headnr; erofs_off_t pos; - struct page *page; + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; void *kaddr; struct z_erofs_map_header *h; =20 @@ -61,14 +61,13 @@ static int z_erofs_fill_inode_lazy(struct inode *inode) =20 pos =3D ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + vi->xattr_isize, 8); - page =3D erofs_get_meta_page(sb, erofs_blknr(pos)); - if (IS_ERR(page)) { - err =3D PTR_ERR(page); + kaddr =3D erofs_read_metabuf(&buf, sb, erofs_blknr(pos), + EROFS_KMAP_ATOMIC); + if (IS_ERR(kaddr)) { + err =3D PTR_ERR(kaddr); goto out_unlock; } =20 - kaddr =3D kmap_atomic(page); - h =3D kaddr + erofs_blkoff(pos); vi->z_advise =3D le16_to_cpu(h->h_advise); vi->z_algorithmtype[0] =3D h->h_algorithmtype & 15; @@ -101,20 +100,19 @@ static int z_erofs_fill_inode_lazy(struct inode *inod= e) goto unmap_done; } unmap_done: - kunmap_atomic(kaddr); - unlock_page(page); - put_page(page); + erofs_put_metabuf(&buf); if (err) goto out_unlock; =20 if (vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER) { - struct erofs_map_blocks map =3D { .mpage =3D NULL }; + struct erofs_map_blocks map =3D { + .buf =3D __EROFS_BUF_INITIALIZER + }; =20 vi->z_idata_size =3D le16_to_cpu(h->h_idata_size); err =3D z_erofs_do_map_blocks(inode, &map, EROFS_GET_BLOCKS_FINDTAIL); - if (map.mpage) - put_page(map.mpage); + erofs_put_metabuf(&map.buf); =20 if (!map.m_plen || erofs_blkoff(map.m_pa) + map.m_plen > EROFS_BLKSIZ) { @@ -151,31 +149,11 @@ static int z_erofs_reload_indexes(struct z_erofs_mapr= ecorder *m, erofs_blk_t eblk) { struct super_block *const sb =3D m->inode->i_sb; - struct erofs_map_blocks *const map =3D m->map; - struct page *mpage =3D map->mpage; - - if (mpage) { - if (mpage->index =3D=3D eblk) { - if (!m->kaddr) - m->kaddr =3D kmap_atomic(mpage); - return 0; - } =20 - if (m->kaddr) { - kunmap_atomic(m->kaddr); - m->kaddr =3D NULL; - } - put_page(mpage); - } - - mpage =3D erofs_get_meta_page(sb, eblk); - if (IS_ERR(mpage)) { - map->mpage =3D NULL; - return PTR_ERR(mpage); - } - m->kaddr =3D kmap_atomic(mpage); - unlock_page(mpage); - map->mpage =3D mpage; + m->kaddr =3D erofs_read_metabuf(&m->map->buf, sb, eblk, + EROFS_KMAP_ATOMIC); + if (IS_ERR(m->kaddr)) + return PTR_ERR(m->kaddr); return 0; } =20 @@ -711,8 +689,7 @@ static int z_erofs_do_map_blocks(struct inode *inode, map->m_flags |=3D EROFS_MAP_FULL_MAPPED; } unmap_out: - if (m.kaddr) - kunmap_atomic(m.kaddr); + erofs_unmap_metabuf(&m.map->buf); =20 out: erofs_dbg("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o", @@ -759,8 +736,7 @@ static int z_erofs_iomap_begin_report(struct inode *ino= de, loff_t offset, struct erofs_map_blocks map =3D { .m_la =3D offset }; =20 ret =3D z_erofs_map_blocks_iter(inode, &map, EROFS_GET_BLOCKS_FIEMAP); - if (map.mpage) - put_page(map.mpage); + erofs_put_metabuf(&map.buf); if (ret < 0) return ret; =20 --=20 2.24.4