From nobody Fri Apr 10 01:05:14 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5731B1D47B4 for ; Thu, 5 Mar 2026 06:44:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772693083; cv=none; b=s49QeLcpGZtUqOqpzwN6LuLKPevZLR9ES0v/jD0JjAxSqYYvwt5euT8FjipU6qpXE6L9R+TGqUrOzoEFFxO/om2UPtSx0cFKI4AEukJTxMsqWwQu31NHKqytkeMQs9iFt/DnBAL4q8Cooq8Av+lwG9Z0qYWDnlAst2GVALfg4nk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772693083; c=relaxed/simple; bh=evuktCgz3BzAqL6EqgNejfUEuDnLZo6tISqwzXjV6KA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=usZgdPkF+nEpfy3Tj5yGv+2k+3+OsQopBcCFGI030qo0F4bg+NloRHCgRzf+ofLIRAaJMeZZyDez5dPp3sRq+1DxCcdBBf7Dj9rGIUTA2qcfQHVvghykRpHIPUKnxzJGzzgmrVVdNBCzVDWEK3RyHvlm3Fxy4v76F0j1Wc2IOQI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=5Cos5Q8v; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="5Cos5Q8v" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=CdgpyTruSz0lkCGoGw+Mexu2uEf1R1zNw2yigg5yqd4=; b=5Cos5Q8vtkEImuDCeU7xAhVGYt4gl+FEaHFV/r3FV8zDxPKkqwXEfQMjG5XKfVi4lRj28R7l7 SlUNIPldtQJClKYj8Lci224kPfm6KscJyYFu25qsaqFU2NfnWRFZwz47RUOB8qdqen9PAhJ7oYK EH49UeTK1ZKUpZYqxsoKNXk= Received: from mail.maildlp.com (unknown [172.19.162.197]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4fRKdh6zmrzpTJ3; Thu, 5 Mar 2026 14:39:36 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id E2EEB40363; Thu, 5 Mar 2026 14:44:37 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 5 Mar 2026 14:44:37 +0800 From: Hongbo Li To: , CC: , , Subject: [PATCH v2] erofs: using iomap mechanisms in fileio for reading unencoded data Date: Thu, 5 Mar 2026 06:31:40 +0000 Message-ID: <20260305063140.47375-1-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260305013146.46349-1-lihongbo22@huawei.com> References: <20260305013146.46349-1-lihongbo22@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100002.china.huawei.com (7.221.188.206) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" In EROFS file-backend mount mode, the whole folio may trigger multiple backend file I/Os. The original read process mainly uses the @erofs_fileio_scan_folio, which employs a custom iteration mechanism on the folio and then to handle the I/Os. It requires complex mechanisms to manage the synchronization of multiple split file I/Os. This way couples the iteration operation with the data reading operation. We can decouple these two steps by using the iomap mechanism, thereby simplifying the implementation of the read process. Signed-off-by: Hongbo Li --- Changes from v1: - add folio release/invalidate hook. --- fs/erofs/data.c | 11 +-- fs/erofs/fileio.c | 176 ++++++++++++++++++++++---------------------- fs/erofs/internal.h | 8 ++ 3 files changed, 101 insertions(+), 94 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index f79ee80627d9..d1931fd6eed7 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -267,12 +267,6 @@ void erofs_onlinefolio_end(struct folio *folio, int er= r, bool dirty) folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO))); } =20 -struct erofs_iomap_iter_ctx { - struct page *page; - void *base; - struct inode *realinode; -}; - static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t le= ngth, unsigned int flags, struct iomap *iomap, struct iomap *srcmap) { @@ -313,6 +307,9 @@ static int erofs_iomap_begin(struct inode *inode, loff_= t offset, loff_t length, else iomap->bdev =3D mdev.m_bdev; iomap->addr =3D mdev.m_dif->fsoff + mdev.m_pa; + /* keep device context when mapping to device */ + if (ctx) + ctx->dif =3D mdev.m_dif; if (flags & IOMAP_DAX) iomap->addr +=3D mdev.m_dif->dax_part_off; } @@ -357,7 +354,7 @@ static int erofs_iomap_end(struct inode *inode, loff_t = pos, loff_t length, return written; } =20 -static const struct iomap_ops erofs_iomap_ops =3D { +const struct iomap_ops erofs_iomap_ops =3D { .iomap_begin =3D erofs_iomap_begin, .iomap_end =3D erofs_iomap_end, }; diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c index abe873f01297..bdf086a992a7 100644 --- a/fs/erofs/fileio.c +++ b/fs/erofs/fileio.c @@ -13,10 +13,9 @@ struct erofs_fileio_rq { refcount_t ref; }; =20 -struct erofs_fileio { - struct erofs_map_blocks map; - struct erofs_map_dev dev; +struct erofs_fileio_ctx { struct erofs_fileio_rq *rq; + struct erofs_device_info *dif; }; =20 static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret) @@ -32,7 +31,8 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, = long ret) if (!rq->bio.bi_end_io) { bio_for_each_folio_all(fi, &rq->bio) { DBG_BUGON(folio_test_uptodate(fi.folio)); - erofs_onlinefolio_end(fi.folio, ret < 0, false); + iomap_finish_folio_read(fi.folio, fi.offset, fi.length, + ret < 0 ? ret : 0); } } else if (ret < 0 && !rq->bio.bi_status) { rq->bio.bi_status =3D errno_to_blk_status(ret); @@ -88,111 +88,113 @@ void erofs_fileio_submit_bio(struct bio *bio) bio)); } =20 -static int erofs_fileio_scan_folio(struct erofs_fileio *io, - struct inode *inode, struct folio *folio) +static int erofs_fileio_read_folio_range(const struct iomap_iter *iter, + struct iomap_read_folio_ctx *ctx, size_t len) { - struct erofs_map_blocks *map =3D &io->map; - unsigned int cur =3D 0, end =3D folio_size(folio), len, attached =3D 0; - loff_t pos =3D folio_pos(folio), ofs; - int err =3D 0; - - erofs_onlinefolio_init(folio); - while (cur < end) { - if (!in_range(pos + cur, map->m_la, map->m_llen)) { - map->m_la =3D pos + cur; - map->m_llen =3D end - cur; - err =3D erofs_map_blocks(inode, map); - if (err) - break; - } + struct erofs_iomap_iter_ctx *iter_ctx =3D iter->private; + struct erofs_device_info *dif =3D iter_ctx->dif; + struct inode *realinode =3D iter_ctx ? iter_ctx->realinode : iter->inode; + struct folio *folio =3D ctx->cur_folio; + struct erofs_fileio_ctx *fileio_ctx =3D ctx->read_ctx; + struct iomap *iomap =3D (struct iomap *)&iter->iomap; + size_t poff =3D offset_in_folio(folio, iter->pos); + loff_t pos =3D iter->pos; + int ret =3D 0; + + if (iomap->type =3D=3D IOMAP_HOLE) { + folio_zero_range(folio, poff, len); + return 0; + } =20 - ofs =3D folio_pos(folio) + cur - map->m_la; - len =3D min_t(loff_t, map->m_llen - ofs, end - cur); - if (map->m_flags & EROFS_MAP_META) { - struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; - void *src; - - src =3D erofs_read_metabuf(&buf, inode->i_sb, - map->m_pa + ofs, erofs_inode_in_metabox(inode)); - if (IS_ERR(src)) { - err =3D PTR_ERR(src); - break; - } - memcpy_to_folio(folio, cur, src, len); - erofs_put_metabuf(&buf); - } else if (!(map->m_flags & EROFS_MAP_MAPPED)) { - folio_zero_segment(folio, cur, cur + len); - attached =3D 0; - } else { - if (io->rq && (map->m_pa + ofs !=3D io->dev.m_pa || - map->m_deviceid !=3D io->dev.m_deviceid)) { -io_retry: - erofs_fileio_rq_submit(io->rq); - io->rq =3D NULL; - } - - if (!io->rq) { - io->dev =3D (struct erofs_map_dev) { - .m_pa =3D io->map.m_pa + ofs, - .m_deviceid =3D io->map.m_deviceid, - }; - err =3D erofs_map_dev(inode->i_sb, &io->dev); - if (err) - break; - io->rq =3D erofs_fileio_rq_alloc(&io->dev); - io->rq->bio.bi_iter.bi_sector =3D - (io->dev.m_dif->fsoff + io->dev.m_pa) >> 9; - attached =3D 0; - } - if (!bio_add_folio(&io->rq->bio, folio, len, cur)) - goto io_retry; - if (!attached++) - erofs_onlinefolio_split(folio); - io->dev.m_pa +=3D len; + while (len > 0) { + sector_t sector =3D iomap_sector(iomap, pos); + unsigned int off =3D offset_in_folio(folio, pos); + unsigned int n =3D min(len, folio_size(folio) - off); + struct erofs_map_dev mdev =3D {}; + + if (!n) + break; + if (!fileio_ctx->rq || + fileio_ctx->dif !=3D dif || + bio_end_sector(&fileio_ctx->rq->bio) !=3D sector) { + erofs_fileio_rq_submit(fileio_ctx->rq); + mdev =3D (struct erofs_map_dev) { + .m_dif =3D dif, + .m_sb =3D realinode->i_sb, + .m_pa =3D (sector << SECTOR_SHIFT) + off, + }; + fileio_ctx->dif =3D mdev.m_dif; + fileio_ctx->rq =3D erofs_fileio_rq_alloc(&mdev); + fileio_ctx->rq->bio.bi_iter.bi_sector =3D + (mdev.m_dif->fsoff + mdev.m_pa) >> SECTOR_SHIFT; + } + if (!bio_add_folio(&fileio_ctx->rq->bio, folio, n, off)) { + erofs_fileio_rq_submit(fileio_ctx->rq); + fileio_ctx->rq =3D NULL; + continue; } - cur +=3D len; + pos +=3D n; + len -=3D n; } - erofs_onlinefolio_end(folio, err, false); - return err; + return ret; +} + +static void erofs_fileio_submit_read(struct iomap_read_folio_ctx *ctx) +{ + struct erofs_fileio_ctx *fileio_ctx =3D ctx->read_ctx; + + erofs_fileio_rq_submit(fileio_ctx->rq); + fileio_ctx->rq =3D NULL; } =20 +static const struct iomap_read_ops erofs_fileio_read_ops =3D { + .read_folio_range =3D erofs_fileio_read_folio_range, + .submit_read =3D erofs_fileio_submit_read, +}; + static int erofs_fileio_read_folio(struct file *file, struct folio *folio) { + struct erofs_fileio_ctx fileio_ctx =3D {}; + struct iomap_read_folio_ctx read_ctx =3D { + .ops =3D &erofs_fileio_read_ops, + .cur_folio =3D folio, + .read_ctx =3D &fileio_ctx, + }; bool need_iput; - struct inode *realinode =3D erofs_real_inode(folio_inode(folio), &need_ip= ut); - struct erofs_fileio io =3D {}; - int err; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .realinode =3D erofs_real_inode(folio_inode(folio), &need_iput), + }; =20 - trace_erofs_read_folio(realinode, folio, true); - err =3D erofs_fileio_scan_folio(&io, realinode, folio); - erofs_fileio_rq_submit(io.rq); + trace_erofs_read_folio(iter_ctx.realinode, folio, true); + iomap_read_folio(&erofs_iomap_ops, &read_ctx, &iter_ctx); if (need_iput) - iput(realinode); - return err; + iput(iter_ctx.realinode); + return 0; } =20 static void erofs_fileio_readahead(struct readahead_control *rac) { + struct erofs_fileio_ctx fileio_ctx =3D {}; + struct iomap_read_folio_ctx read_ctx =3D { + .ops =3D &erofs_fileio_read_ops, + .rac =3D rac, + .read_ctx =3D &fileio_ctx, + }; bool need_iput; - struct inode *realinode =3D erofs_real_inode(rac->mapping->host, &need_ip= ut); - struct erofs_fileio io =3D {}; - struct folio *folio; - int err; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .realinode =3D erofs_real_inode(rac->mapping->host, &need_iput), + }; =20 - trace_erofs_readahead(realinode, readahead_index(rac), + trace_erofs_readahead(iter_ctx.realinode, readahead_index(rac), readahead_count(rac), true); - while ((folio =3D readahead_folio(rac))) { - err =3D erofs_fileio_scan_folio(&io, realinode, folio); - if (err && err !=3D -EINTR) - erofs_err(realinode->i_sb, "readahead error at folio %lu @ nid %llu", - folio->index, EROFS_I(realinode)->nid); - } - erofs_fileio_rq_submit(io.rq); + iomap_readahead(&erofs_iomap_ops, &read_ctx, &iter_ctx); if (need_iput) - iput(realinode); + iput(iter_ctx.realinode); } =20 const struct address_space_operations erofs_fileio_aops =3D { .read_folio =3D erofs_fileio_read_folio, .readahead =3D erofs_fileio_readahead, + .release_folio =3D iomap_release_folio, + .invalidate_folio =3D iomap_invalidate_folio, }; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index a4f0a42cf8c3..cda927225b9a 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -411,6 +411,13 @@ struct erofs_map_dev { unsigned int m_deviceid; }; =20 +struct erofs_iomap_iter_ctx { + struct page *page; + void *base; + struct inode *realinode; + struct erofs_device_info *dif; +}; + extern const struct super_operations erofs_sops; =20 extern const struct address_space_operations erofs_aops; @@ -427,6 +434,7 @@ extern const struct file_operations erofs_file_fops; extern const struct file_operations erofs_dir_fops; extern const struct file_operations erofs_ishare_fops; =20 +extern const struct iomap_ops erofs_iomap_ops; extern const struct iomap_ops z_erofs_iomap_report_ops; =20 /* flags for erofs_fscache_register_cookie() */ --=20 2.22.0