From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (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 A6E3030F7EA; Fri, 14 Nov 2025 10:07:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114826; cv=none; b=jPKUWhwLugh1h4hVuOEPWyAqIXe4cVCFuzyLz32XYcmI3yqCCERCaZ/cdSUvO6QXr8xB/Hr+jhK7lDjDP0UNcolaiGrFqz3rvh8itI9T6SbRpfzGE9KdAA+zJD7ohZ5BvlDOue+ZYb95nw5JW5kpN+t2oCjeu8biJ7BwMMgggzM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114826; c=relaxed/simple; bh=S+i9I/UqevohlXSVPtPcsSZNYaIQ8MBY912CHMWdSwI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mG1QXFq1YkBzf4wxwlUFTMcXW2stkzgudjLgwnwUcGYOCgiaLwvfEO8QPKKEi/MLA+dya22oPK9sdQKDchpMk6CdR3hY6vf/+74o28ZX8Am8iVcDAP+cSOf/PMJ+tIRCuIqQmoZPTVf+8LCI1lz+jSFUGOLsZc74PafFLejW4Gs= 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=5Sv2DVfY; arc=none smtp.client-ip=113.46.200.216 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="5Sv2DVfY" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=K0Uha1E1AoTTdsUqS8ogAzLegDGAzEZvOWEH95Tolb8=; b=5Sv2DVfYlUO5XY0hrSs5KJkDBSjT4n4BjyMTqeRgBOCu/hEpoWKoDtvPeyeiwpN7ITrrKdI+H SUkDpdCFVlqGPxDYdg+28EA8YS0U5/89lTWDTFLCX/kAs7UOW2z69706j/87dD0m2QBL+m40TIX 1BM+x9kwrSfbkY4tKSv0d+Q= Received: from mail.maildlp.com (unknown [172.19.163.48]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4d7CST1Rt2z1T4LW; Fri, 14 Nov 2025 18:05:29 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 4FA03180478; Fri, 14 Nov 2025 18:06:55 +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; Fri, 14 Nov 2025 18:06:54 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 1/9] iomap: stash iomap read ctx in the private field of iomap_iter Date: Fri, 14 Nov 2025 09:55:08 +0000 Message-ID: <20251114095516.207555-2-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" It's useful to get filesystem-specific information using the existing private field in the @iomap_iter passed to iomap_{begin,end} for advanced usage for iomap buffered reads, which is much like the current iomap DIO. For example, EROFS needs it to: - implement an efficient page cache sharing feature, since iomap needs to apply to anon inode page cache but we'd like to get the backing inode/fs instead, so filesystem-specific private data is needed to keep such information; - pass in both struct page * and void * for inline data to avoid kmap_to_page() usage (which is bogus). Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/fuse/file.c | 4 ++-- fs/iomap/buffered-io.c | 6 ++++-- include/linux/iomap.h | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 8275b6681b9b..98dd20f0bb53 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -973,7 +973,7 @@ static int fuse_read_folio(struct file *file, struct fo= lio *folio) return -EIO; } =20 - iomap_read_folio(&fuse_iomap_ops, &ctx); + iomap_read_folio(&fuse_iomap_ops, &ctx, NULL); fuse_invalidate_atime(inode); return 0; } @@ -1075,7 +1075,7 @@ static void fuse_readahead(struct readahead_control *= rac) if (fuse_is_bad(inode)) return; =20 - iomap_readahead(&fuse_iomap_ops, &ctx); + iomap_readahead(&fuse_iomap_ops, &ctx, NULL); } =20 static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *t= o) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 6ae031ac8058..8e79303c074e 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -496,13 +496,14 @@ static int iomap_read_folio_iter(struct iomap_iter *i= ter, } =20 void iomap_read_folio(const struct iomap_ops *ops, - struct iomap_read_folio_ctx *ctx) + struct iomap_read_folio_ctx *ctx, void *private) { struct folio *folio =3D ctx->cur_folio; struct iomap_iter iter =3D { .inode =3D folio->mapping->host, .pos =3D folio_pos(folio), .len =3D folio_size(folio), + .private =3D private, }; size_t bytes_pending =3D 0; int ret; @@ -560,13 +561,14 @@ static int iomap_readahead_iter(struct iomap_iter *it= er, * the filesystem to be reentered. */ void iomap_readahead(const struct iomap_ops *ops, - struct iomap_read_folio_ctx *ctx) + struct iomap_read_folio_ctx *ctx, void *private) { struct readahead_control *rac =3D ctx->rac; struct iomap_iter iter =3D { .inode =3D rac->mapping->host, .pos =3D readahead_pos(rac), .len =3D readahead_length(rac), + .private =3D private, }; size_t cur_bytes_pending; =20 diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 8b1ac08c7474..c3ecbbdb14e8 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -341,9 +341,9 @@ ssize_t iomap_file_buffered_write(struct kiocb *iocb, s= truct iov_iter *from, const struct iomap_ops *ops, const struct iomap_write_ops *write_ops, void *private); void iomap_read_folio(const struct iomap_ops *ops, - struct iomap_read_folio_ctx *ctx); + struct iomap_read_folio_ctx *ctx, void *private); void iomap_readahead(const struct iomap_ops *ops, - struct iomap_read_folio_ctx *ctx); + struct iomap_read_folio_ctx *ctx, void *private); bool iomap_is_partially_uptodate(struct folio *, size_t from, size_t count= ); struct folio *iomap_get_folio(struct iomap_iter *iter, loff_t pos, size_t = len); bool iomap_release_folio(struct folio *folio, gfp_t gfp_flags); @@ -594,7 +594,7 @@ static inline void iomap_bio_read_folio(struct folio *f= olio, .cur_folio =3D folio, }; =20 - iomap_read_folio(ops, &ctx); + iomap_read_folio(ops, &ctx, NULL); } =20 static inline void iomap_bio_readahead(struct readahead_control *rac, @@ -605,7 +605,7 @@ static inline void iomap_bio_readahead(struct readahead= _control *rac, .rac =3D rac, }; =20 - iomap_readahead(ops, &ctx); + iomap_readahead(ops, &ctx, NULL); } #endif /* CONFIG_BLOCK */ =20 --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (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 A577230F7E4; Fri, 14 Nov 2025 10:07:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114825; cv=none; b=TNIEb/glSfrwLLH9plt+6jfoOxF+XHAn56MIldh2Qs8LvF1hA+vBll784T45RMfgey52wVna/HHtsZh7E1KYKmmHb1UvigckRqZqQMAkwAn1NNsZHC1Z+1VpfJECUXJAHmRKaYq06O41j9twsM0fjridGCwYS0cgCJf9vju9GQA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114825; c=relaxed/simple; bh=60G7Og+fkL/ycDlX4lls67Wo98U0QEGGA8YMPqHQ0po=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KHisTICbq2+jwvV+dYF+KT5Dxp8d0Yy6i2BPo6wvRwjYrDuWUo+99bFjDhNVei7DxlGlCjLbYTECD64eWGvJy6ozH2J4S3XLVtLGHoexPFh/Mw3C8pzXQd8y23QMQmvCXCNdt2oMCB8Z0x8ByCpmZABCOLCkCxb+EH6t3urs4qU= 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=EV8iVJoK; arc=none smtp.client-ip=113.46.200.219 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="EV8iVJoK" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=taDPXuSohFIbjKqHNC7TAvBRm/MUsJxB6CrB2qYxkis=; b=EV8iVJoK7ecc8euILR3Ko+h8dtrSgWNrVnjY8Vcmao3+AkMEaU8pATbmZEDpmMiRkSTdu+Gsa XMaew/zvJVirMT6LwmE63XorCDRwkPo+twFwkod6zJj3F1uqtPl3HEG9Kz0Ofnj4roJDk+bxCX2 9s4ydz0TIyD24QrPdbVnaZc= Received: from mail.maildlp.com (unknown [172.19.163.174]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4d7CSB3S9cz1prLM; Fri, 14 Nov 2025 18:05:14 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id CFF9C14035E; Fri, 14 Nov 2025 18:06:55 +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; Fri, 14 Nov 2025 18:06:55 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 2/9] erofs: hold read context in iomap_iter if needed Date: Fri, 14 Nov 2025 09:55:09 +0000 Message-ID: <20251114095516.207555-3-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" Uncoming page cache sharing needs pass read context to iomap_iter, here we unify the way of passing the read context in EROFS. Moreover, bmap and fiemap don't need to map the inline data. Note that we keep `struct page *` in `struct erofs_iomap_iter_ctx` as well to avoid bogus kmap_to_page usage. Signed-off-by: Hongbo Li --- fs/erofs/data.c | 79 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index bb13c4cb8455..bd3d85c61341 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -266,14 +266,23 @@ void erofs_onlinefolio_end(struct folio *folio, int e= rr, bool dirty) folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO))); } =20 +struct erofs_iomap_iter_ctx { + struct page *page; + void *base; +}; + static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t le= ngth, unsigned int flags, struct iomap *iomap, struct iomap *srcmap) { int ret; + struct erofs_iomap_iter_ctx *ctx; struct super_block *sb =3D inode->i_sb; struct erofs_map_blocks map; struct erofs_map_dev mdev; + struct iomap_iter *iter; =20 + iter =3D container_of(iomap, struct iomap_iter, iomap); + ctx =3D iter->private; map.m_la =3D offset; map.m_llen =3D length; ret =3D erofs_map_blocks(inode, &map); @@ -283,7 +292,8 @@ static int erofs_iomap_begin(struct inode *inode, loff_= t offset, loff_t length, iomap->offset =3D map.m_la; iomap->length =3D map.m_llen; iomap->flags =3D 0; - iomap->private =3D NULL; + if (ctx) + ctx->base =3D NULL; iomap->addr =3D IOMAP_NULL_ADDR; if (!(map.m_flags & EROFS_MAP_MAPPED)) { iomap->type =3D IOMAP_HOLE; @@ -309,16 +319,20 @@ static int erofs_iomap_begin(struct inode *inode, lof= f_t offset, loff_t length, } =20 if (map.m_flags & EROFS_MAP_META) { - void *ptr; - struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; - iomap->type =3D IOMAP_INLINE; - ptr =3D erofs_read_metabuf(&buf, sb, map.m_pa, - erofs_inode_in_metabox(inode)); - if (IS_ERR(ptr)) - return PTR_ERR(ptr); - iomap->inline_data =3D ptr; - iomap->private =3D buf.base; + /* read context should read the inlined data */ + if (ctx) { + void *ptr; + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; + + ptr =3D erofs_read_metabuf(&buf, sb, map.m_pa, + erofs_inode_in_metabox(inode)); + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + iomap->inline_data =3D ptr; + ctx->page =3D buf.page; + ctx->base =3D buf.base; + } } else { iomap->type =3D IOMAP_MAPPED; } @@ -328,18 +342,19 @@ 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) { - void *ptr =3D iomap->private; + struct erofs_iomap_iter_ctx *ctx; + struct iomap_iter *iter; =20 - if (ptr) { + iter =3D container_of(iomap, struct iomap_iter, iomap); + ctx =3D iter->private; + if (ctx && ctx->base) { struct erofs_buf buf =3D { - .page =3D kmap_to_page(ptr), - .base =3D ptr, + .page =3D ctx->page, + .base =3D ctx->base, }; =20 DBG_BUGON(iomap->type !=3D IOMAP_INLINE); erofs_put_metabuf(&buf); - } else { - DBG_BUGON(iomap->type =3D=3D IOMAP_INLINE); } return written; } @@ -369,18 +384,36 @@ int erofs_fiemap(struct inode *inode, struct fiemap_e= xtent_info *fieinfo, */ static int erofs_read_folio(struct file *file, struct folio *folio) { + struct iomap_read_folio_ctx read_ctx =3D { + .ops =3D &iomap_bio_read_ops, + .cur_folio =3D folio, + }; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .page =3D NULL, + .base =3D NULL, + }; + trace_erofs_read_folio(folio, true); =20 - iomap_bio_read_folio(folio, &erofs_iomap_ops); + iomap_read_folio(&erofs_iomap_ops, &read_ctx, &iter_ctx); return 0; } =20 static void erofs_readahead(struct readahead_control *rac) { + struct iomap_read_folio_ctx read_ctx =3D { + .ops =3D &iomap_bio_read_ops, + .rac =3D rac, + }; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .page =3D NULL, + .base =3D NULL, + }; + trace_erofs_readahead(rac->mapping->host, readahead_index(rac), readahead_count(rac), true); =20 - iomap_bio_readahead(rac, &erofs_iomap_ops); + iomap_readahead(&erofs_iomap_ops, &read_ctx, &iter_ctx); } =20 static sector_t erofs_bmap(struct address_space *mapping, sector_t block) @@ -400,9 +433,15 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb= , struct iov_iter *to) if (IS_DAX(inode)) return dax_iomap_rw(iocb, to, &erofs_iomap_ops); #endif - if ((iocb->ki_flags & IOCB_DIRECT) && inode->i_sb->s_bdev) + if ((iocb->ki_flags & IOCB_DIRECT) && inode->i_sb->s_bdev) { + struct erofs_iomap_iter_ctx iter_ctx =3D { + .page =3D NULL, + .base =3D NULL, + }; + return iomap_dio_rw(iocb, to, &erofs_iomap_ops, - NULL, 0, NULL, 0); + NULL, 0, &iter_ctx, 0); + } return filemap_read(iocb, to, 0); } =20 --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (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 C6C0430BBB3; Fri, 14 Nov 2025 10:06:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114821; cv=none; b=pQWtOxm4OjR8XJLEUXnpEY5d1dzVUqasoV4j3e19NJ++1Ldojx8v2oLYp50N0APueQ654/+6yX4S5FycwzD+selYdjLhXIyjgLolNNcBRB8kn0h5hyd3/rllsrV4mV+2A3+0qfUX2bQIhWpJCgWwlA3Bg2H+9yImvAGjANgfXq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114821; c=relaxed/simple; bh=GqoLNNphLdkOlqPvRK2MOXqRFMk5iEPy8QHIVaoh4MQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P6hXNKU481SunqfBNN+OSHSzeTBNrgWZiiYfTb19J3XanPTHNScw7sgpg0qPsI4qEjygDGGDTT+0co3es6tS3J0nMPRtIe4UJJL2znshIqIPl+mKivOby8rzihTJ/vfkiLe7aBDepqcn2NfuSVls2zvDGV4lp92slxkMNlxzlhw= 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=Rav2GhBU; arc=none smtp.client-ip=113.46.200.224 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="Rav2GhBU" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=oR1PXK3pguj2JmCtIjiUOfecM6WsfL7kdXjl3dsVSrc=; b=Rav2GhBUOnWTidUOwR73S2bP0bYZVAVDHALDWmNyhN2kAa+o6IkVtpFyoR1bx/ZwbEMHS612p +n6LT3BGLruBpFXLJ9rkCGVhevYQA61/2a9r3/2q9waiAhbImexF2x/9tqOfREmJsaMQHCTW97n s+BKkcJFP3+7/QyowDMqrFw= Received: from mail.maildlp.com (unknown [172.19.163.44]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4d7CSC1WVVz1cypB; Fri, 14 Nov 2025 18:05:15 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 4796C140275; Fri, 14 Nov 2025 18:06:56 +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; Fri, 14 Nov 2025 18:06:55 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 3/9] erofs: move `struct erofs_anon_fs_type` to super.c Date: Fri, 14 Nov 2025 09:55:10 +0000 Message-ID: <20251114095516.207555-4-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo Move the `struct erofs_anon_fs_type` to the super.c and expose it in preparation for the upcoming page cache share feature. Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li --- fs/erofs/fscache.c | 13 ------------- fs/erofs/internal.h | 4 ++++ fs/erofs/super.c | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 362acf828279..2d1683479fc0 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -3,7 +3,6 @@ * Copyright (C) 2022, Alibaba Cloud * Copyright (C) 2022, Bytedance Inc. All rights reserved. */ -#include #include #include "internal.h" =20 @@ -13,18 +12,6 @@ static LIST_HEAD(erofs_domain_list); static LIST_HEAD(erofs_domain_cookies_list); static struct vfsmount *erofs_pseudo_mnt; =20 -static int erofs_anon_init_fs_context(struct fs_context *fc) -{ - return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM; -} - -static struct file_system_type erofs_anon_fs_type =3D { - .owner =3D THIS_MODULE, - .name =3D "pseudo_erofs", - .init_fs_context =3D erofs_anon_init_fs_context, - .kill_sb =3D kill_anon_super, -}; - struct erofs_fscache_io { struct netfs_cache_resources cres; struct iov_iter iter; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index f7f622836198..e80b35db18e4 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -188,6 +188,10 @@ static inline bool erofs_is_fileio_mode(struct erofs_s= b_info *sbi) return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->dif0.file; } =20 +#if defined(CONFIG_EROFS_FS_ONDEMAND) +extern struct file_system_type erofs_anon_fs_type; +#endif + static inline bool erofs_is_fscache_mode(struct super_block *sb) { return IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && diff --git a/fs/erofs/super.c b/fs/erofs/super.c index f3f8d8c066e4..0d88c04684b9 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "xattr.h" =20 #define CREATE_TRACE_POINTS @@ -920,6 +921,20 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 +#if defined(CONFIG_EROFS_FS_ONDEMAND) +static int erofs_anon_init_fs_context(struct fs_context *fc) +{ + return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM; +} + +struct file_system_type erofs_anon_fs_type =3D { + .owner =3D THIS_MODULE, + .name =3D "pseudo_erofs", + .init_fs_context =3D erofs_anon_init_fs_context, + .kill_sb =3D kill_anon_super, +}; +#endif + static int __init erofs_module_init(void) { int err; --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (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 CD14C30C360; Fri, 14 Nov 2025 10:06:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114822; cv=none; b=rfpA0tSpC47QuTS1XRPEiADJTNGI+ovkfpzt7lNc/Ul7/xLu+5ne8ggIuKZDmHwT3NLCJ1/VY+AqKTev8/qby/rSuZ/0C9/zT/PpE0i9R2e+XE/zuGV0O0wY0B+10UkqpexmpT1we57/SNBx/18P23vEOtEUaKRXikhhqr+JLQU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114822; c=relaxed/simple; bh=Kg0QCfmFyUNtsDlUVBarSBCCkw7lWjyL3Ax0t78Uvxo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QXd9jGyGVE7y4Alvctar9XTVvF8iDB0/FAN6cjfKNr+X/qZXfFGngJp3u/3WMZDZZkpr4s0mMP0VwW15txeGV/pIU9NBkBjz6x/YNiVLNweIlFozgheSKH/+jar+F1DfyASLS3KufBCaZSoKT34/lDAXK25+UVv16m2xuxjizDc= 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=V+TmuZrY; arc=none smtp.client-ip=113.46.200.226 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="V+TmuZrY" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=YL/tWdSMyJnhT69kjA2piGvwBmgoM2UAWnLITs3jTEg=; b=V+TmuZrYmgHvOsWxyuHKiGIRN7ibFSt+AxOTCD9SrXmlbNoUuTqDaNvpnOf30R2wDLrlB7gv7 ZLw5E25Ga8cOAzgfmSZ7qwj2ATBqTSLfjnpWWhlk/TeMbiSQNcdPo/zTRXPZ5Iks+YUnlB3Gvqw ISmjrPMwBRGUeBFlKftEXAM= Received: from mail.maildlp.com (unknown [172.19.88.163]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4d7CSC3NMRzKm5f; Fri, 14 Nov 2025 18:05:15 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id C6EA9180044; Fri, 14 Nov 2025 18:06:56 +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; Fri, 14 Nov 2025 18:06:56 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 4/9] erofs: support user-defined fingerprint name Date: Fri, 14 Nov 2025 09:55:11 +0000 Message-ID: <20251114095516.207555-5-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo When creating the EROFS image, users can specify the fingerprint name. This is to prepare for the upcoming inode page cache share. Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li --- fs/erofs/Kconfig | 9 +++++++++ fs/erofs/erofs_fs.h | 6 ++++-- fs/erofs/internal.h | 6 ++++++ fs/erofs/super.c | 5 ++++- fs/erofs/xattr.c | 26 ++++++++++++++++++++++++++ fs/erofs/xattr.h | 6 ++++++ 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index d81f3318417d..1b5c0cd99203 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -194,3 +194,12 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI at higher priority. =20 If unsure, say N. + +config EROFS_FS_INODE_SHARE + bool "EROFS inode page cache share support (experimental)" + depends on EROFS_FS && EROFS_FS_XATTR && !EROFS_FS_ONDEMAND + help + This permits EROFS to share page cache for files with same + fingerprints. + + If unsure, say N. \ No newline at end of file diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 3d5738f80072..104518cd161d 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -35,8 +35,9 @@ #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040 #define EROFS_FEATURE_INCOMPAT_48BIT 0x00000080 #define EROFS_FEATURE_INCOMPAT_METABOX 0x00000100 +#define EROFS_FEATURE_INCOMPAT_ISHARE_KEY 0x00000200 #define EROFS_ALL_FEATURE_INCOMPAT \ - ((EROFS_FEATURE_INCOMPAT_METABOX << 1) - 1) + ((EROFS_FEATURE_INCOMPAT_ISHARE_KEY << 1) - 1) =20 #define EROFS_SB_EXTSLOT_SIZE 16 =20 @@ -83,7 +84,8 @@ struct erofs_super_block { __le32 xattr_prefix_start; /* start of long xattr prefixes */ __le64 packed_nid; /* nid of the special packed inode */ __u8 xattr_filter_reserved; /* reserved for xattr name filter */ - __u8 reserved[3]; + __u8 ishare_key_start; /* start of ishare key */ + __u8 reserved[2]; __le32 build_time; /* seconds added to epoch for mkfs time */ __le64 rootnid_8b; /* (48BIT on) nid of root directory */ __le64 reserved2; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index e80b35db18e4..3ebbb7c5d085 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -167,6 +167,11 @@ struct erofs_sb_info { struct erofs_domain *domain; char *fsid; char *domain_id; + + /* inode page cache share support */ + u8 ishare_key_start; + u8 ishare_key_idx; + char *ishare_key; }; =20 #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) @@ -236,6 +241,7 @@ EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE) EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES) EROFS_FEATURE_FUNCS(48bit, incompat, INCOMPAT_48BIT) EROFS_FEATURE_FUNCS(metabox, incompat, INCOMPAT_METABOX) +EROFS_FEATURE_FUNCS(ishare_key, incompat, INCOMPAT_ISHARE_KEY) EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER) EROFS_FEATURE_FUNCS(shared_ea_in_metabox, compat, COMPAT_SHARED_EA_IN_META= BOX) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 0d88c04684b9..3561473cb789 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -339,7 +339,7 @@ static int erofs_read_superblock(struct super_block *sb) return -EFSCORRUPTED; /* self-loop detection */ } sbi->inos =3D le64_to_cpu(dsb->inos); - + sbi->ishare_key_start =3D dsb->ishare_key_start; sbi->epoch =3D (s64)le64_to_cpu(dsb->epoch); sbi->fixed_nsec =3D le32_to_cpu(dsb->fixed_nsec); super_set_uuid(sb, (void *)dsb->uuid, sizeof(dsb->uuid)); @@ -738,6 +738,9 @@ static int erofs_fc_fill_super(struct super_block *sb, = struct fs_context *fc) if (err) return err; =20 + err =3D erofs_xattr_set_ishare_key(sb); + if (err) + return err; erofs_set_sysfs_name(sb); err =3D erofs_register_sysfs(sb); if (err) diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 396536d9a862..3c99091f39a5 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -564,3 +564,29 @@ struct posix_acl *erofs_get_acl(struct inode *inode, i= nt type, bool rcu) return acl; } #endif + +#ifdef CONFIG_EROFS_FS_INODE_SHARE +int erofs_xattr_set_ishare_key(struct super_block *sb) +{ + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + struct erofs_xattr_prefix_item *pf; + char *ishare_key; + + if (!sbi->xattr_prefixes || + !(sbi->ishare_key_start & EROFS_XATTR_LONG_PREFIX)) + return 0; + + pf =3D sbi->xattr_prefixes + + (sbi->ishare_key_start & EROFS_XATTR_LONG_PREFIX_MASK); + if (!pf || pf >=3D sbi->xattr_prefixes + sbi->xattr_prefix_count) + return 0; + ishare_key =3D kmalloc(pf->infix_len + 1, GFP_KERNEL); + if (!ishare_key) + return -ENOMEM; + memcpy(ishare_key, pf->prefix->infix, pf->infix_len); + ishare_key[pf->infix_len] =3D '\0'; + sbi->ishare_key =3D ishare_key; + sbi->ishare_key_idx =3D pf->prefix->base_index; + return 0; +} +#endif diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index 6317caa8413e..21684359662c 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -67,4 +67,10 @@ struct posix_acl *erofs_get_acl(struct inode *inode, int= type, bool rcu); #define erofs_get_acl (NULL) #endif =20 +#ifdef CONFIG_EROFS_FS_INODE_SHARE +int erofs_xattr_set_ishare_key(struct super_block *sb); +#else +static inline int erofs_xattr_set_ishare_key(struct super_block *sb) { ret= urn 0; } +#endif + #endif --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (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 9552D30FF37; Fri, 14 Nov 2025 10:07:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114827; cv=none; b=aI+hK8pmFYvuOLVYarN+3D8F1uTy7Nji10iSHcrGxKrRI/0A+EAsOF3Xo+muvJQGByUzb1DFAdc54fizzsRdrWje6dtn+xOonpz8iCQf1K7FNYtr0LWZNWvPiZyrNpvNyqKHvSjZpJ/7hOpLVG0v9u+6qT1XnWRNuU5RlQy6gLs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114827; c=relaxed/simple; bh=bsXHaXIuK9R9yIZNEZJfEha8lhnJlfKz6QWd9DGnzHM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eaGua6cPV0OkzUCedT2VkCa8CKBnqMuxjHFa2gOb7GOC1i8puvcXn6gIrfbJfKEK7yJj/RjVg28gC9mD8AvpO5bYMlDM/j77pXf+D4p1aKOuQNRpXU7EYaVyaOV/v/wqUnLWOEK70pEjzOJT0juuCoDAkdzYOQ30QgvVD0zsFtc= 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=o7D8i3lB; arc=none smtp.client-ip=113.46.200.219 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="o7D8i3lB" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=ieQKM8di5soOYofHjv7enQxmHnjBsCzD05Jj+DgINJ0=; b=o7D8i3lBR8INJiBT8X78v+EFIoLPbOOzkHlMak8YD5D5PUzxMYq4JGtgeukgfzkyR8EpDOEz/ D5IqQ22VOBoM01RJm4p3NKefGgRZ7g6Yei9ibS/12Wc5577fFe+N5ckKW6KkVqWaNb2bhbKKWND Duvd2RZrJt/6kruOG/SdNss= Received: from mail.maildlp.com (unknown [172.19.88.194]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4d7CSC64JSz1prQF; Fri, 14 Nov 2025 18:05:15 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 36BE41401E0; Fri, 14 Nov 2025 18:06:57 +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; Fri, 14 Nov 2025 18:06:56 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 5/9] erofs: support domain-specific page cache share Date: Fri, 14 Nov 2025 09:55:12 +0000 Message-ID: <20251114095516.207555-6-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo Only files in the same domain will share the page cache. Also modify the sysfs related content in preparation for the upcoming page cache share feature. Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li --- fs/erofs/super.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 3561473cb789..ce95454c9ee7 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -515,6 +515,8 @@ static int erofs_fc_parse_param(struct fs_context *fc, if (!sbi->fsid) return -ENOMEM; break; +#endif +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_INODE_SHA= RE) case Opt_domain_id: kfree(sbi->domain_id); sbi->domain_id =3D kstrdup(param->string, GFP_KERNEL); @@ -615,7 +617,7 @@ static void erofs_set_sysfs_name(struct super_block *sb) { struct erofs_sb_info *sbi =3D EROFS_SB(sb); =20 - if (sbi->domain_id) + if (sbi->domain_id && !sbi->ishare_key) super_set_sysfs_name_generic(sb, "%s,%s", sbi->domain_id, sbi->fsid); else if (sbi->fsid) @@ -1036,6 +1038,8 @@ static int erofs_show_options(struct seq_file *seq, s= truct dentry *root) #ifdef CONFIG_EROFS_FS_ONDEMAND if (sbi->fsid) seq_printf(seq, ",fsid=3D%s", sbi->fsid); +#endif +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_INODE_SHA= RE) if (sbi->domain_id) seq_printf(seq, ",domain_id=3D%s", sbi->domain_id); #endif --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout02.his.huawei.com (canpmsgout02.his.huawei.com [113.46.200.217]) (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 C411E30C618; Fri, 14 Nov 2025 10:06:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.217 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114823; cv=none; b=tBQvQ+GiHDd+W7phfdF+fPnKiRieAXc7gZCRzTTrbqhQquogi8IMQF3nVvaGj7Pc+ItzutbCCRo6Qfqb6JMtfmdzDHKHkebhktRXSwKyxzOdzH2gt7OEauH6543YbVPS+H0I1Gc6ybJJqF/mrb7m+DtmNrzcrtfBgUog7JJX4qE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114823; c=relaxed/simple; bh=ov7dh/uuURim/CftKkpdpfhfOcNLkEXK0AXcZBc0xgg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p4kdBevVZw1YqjBpyjYne2uotslS5I2jWsF6V9byxDLocVp7+awVgcGO950omz6UJWR44k3UTAR2YcJ5lwurRIs0/GwMsk57MqFYEjoYx2+g5c3lzKJqxQr4J6sQxcRxXDdBnAge43qTaPpQfG3pb5vCvrdsaa3+Dl5IPHBw8TM= 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=rXhUHCQ0; arc=none smtp.client-ip=113.46.200.217 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="rXhUHCQ0" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=B8DEAHKpK8WFmqiYDgExYub+7n82n1eSz+k73lgwcIA=; b=rXhUHCQ0OCNMaLxGqkoD0iVLr0a0GLdR8MKCrc+ucPKFRlxh8tiBC6xH7AZwLRXVImaq0h/Xy +zDAmvRsIYs6zluNdSzF98zCG2ueK6o1AWnIuTvhKkDpljnjfgtjBkggsnNpLpw5/SUdAIJi8Zu CjNp7t8ooG1xFuRch4lk340= Received: from mail.maildlp.com (unknown [172.19.162.254]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4d7CS04CMBzcZxm; Fri, 14 Nov 2025 18:05:04 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id B7E83180494; Fri, 14 Nov 2025 18:06:57 +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; Fri, 14 Nov 2025 18:06:57 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 6/9] erofs: introduce the page cache share feature Date: Fri, 14 Nov 2025 09:55:13 +0000 Message-ID: <20251114095516.207555-7-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo Currently, reading files with different paths (or names) but the same content will consume multiple copies of the page cache, even if the content of these page caches is the same. For example, reading identical files (e.g., *.so files) from two different minor versions of container images will cost multiple copies of the same page cache, since different containers have different mount points. Therefore, sharing the page cache for files with the same content can save memory. This introduces the page cache share feature in erofs. It allocate a deduplicated inode and use its page cache as shared. Reads for files with identical content will ultimately be routed to the page cache of the deduplicated inode. In this way, a single page cache satisfies multiple read requests for different files with the same contents. Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li --- fs/erofs/Makefile | 1 + fs/erofs/internal.h | 32 +++++- fs/erofs/ishare.c | 236 ++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/ishare.h | 28 ++++++ fs/erofs/super.c | 30 +++++- 5 files changed, 324 insertions(+), 3 deletions(-) create mode 100644 fs/erofs/ishare.c create mode 100644 fs/erofs/ishare.h diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 549abc424763..102a23bf5dec 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -10,3 +10,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) +=3D decompressor_zstd.o erofs-$(CONFIG_EROFS_FS_ZIP_ACCEL) +=3D decompressor_crypto.o erofs-$(CONFIG_EROFS_FS_BACKED_BY_FILE) +=3D fileio.o erofs-$(CONFIG_EROFS_FS_ONDEMAND) +=3D fscache.o +erofs-$(CONFIG_EROFS_FS_INODE_SHARE) +=3D ishare.o \ No newline at end of file diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 3ebbb7c5d085..26772458fda7 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -193,7 +193,7 @@ static inline bool erofs_is_fileio_mode(struct erofs_sb= _info *sbi) return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->dif0.file; } =20 -#if defined(CONFIG_EROFS_FS_ONDEMAND) +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_INODE_SHA= RE) extern struct file_system_type erofs_anon_fs_type; #endif =20 @@ -203,6 +203,19 @@ static inline bool erofs_is_fscache_mode(struct super_= block *sb) !erofs_is_fileio_mode(EROFS_SB(sb)) && !sb->s_bdev; } =20 +#if defined(CONFIG_EROFS_FS_INODE_SHARE) +static inline bool erofs_is_ishare_inode(struct inode *inode) +{ + /* we have assumed FS_ONDEMAND is excluded with FS_INODE_SHARE feature */ + return inode->i_sb->s_type =3D=3D &erofs_anon_fs_type; +} +#else +static inline bool erofs_is_ishare_inode(struct inode *inode) +{ + return false; +} +#endif + enum { EROFS_ZIP_CACHE_DISABLED, EROFS_ZIP_CACHE_READAHEAD, @@ -310,6 +323,22 @@ struct erofs_inode { }; #endif /* CONFIG_EROFS_FS_ZIP */ }; +#ifdef CONFIG_EROFS_FS_INODE_SHARE + union { + /* internal dedup inode */ + struct { + char *fingerprint; + spinlock_t lock; + /* all backing inodes */ + struct list_head backing_head; + }; + + struct { + struct inode *ishare; + struct list_head backing_link; + }; + }; +#endif /* the corresponding vfs inode */ struct inode vfs_inode; }; @@ -416,6 +445,7 @@ extern const struct inode_operations erofs_dir_iops; =20 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 z_erofs_iomap_report_ops; =20 diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c new file mode 100644 index 000000000000..910b732bf8e7 --- /dev/null +++ b/fs/erofs/ishare.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#include +#include +#include +#include +#include +#include "ishare.h" +#include "internal.h" +#include "xattr.h" + +static DEFINE_MUTEX(erofs_ishare_lock); +static struct vfsmount *erofs_ishare_mnt; +static refcount_t erofs_ishare_supers; + +int erofs_ishare_init(struct super_block *sb) +{ + struct vfsmount *mnt =3D NULL; + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + + if (!sbi->ishare_key) + return 0; + + mutex_lock(&erofs_ishare_lock); + if (erofs_ishare_mnt) { + refcount_inc(&erofs_ishare_supers); + } else { + mnt =3D kern_mount(&erofs_anon_fs_type); + if (!IS_ERR(mnt)) { + erofs_ishare_mnt =3D mnt; + refcount_set(&erofs_ishare_supers, 1); + } + } + mutex_unlock(&erofs_ishare_lock); + return IS_ERR(mnt) ? PTR_ERR(mnt) : 0; +} + +void erofs_ishare_exit(struct super_block *sb) +{ + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + struct vfsmount *tmp; + + if (!sbi->ishare_key || !erofs_ishare_mnt) + return; + + mutex_lock(&erofs_ishare_lock); + if (refcount_dec_and_test(&erofs_ishare_supers)) { + tmp =3D erofs_ishare_mnt; + erofs_ishare_mnt =3D NULL; + mutex_unlock(&erofs_ishare_lock); + kern_unmount(tmp); + mutex_lock(&erofs_ishare_lock); + } + mutex_unlock(&erofs_ishare_lock); + kfree(sbi->ishare_key); + sbi->ishare_key =3D NULL; +} + +static int erofs_ishare_iget5_eq(struct inode *inode, void *data) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + return vi->fingerprint && memcmp(vi->fingerprint, data, + sizeof(size_t) + *(size_t *)data) =3D=3D 0; +} + +static int erofs_ishare_iget5_set(struct inode *inode, void *data) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + vi->fingerprint =3D data; + INIT_LIST_HEAD(&vi->backing_head); + spin_lock_init(&vi->lock); + return 0; +} + +bool erofs_ishare_fill_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct erofs_sb_info *sbi =3D EROFS_SB(inode->i_sb); + struct inode *idedup; + /* + * fingerprint layout: + * fingerprint length + fingerprint content (xattr_value + domain_id) + */ + char *ishare_key =3D sbi->ishare_key, *fingerprint; + ssize_t ishare_vlen; + unsigned long hash; + int key_idx; + + if (!sbi->domain_id || !ishare_key) + return false; + + key_idx =3D sbi->ishare_key_idx; + ishare_vlen =3D erofs_getxattr(inode, key_idx, ishare_key, NULL, 0); + if (ishare_vlen <=3D 0 || ishare_vlen > (1 << sbi->blkszbits)) + return false; + + fingerprint =3D kmalloc(sizeof(ssize_t) + ishare_vlen + + strlen(sbi->domain_id), GFP_KERNEL); + if (!fingerprint) + return false; + + *(ssize_t *)fingerprint =3D ishare_vlen + strlen(sbi->domain_id); + if (ishare_vlen !=3D erofs_getxattr(inode, key_idx, ishare_key, + fingerprint + sizeof(ssize_t), + ishare_vlen)) { + kfree(fingerprint); + return false; + } + + memcpy(fingerprint + sizeof(ssize_t) + ishare_vlen, + sbi->domain_id, strlen(sbi->domain_id)); + hash =3D xxh32(fingerprint + sizeof(ssize_t), + ishare_vlen + strlen(sbi->domain_id), hash); + idedup =3D iget5_locked(erofs_ishare_mnt->mnt_sb, hash, + erofs_ishare_iget5_eq, erofs_ishare_iget5_set, + fingerprint); + if (!idedup) { + kfree(fingerprint); + return false; + } + + INIT_LIST_HEAD(&vi->backing_link); + vi->ishare =3D idedup; + spin_lock(&EROFS_I(idedup)->lock); + list_add(&vi->backing_link, &EROFS_I(idedup)->backing_head); + spin_unlock(&EROFS_I(idedup)->lock); + + if (!(idedup->i_state & I_NEW)) { + kfree(fingerprint); + return true; + } + + if (erofs_inode_is_data_compressed(vi->datalayout)) + idedup->i_mapping->a_ops =3D &z_erofs_aops; + else + idedup->i_mapping->a_ops =3D &erofs_aops; + idedup->i_mode =3D vi->vfs_inode.i_mode; + i_size_write(idedup, vi->vfs_inode.i_size); + unlock_new_inode(idedup); + return true; +} + +void erofs_ishare_free_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct inode *idedup =3D vi->ishare; + + if (!idedup) + return; + + spin_lock(&EROFS_I(idedup)->lock); + list_del(&vi->backing_link); + spin_unlock(&EROFS_I(idedup)->lock); + iput(idedup); + vi->ishare =3D NULL; +} + +static int erofs_ishare_file_open(struct inode *inode, struct file *file) +{ + struct file *realfile; + struct inode *dedup; + + dedup =3D EROFS_I(inode)->ishare; + if (!dedup) + return -EINVAL; + + realfile =3D alloc_file_pseudo(dedup, erofs_ishare_mnt, "erofs_ishare_fil= e", + O_RDONLY, &erofs_file_fops); + if (IS_ERR(realfile)) + return PTR_ERR(realfile); + + file_ra_state_init(&realfile->f_ra, file->f_mapping); + realfile->private_data =3D EROFS_I(inode); + file->private_data =3D realfile; + return 0; +} + +static int erofs_ishare_file_release(struct inode *inode, struct file *fil= e) +{ + struct file *realfile =3D file->private_data; + + if (!realfile) + return -EINVAL; + fput(realfile); + realfile->private_data =3D NULL; + return 0; +} + +static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb, + struct iov_iter *to) +{ + struct file *realfile =3D iocb->ki_filp->private_data; + struct inode *inode =3D file_inode(iocb->ki_filp); + struct kiocb dedup_iocb; + ssize_t nread; + + if (!realfile) + return -EINVAL; + if (!iov_iter_count(to)) + return 0; + + /* fallback to the original file in DAX or DIRECT mode */ + if (IS_DAX(inode) || (iocb->ki_flags & IOCB_DIRECT)) + realfile =3D iocb->ki_filp; + + kiocb_clone(&dedup_iocb, iocb, realfile); + nread =3D filemap_read(&dedup_iocb, to, 0); + iocb->ki_pos =3D dedup_iocb.ki_pos; + touch_atime(&iocb->ki_filp->f_path); + return nread; +} + +static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct file *realfile =3D file->private_data; + + if (!realfile) + return -EINVAL; + + vma_set_file(vma, realfile); + return generic_file_readonly_mmap(file, vma); +} + +const struct file_operations erofs_ishare_fops =3D { + .open =3D erofs_ishare_file_open, + .llseek =3D generic_file_llseek, + .read_iter =3D erofs_ishare_file_read_iter, + .mmap =3D erofs_ishare_mmap, + .release =3D erofs_ishare_file_release, + .get_unmapped_area =3D thp_get_unmapped_area, + .splice_read =3D filemap_splice_read, +}; diff --git a/fs/erofs/ishare.h b/fs/erofs/ishare.h new file mode 100644 index 000000000000..54f2251c8179 --- /dev/null +++ b/fs/erofs/ishare.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#ifndef __EROFS_ISHARE_H +#define __EROFS_ISHARE_H + +#include +#include +#include "internal.h" + +#ifdef CONFIG_EROFS_FS_INODE_SHARE + +int erofs_ishare_init(struct super_block *sb); +void erofs_ishare_exit(struct super_block *sb); +bool erofs_ishare_fill_inode(struct inode *inode); +void erofs_ishare_free_inode(struct inode *inode); + +#else + +static inline int erofs_ishare_init(struct super_block *sb) { return 0; } +static inline void erofs_ishare_exit(struct super_block *sb) {} +static inline bool erofs_ishare_fill_inode(struct inode *inode) { return f= alse; } +static inline void erofs_ishare_free_inode(struct inode *inode) {} + +#endif // CONFIG_EROFS_FS_INODE_SHARE + +#endif diff --git a/fs/erofs/super.c b/fs/erofs/super.c index ce95454c9ee7..613dfbe988de 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -13,6 +13,7 @@ #include #include #include "xattr.h" +#include "ishare.h" =20 #define CREATE_TRACE_POINTS #include @@ -81,6 +82,10 @@ static void erofs_free_inode(struct inode *inode) { struct erofs_inode *vi =3D EROFS_I(inode); =20 + if (erofs_is_ishare_inode(inode)) { + erofs_free_dedup_inode(vi); + return; + } if (inode->i_op =3D=3D &erofs_fast_symlink_iops) kfree(inode->i_link); kfree(vi->xattr_shared_xattrs); @@ -926,10 +931,31 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 -#if defined(CONFIG_EROFS_FS_ONDEMAND) +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_INODE_SHA= RE) +static void erofs_free_anon_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + +#ifdef CONFIG_EROFS_FS_INODE_SHARE + kfree(vi->fingerprint); +#endif + kmem_cache_free(erofs_inode_cachep, vi); +} + +static const struct super_operations erofs_anon_sops =3D { + .alloc_inode =3D erofs_alloc_inode, + .free_inode =3D erofs_free_anon_inode, +}; + static int erofs_anon_init_fs_context(struct fs_context *fc) { - return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM; + struct pseudo_fs_context *ctx; + + ctx =3D init_pseudo(fc, EROFS_SUPER_MAGIC); + if (ctx) + ctx->ops =3D &erofs_anon_sops; + + return ctx ? 0 : -ENOMEM; } =20 struct file_system_type erofs_anon_fs_type =3D { --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (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 00E4B3112DC; Fri, 14 Nov 2025 10:07:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114829; cv=none; b=hV1drxoQLGdB/WhxyiWdNtjDCSx21h/xACVyOLEgkRZdhvMX/+LiiTObFpyiK2EFQza5K8iv8mbcypYYuwdWrlGuZey6mSW2XyDJ/M6MAHLHKa8G6fdbs9fMQK3R4ZDooyChqfIz5V4QlsNFrSF5bzGdq2MbUd7pmwooKALHryE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114829; c=relaxed/simple; bh=6riCg433t7qB+ILg890ziYT/4uKm9DGv5PIHAzbHdcc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dx2EnCXMZp7zO2QSjjQDQ3vVdb6BrPt7DycpqznYBJ6GTXa0MaN+NkFf3Bcj/9uCjt1RvcECZUmdyxWh+6BWMDEIHFpVhQiToffS3q2doEGxEXCc/v23aWF6h+XUM+g4Q50RyBbysXLJt2rfl/Zkwj7q3QetmDhK+DTAhQZLhGI= 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=zhgrjLX0; arc=none smtp.client-ip=113.46.200.216 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="zhgrjLX0" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=5SLCY9E4I2eWPgxD26E2VWjjMx+WOcMowunKXjSKJWw=; b=zhgrjLX0Ib+b8Gec24sgIFt5T9xCuOX4EVC0Icwhkk/rC229+yaqDr/yS0WGmnIUtF+oWCDeU AUoMjik1tEh5wkTZq3kCitpAf/rChIkE3Pr6kx4XSg74ShiYmRIZ6msDXjjf8chMB33OxOGKIFt dXyqLkysfqyZt8yFq7MS740= Received: from mail.maildlp.com (unknown [172.19.163.48]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4d7CSX0knTz1T4g8; Fri, 14 Nov 2025 18:05:32 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 384DA180488; Fri, 14 Nov 2025 18:06:58 +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; Fri, 14 Nov 2025 18:06:57 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 7/9] erofs: support unencoded inodes for page cache share Date: Fri, 14 Nov 2025 09:55:14 +0000 Message-ID: <20251114095516.207555-8-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" This patch adds inode page cache sharing functionality for unencoded files. I conducted experiments in the container environment. Below is the memory usage for reading all files in two different minor versions of container images: +-------------------+------------------+-------------+---------------+ | Image | Page Cache Share | Memory (MB) | Memory | | | | | Reduction (%) | +-------------------+------------------+-------------+---------------+ | | No | 241 | - | | redis +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 163 | 33% | +-------------------+------------------+-------------+---------------+ | | No | 872 | - | | postgres +------------------+-------------+---------------+ | 16.1 & 16.2 | Yes | 630 | 28% | +-------------------+------------------+-------------+---------------+ | | No | 2771 | - | | tensorflow +------------------+-------------+---------------+ | 2.11.0 & 2.11.1 | Yes | 2340 | 16% | +-------------------+------------------+-------------+---------------+ | | No | 926 | - | | mysql +------------------+-------------+---------------+ | 8.0.11 & 8.0.12 | Yes | 735 | 21% | +-------------------+------------------+-------------+---------------+ | | No | 390 | - | | nginx +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 219 | 44% | +-------------------+------------------+-------------+---------------+ | tomcat | No | 924 | - | | 10.1.25 & 10.1.26 +------------------+-------------+---------------+ | | Yes | 474 | 49% | +-------------------+------------------+-------------+---------------+ Additionally, the table below shows the runtime memory usage of the container: +-------------------+------------------+-------------+---------------+ | Image | Page Cache Share | Memory (MB) | Memory | | | | | Reduction (%) | +-------------------+------------------+-------------+---------------+ | | No | 35 | - | | redis +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 28 | 20% | +-------------------+------------------+-------------+---------------+ | | No | 149 | - | | postgres +------------------+-------------+---------------+ | 16.1 & 16.2 | Yes | 95 | 37% | +-------------------+------------------+-------------+---------------+ | | No | 1028 | - | | tensorflow +------------------+-------------+---------------+ | 2.11.0 & 2.11.1 | Yes | 930 | 10% | +-------------------+------------------+-------------+---------------+ | | No | 155 | - | | mysql +------------------+-------------+---------------+ | 8.0.11 & 8.0.12 | Yes | 132 | 15% | +-------------------+------------------+-------------+---------------+ | | No | 25 | - | | nginx +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 20 | 20% | +-------------------+------------------+-------------+---------------+ | tomcat | No | 186 | - | | 10.1.25 & 10.1.26 +------------------+-------------+---------------+ | | Yes | 98 | 48% | +-------------------+------------------+-------------+---------------+ Co-developed-by: Hongzhen Luo Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li --- fs/erofs/data.c | 38 +++++++++++++++--- fs/erofs/inode.c | 5 +++ fs/erofs/internal.h | 4 ++ fs/erofs/ishare.c | 98 ++++++++++++++++++++++++++++++++++++++++++++- fs/erofs/ishare.h | 18 +++++++++ fs/erofs/super.c | 11 +++-- 6 files changed, 163 insertions(+), 11 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index bd3d85c61341..c459104e4734 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -5,6 +5,7 @@ * Copyright (C) 2021, Alibaba Cloud */ #include "internal.h" +#include "ishare.h" #include #include =20 @@ -269,23 +270,27 @@ void erofs_onlinefolio_end(struct folio *folio, int e= rr, bool dirty) struct erofs_iomap_iter_ctx { struct page *page; void *base; + struct inode *realinode; }; =20 static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t le= ngth, unsigned int flags, struct iomap *iomap, struct iomap *srcmap) { - int ret; struct erofs_iomap_iter_ctx *ctx; - struct super_block *sb =3D inode->i_sb; struct erofs_map_blocks map; struct erofs_map_dev mdev; struct iomap_iter *iter; + struct inode *realinode; + struct super_block *sb; + int ret; =20 iter =3D container_of(iomap, struct iomap_iter, iomap); ctx =3D iter->private; + realinode =3D ctx ? ctx->realinode : inode; + sb =3D realinode->i_sb; map.m_la =3D offset; map.m_llen =3D length; - ret =3D erofs_map_blocks(inode, &map); + ret =3D erofs_map_blocks(realinode, &map); if (ret < 0) return ret; =20 @@ -300,7 +305,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_= t offset, loff_t length, return 0; } =20 - if (!(map.m_flags & EROFS_MAP_META) || !erofs_inode_in_metabox(inode)) { + if (!(map.m_flags & EROFS_MAP_META) || !erofs_inode_in_metabox(realinode)= ) { mdev =3D (struct erofs_map_dev) { .m_deviceid =3D map.m_deviceid, .m_pa =3D map.m_pa, @@ -326,7 +331,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_= t offset, loff_t length, struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; =20 ptr =3D erofs_read_metabuf(&buf, sb, map.m_pa, - erofs_inode_in_metabox(inode)); + erofs_inode_in_metabox(realinode)); if (IS_ERR(ptr)) return PTR_ERR(ptr); iomap->inline_data =3D ptr; @@ -384,6 +389,7 @@ int erofs_fiemap(struct inode *inode, struct fiemap_ext= ent_info *fieinfo, */ static int erofs_read_folio(struct file *file, struct folio *folio) { + struct inode *inode =3D folio_inode(folio); struct iomap_read_folio_ctx read_ctx =3D { .ops =3D &iomap_bio_read_ops, .cur_folio =3D folio, @@ -391,16 +397,27 @@ static int erofs_read_folio(struct file *file, struct= folio *folio) struct erofs_iomap_iter_ctx iter_ctx =3D { .page =3D NULL, .base =3D NULL, + .realinode =3D erofs_ishare_iget(inode), + }; + struct erofs_read_ctx rdctx =3D { + .file =3D file, + .inode =3D inode, }; =20 + if (!iter_ctx.realinode) + return -EIO; trace_erofs_read_folio(folio, true); =20 + erofs_read_begin(&rdctx); iomap_read_folio(&erofs_iomap_ops, &read_ctx, &iter_ctx); + erofs_read_end(&rdctx); + erofs_ishare_iput(iter_ctx.realinode); return 0; } =20 static void erofs_readahead(struct readahead_control *rac) { + struct inode *inode =3D rac->mapping->host; struct iomap_read_folio_ctx read_ctx =3D { .ops =3D &iomap_bio_read_ops, .rac =3D rac, @@ -408,12 +425,22 @@ static void erofs_readahead(struct readahead_control = *rac) struct erofs_iomap_iter_ctx iter_ctx =3D { .page =3D NULL, .base =3D NULL, + .realinode =3D erofs_ishare_iget(inode), + }; + struct erofs_read_ctx rdctx =3D { + .file =3D rac->file, + .inode =3D inode, }; =20 + if (!iter_ctx.realinode) + return; trace_erofs_readahead(rac->mapping->host, readahead_index(rac), readahead_count(rac), true); =20 + erofs_read_begin(&rdctx); iomap_readahead(&erofs_iomap_ops, &read_ctx, &iter_ctx); + erofs_read_end(&rdctx); + erofs_ishare_iput(iter_ctx.realinode); } =20 static sector_t erofs_bmap(struct address_space *mapping, sector_t block) @@ -437,6 +464,7 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb,= struct iov_iter *to) struct erofs_iomap_iter_ctx iter_ctx =3D { .page =3D NULL, .base =3D NULL, + .realinode =3D inode, }; =20 return iomap_dio_rw(iocb, to, &erofs_iomap_ops, diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index cb780c095d28..fe45e6c18f8e 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -5,6 +5,7 @@ * Copyright (C) 2021, Alibaba Cloud */ #include "xattr.h" +#include "ishare.h" #include #include =20 @@ -215,6 +216,10 @@ static int erofs_fill_inode(struct inode *inode) case S_IFREG: inode->i_op =3D &erofs_generic_iops; inode->i_fop =3D &erofs_file_fops; +#ifdef CONFIG_EROFS_FS_INODE_SHARE + if (erofs_ishare_fill_inode(inode)) + inode->i_fop =3D &erofs_ishare_fops; +#endif break; case S_IFDIR: inode->i_op =3D &erofs_dir_iops; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 26772458fda7..6f7d441955c6 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -331,11 +331,15 @@ struct erofs_inode { spinlock_t lock; /* all backing inodes */ struct list_head backing_head; + /* processing list */ + struct list_head processing_head; }; =20 struct { struct inode *ishare; struct list_head backing_link; + struct list_head processing_link; + atomic_t processing_count; }; }; #endif diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index 910b732bf8e7..14b2690055c5 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -72,6 +72,7 @@ static int erofs_ishare_iget5_set(struct inode *inode, vo= id *data) =20 vi->fingerprint =3D data; INIT_LIST_HEAD(&vi->backing_head); + INIT_LIST_HEAD(&vi->processing_head); spin_lock_init(&vi->lock); return 0; } @@ -124,7 +125,9 @@ bool erofs_ishare_fill_inode(struct inode *inode) } =20 INIT_LIST_HEAD(&vi->backing_link); + INIT_LIST_HEAD(&vi->processing_link); vi->ishare =3D idedup; + spin_lock(&EROFS_I(idedup)->lock); list_add(&vi->backing_link, &EROFS_I(idedup)->backing_head); spin_unlock(&EROFS_I(idedup)->lock); @@ -163,17 +166,28 @@ static int erofs_ishare_file_open(struct inode *inode= , struct file *file) { struct file *realfile; struct inode *dedup; + char *buf, *filepath; =20 dedup =3D EROFS_I(inode)->ishare; if (!dedup) return -EINVAL; =20 - realfile =3D alloc_file_pseudo(dedup, erofs_ishare_mnt, "erofs_ishare_fil= e", + buf =3D kmalloc(PATH_MAX, GFP_KERNEL); + if (!buf) + return -ENOMEM; + filepath =3D file_path(file, buf, PATH_MAX); + if (IS_ERR(filepath)) { + kfree(buf); + return -PTR_ERR(filepath); + } + realfile =3D alloc_file_pseudo(dedup, erofs_ishare_mnt, filepath + 1, O_RDONLY, &erofs_file_fops); + kfree(buf); if (IS_ERR(realfile)) return PTR_ERR(realfile); =20 file_ra_state_init(&realfile->f_ra, file->f_mapping); + ihold(dedup); realfile->private_data =3D EROFS_I(inode); file->private_data =3D realfile; return 0; @@ -185,8 +199,8 @@ static int erofs_ishare_file_release(struct inode *inod= e, struct file *file) =20 if (!realfile) return -EINVAL; + file->private_data =3D NULL; fput(realfile); - realfile->private_data =3D NULL; return 0; } =20 @@ -234,3 +248,83 @@ const struct file_operations erofs_ishare_fops =3D { .get_unmapped_area =3D thp_get_unmapped_area, .splice_read =3D filemap_splice_read, }; + +void erofs_read_begin(struct erofs_read_ctx *rdctx) +{ + struct erofs_inode *vi, *vi_dedup; + + if (!rdctx->file || !erofs_is_ishare_inode(rdctx->inode)) + return; + + vi =3D rdctx->file->private_data; + vi_dedup =3D EROFS_I(file_inode(rdctx->file)); + + spin_lock(&vi_dedup->lock); + if (!list_empty(&vi->processing_link)) { + atomic_inc(&vi->processing_count); + } else { + list_add(&vi->processing_link, + &vi_dedup->processing_head); + atomic_set(&vi->processing_count, 1); + } + spin_unlock(&vi_dedup->lock); +} + +void erofs_read_end(struct erofs_read_ctx *rdctx) +{ + struct erofs_inode *vi, *vi_dedup; + + if (!rdctx->file || !erofs_is_ishare_inode(rdctx->inode)) + return; + + vi =3D rdctx->file->private_data; + vi_dedup =3D EROFS_I(file_inode(rdctx->file)); + + spin_lock(&vi_dedup->lock); + if (atomic_dec_and_test(&vi->processing_count)) + list_del_init(&vi->processing_link); + spin_unlock(&vi_dedup->lock); +} + +/* + * erofs_ishare_iget - find the backing inode. + */ +struct inode *erofs_ishare_iget(struct inode *inode) +{ + struct erofs_inode *vi, *vi_dedup; + struct inode *realinode; + + if (!erofs_is_ishare_inode(inode)) + return igrab(inode); + + vi_dedup =3D EROFS_I(inode); + spin_lock(&vi_dedup->lock); + /* try processing inodes first */ + if (!list_empty(&vi_dedup->processing_head)) { + list_for_each_entry(vi, &vi_dedup->processing_head, + processing_link) { + realinode =3D igrab(&vi->vfs_inode); + if (realinode) { + spin_unlock(&vi_dedup->lock); + return realinode; + } + } + } + + /* fall back to all backing inodes */ + DBG_BUGON(list_empty(&vi_dedup->backing_head)); + list_for_each_entry(vi, &vi_dedup->backing_head, backing_link) { + realinode =3D igrab(&vi->vfs_inode); + if (realinode) + break; + } + spin_unlock(&vi_dedup->lock); + + DBG_BUGON(!realinode); + return realinode; +} + +void erofs_ishare_iput(struct inode *realinode) +{ + iput(realinode); +} diff --git a/fs/erofs/ishare.h b/fs/erofs/ishare.h index 54f2251c8179..b85fa240507b 100644 --- a/fs/erofs/ishare.h +++ b/fs/erofs/ishare.h @@ -9,6 +9,11 @@ #include #include "internal.h" =20 +struct erofs_read_ctx { + struct file *file; /* may be NULL */ + struct inode *inode; +}; + #ifdef CONFIG_EROFS_FS_INODE_SHARE =20 int erofs_ishare_init(struct super_block *sb); @@ -16,6 +21,13 @@ void erofs_ishare_exit(struct super_block *sb); bool erofs_ishare_fill_inode(struct inode *inode); void erofs_ishare_free_inode(struct inode *inode); =20 +/* read/readahead */ +void erofs_read_begin(struct erofs_read_ctx *rdctx); +void erofs_read_end(struct erofs_read_ctx *rdctx); + +struct inode *erofs_ishare_iget(struct inode *inode); +void erofs_ishare_iput(struct inode *realinode); + #else =20 static inline int erofs_ishare_init(struct super_block *sb) { return 0; } @@ -23,6 +35,12 @@ static inline void erofs_ishare_exit(struct super_block = *sb) {} static inline bool erofs_ishare_fill_inode(struct inode *inode) { return f= alse; } static inline void erofs_ishare_free_inode(struct inode *inode) {} =20 +static inline void erofs_read_begin(struct erofs_read_ctx *rdctx) {} +static inline void erofs_read_end(struct erofs_read_ctx *rdctx) {} + +static inline struct inode *erofs_ishare_iget(struct inode *inode) { retur= n inode; } +static inline void erofs_ishare_iput(struct inode *realinode) {} + #endif // CONFIG_EROFS_FS_INODE_SHARE =20 #endif diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 613dfbe988de..2af82171dd78 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -82,10 +82,6 @@ static void erofs_free_inode(struct inode *inode) { struct erofs_inode *vi =3D EROFS_I(inode); =20 - if (erofs_is_ishare_inode(inode)) { - erofs_free_dedup_inode(vi); - return; - } if (inode->i_op =3D=3D &erofs_fast_symlink_iops) kfree(inode->i_link); kfree(vi->xattr_shared_xattrs); @@ -753,6 +749,10 @@ static int erofs_fc_fill_super(struct super_block *sb,= struct fs_context *fc) if (err) return err; =20 + err =3D erofs_ishare_init(sb); + if (err) + return err; + sbi->dir_ra_bytes =3D EROFS_DIR_RA_BYTES; erofs_info(sb, "mounted with root inode @ nid %llu.", sbi->root_nid); return 0; @@ -902,6 +902,7 @@ static void erofs_kill_sb(struct super_block *sb) kill_anon_super(sb); else kill_block_super(sb); + erofs_drop_internal_inodes(sbi); fs_put_dax(sbi->dif0.dax_dev, NULL); erofs_fscache_unregister_fs(sb); @@ -913,6 +914,7 @@ static void erofs_put_super(struct super_block *sb) { struct erofs_sb_info *const sbi =3D EROFS_SB(sb); =20 + erofs_ishare_exit(sb); erofs_unregister_sysfs(sb); erofs_shrinker_unregister(sb); erofs_xattr_prefixes_cleanup(sb); @@ -1081,6 +1083,7 @@ static void erofs_evict_inode(struct inode *inode) dax_break_layout_final(inode); #endif =20 + erofs_ishare_free_inode(inode); truncate_inode_pages_final(&inode->i_data); clear_inode(inode); } --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout02.his.huawei.com (canpmsgout02.his.huawei.com [113.46.200.217]) (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 C3AD530C612; Fri, 14 Nov 2025 10:07:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.217 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114823; cv=none; b=JiwH/j5fKBpeH2y6dcj8rAdhyDu2uUUhemr0Wqito35R1zS68o7BFpfp7+IXGvtHLzE+jWO2cRAMAWCqao6knkVOhD5J5LPmVQX3UhgzLJuLl27AUTmAvro3Canj65b4vOrvRkTLpnXcVkYyxTZ9tg0GLH0DzR38MR0UE1l4YmY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114823; c=relaxed/simple; bh=xve2+kGFZTHOkYxgH0jMxSX7r2TIOgzhdqgWX8GsFUQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nj1BJUdql/KUc4qs7S+iZb8issNSDiBoCWVNit7ttZGs/X1GsBcSFl+4mWdK0BwDhhHiJwbvNpQu7O/EdUJBgrcs16cAVuaezO5L0jZ8tcshZ9j0yFgVpnmW539ZZTcxD9QdqL7yTohkdfDLr9O1P6vJ2CEmeqluWLfmb1t/L/8= 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=zn+ICcYV; arc=none smtp.client-ip=113.46.200.217 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="zn+ICcYV" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=RShWmYYNSN4Yj3X7d1YRg7N32NEFA8HDJI2iwIW57nI=; b=zn+ICcYVW4epIJeGzk2AYE4IOT+gunL5IDen0QO4WHmfA4EMIzusgd/lPJbmuEwX/FbrJppR1 F5dC19t/erFefncoDe/oqD496VViYr8Eq/UjIRpXN+RGgtY5/BjCwOMvQPv3FXNTV5/tLPW7C1S u6j0JjyzU31qIR1hQiX4gpI= Received: from mail.maildlp.com (unknown [172.19.88.105]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4d7CS13sLTzcb1n; Fri, 14 Nov 2025 18:05:05 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id B0ABA140136; Fri, 14 Nov 2025 18:06:58 +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; Fri, 14 Nov 2025 18:06:58 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 8/9] erofs: support compressed inodes for page cache share Date: Fri, 14 Nov 2025 09:55:15 +0000 Message-ID: <20251114095516.207555-9-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo This patch adds page cache sharing functionality for compressed inodes. Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li --- fs/erofs/zdata.c | 56 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index bc80cfe482f7..e76421de86cb 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -5,6 +5,7 @@ * Copyright (C) 2022 Alibaba Cloud */ #include "compress.h" +#include "ishare.h" #include #include #include @@ -493,7 +494,7 @@ enum z_erofs_pclustermode { }; =20 struct z_erofs_frontend { - struct inode *const inode; + struct inode *inode; struct erofs_map_blocks map; struct z_erofs_bvec_iter biter; =20 @@ -1870,10 +1871,24 @@ static void z_erofs_pcluster_readmore(struct z_erof= s_frontend *f, =20 static int z_erofs_read_folio(struct file *file, struct folio *folio) { - struct inode *const inode =3D folio->mapping->host; - Z_EROFS_DEFINE_FRONTEND(f, inode, folio_pos(folio)); + struct inode *const inode =3D folio->mapping->host, *realinode; + Z_EROFS_DEFINE_FRONTEND(f, NULL, folio_pos(folio)); + struct erofs_read_ctx rdctx =3D { + .file =3D file, + .inode =3D inode, + }; int err; =20 + trace_erofs_read_folio(folio, false); + + erofs_read_begin(&rdctx); + + if (erofs_is_ishare_inode(inode)) + realinode =3D erofs_ishare_iget(inode); + else + realinode =3D inode; + + f.inode =3D realinode; trace_erofs_read_folio(folio, false); z_erofs_pcluster_readmore(&f, NULL, true); err =3D z_erofs_scan_folio(&f, folio, false); @@ -1883,23 +1898,39 @@ static int z_erofs_read_folio(struct file *file, st= ruct folio *folio) /* if some pclusters are ready, need submit them anyway */ err =3D z_erofs_runqueue(&f, 0) ?: err; if (err && err !=3D -EINTR) - erofs_err(inode->i_sb, "read error %d @ %lu of nid %llu", - err, folio->index, EROFS_I(inode)->nid); + erofs_err(realinode->i_sb, "read error %d @ %lu of nid %llu", + err, folio->index, EROFS_I(realinode)->nid); =20 erofs_put_metabuf(&f.map.buf); erofs_release_pages(&f.pagepool); + + if (erofs_is_ishare_inode(inode)) + erofs_ishare_iput(realinode); + + erofs_read_end(&rdctx); return err; } =20 static void z_erofs_readahead(struct readahead_control *rac) { - struct inode *const inode =3D rac->mapping->host; - Z_EROFS_DEFINE_FRONTEND(f, inode, readahead_pos(rac)); + struct inode *const inode =3D rac->mapping->host, *realinode; + Z_EROFS_DEFINE_FRONTEND(f, NULL, readahead_pos(rac)); unsigned int nrpages =3D readahead_count(rac); struct folio *head =3D NULL, *folio; + struct erofs_read_ctx rdctx =3D { + .file =3D rac->file, + .inode =3D inode, + }; int err; =20 - trace_erofs_readahead(inode, readahead_index(rac), nrpages, false); + erofs_read_begin(&rdctx); + if (erofs_is_ishare_inode(inode)) + realinode =3D erofs_ishare_iget(inode); + else + realinode =3D inode; + + f.inode =3D realinode; + trace_erofs_readahead(realinode, readahead_index(rac), nrpages, false); z_erofs_pcluster_readmore(&f, rac, true); while ((folio =3D readahead_folio(rac))) { folio->private =3D head; @@ -1913,8 +1944,8 @@ static void z_erofs_readahead(struct readahead_contro= l *rac) =20 err =3D z_erofs_scan_folio(&f, folio, true); if (err && err !=3D -EINTR) - erofs_err(inode->i_sb, "readahead error at folio %lu @ nid %llu", - folio->index, EROFS_I(inode)->nid); + erofs_err(realinode->i_sb, "readahead error at folio %lu @ nid %llu", + folio->index, EROFS_I(realinode)->nid); } z_erofs_pcluster_readmore(&f, rac, false); z_erofs_pcluster_end(&f); @@ -1922,6 +1953,11 @@ static void z_erofs_readahead(struct readahead_contr= ol *rac) (void)z_erofs_runqueue(&f, nrpages); erofs_put_metabuf(&f.map.buf); erofs_release_pages(&f.pagepool); + + if (erofs_is_ishare_inode(inode)) + erofs_ishare_iput(realinode); + + erofs_read_end(&rdctx); } =20 const struct address_space_operations z_erofs_aops =3D { --=20 2.22.0 From nobody Mon Feb 9 04:45:32 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (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 00DC63112D3; Fri, 14 Nov 2025 10:07:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114828; cv=none; b=FEKD3MmanVGQaO5sNzDd3emzZ/Fr2B/5+Jelu2/ybrQpxisjRtSYjFDBWVZTTw2mC2nJIt2vRoKaRxF3TJc0rMJ4URSQnyoOgFBeHZ7Qqk9OIFpxmjDYuOv3xx6umNV6n2NMEZCnfP/2KjwYrixUwKydxBEy7OTR9fpcJGPRx2U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763114828; c=relaxed/simple; bh=PUhMmJO3qrxkT0LDtv6TTprBoAA6+lK6CQ814PKAuP8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ATgYSioRx865ianoCGVC0FNUXyIaclZYjguzxRIu2WX7aS4R3mStrSQ2Y5nxNzOWsRswkdLV2Y22oTfzwF99C/S/XR4/qrOKmCzUtKEke05r5tIOwbAlvhGnlTvxUJcm48GRs1D8BUBBbMHe/USzjO2xu6Pbq/eiLx6VSLlaMCw= 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=WVWfC3KE; arc=none smtp.client-ip=113.46.200.216 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="WVWfC3KE" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=BCMyMCc7n0nJXxkfnxnWAQQyWIQKmftwqT0fy6ncGbk=; b=WVWfC3KEX4PuA9XOjVyZAaI2g+IXsviDtdLkgbyYyZI6oOob1B41G98KeAM5E95fvEhkAsT4x Rg+tJUH32VmAMkhqU9bjTFCa/DrJkkt5Dtc2ARBRvGOzoZgR+Thxv50rDCNXSjftWMLzYrnauEN TyT33ug2g5rwWACxr56kQpQ= Received: from mail.maildlp.com (unknown [172.19.163.48]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4d7CSY0WNLz1T4g8; Fri, 14 Nov 2025 18:05:33 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 2BE6318048B; Fri, 14 Nov 2025 18:06:59 +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; Fri, 14 Nov 2025 18:06:58 +0800 From: Hongbo Li To: , , , , , CC: , , Subject: [PATCH v8 9/9] erofs: implement .fadvise for page cache share Date: Fri, 14 Nov 2025 09:55:16 +0000 Message-ID: <20251114095516.207555-10-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251114095516.207555-1-lihongbo22@huawei.com> References: <20251114095516.207555-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: kwepems500001.china.huawei.com (7.221.188.70) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo This patch implements the .fadvise interface for page cache share. Similar to overlayfs, it drops those clean, unused pages through vfs_fadvise(). Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/ishare.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index 14b2690055c5..88c4af3f8993 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -239,6 +239,16 @@ static int erofs_ishare_mmap(struct file *file, struct= vm_area_struct *vma) return generic_file_readonly_mmap(file, vma); } =20 +static int erofs_ishare_fadvice(struct file *file, loff_t offset, + loff_t len, int advice) +{ + struct file *realfile =3D file->private_data; + + if (!realfile) + return -EINVAL; + return vfs_fadvise(realfile, offset, len, advice); +} + const struct file_operations erofs_ishare_fops =3D { .open =3D erofs_ishare_file_open, .llseek =3D generic_file_llseek, @@ -247,6 +257,7 @@ const struct file_operations erofs_ishare_fops =3D { .release =3D erofs_ishare_file_release, .get_unmapped_area =3D thp_get_unmapped_area, .splice_read =3D filemap_splice_read, + .fadvise =3D erofs_ishare_fadvice, }; =20 void erofs_read_begin(struct erofs_read_ctx *rdctx) --=20 2.22.0