Re: [PATCH RFC 08/14] fs/erofs: use folio_attach/detach_private() instead of direct assignment
"Zi Yan" <[email protected]> Tue, 04 Aug 2026 22:41:23 -0400
| Newsgroups | org.ozlabs.lists.linux-erofs,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On Mon Aug 3, 2026 at 7:40 PM EDT, Gao Xiang wrote: > Hi Zi, > > On Fri, Jul 31, 2026 at 10:13:31PM -0400, Zi Yan wrote: >> erofs_onelinefolio_init/split/end() use folio->private without setting >> PG_private or increase folio refcount and it works. But after PG_private= is >> replaced by checking folio->private in a future commit, it can break >> folio_expected_ref_count(), since the folio has private data without >> elevated refcount. Change it now. >>=20 >> It prepares for a future commit that removes PG_private. >>=20 >> No funtional change intended. >>=20 >> Assisted-by: Claude:claude-opus-4-8 >> Assisted-by: Codex:gpt-5 >> Signed-off-by: Zi Yan <[email protected]> >> To: Gao Xiang <[email protected]> >> To: Chao Yu <[email protected]> >> Cc: Yue Hu <[email protected]> >> Cc: Jeffle Xu <[email protected]> >> Cc: Sandeep Dhavale <[email protected]> >> Cc: Hongbo Li <[email protected]> >> Cc: Chunhai Guo <[email protected]> >> Cc: [email protected] >> Cc: [email protected] > > It looks fine as long as PG_private flag will be removed in the > follow-up patches: > Hi Gao, Sashiko spot an issue in this patch[1]. Basically, ->private can be 0 if I/O completes without any issue or being dirty and it causes folio_detach_private() not to folio_put(). My fix is to add a bias, 1, to the counter, so that ->private stays non NULL throughout online folio process. The revised patch is below. Let me know your thoughts. Thanks. [1] https://sashiko.dev/#/patchset/20260731-remove-pg_private-v1-0-142c97ba= 3562%40nvidia.com?part=3D8 From d8fadd13fee03e72c03a718af65ed41927ccbcca Mon Sep 17 00:00:00 2001 From: Zi Yan <[email protected]> Date: Thu, 30 Jul 2026 11:04:00 -0400 Subject: [PATCH] erofs: use folio_attach/detach_private() instead of direct assignment erofs_onlinefolio_init/split/end() use folio->private without setting PG_private or increasing folio refcount and it works. But after PG_private is replaced by checking folio->private in a future commit, it can break folio_expected_ref_count(), since the folio has private data without elevated refcount. Change them to use folio_attach/detach_private(). Furthermore, because folio->private is used to store in-flight I/O counter and the counter reaches 0 when all I/O completes successfully without error or being dirty, ->private=3D0 causes folio_detach_private() to not drop the elevated folio refcount. Solve this issue by using bias=3D1 for the counter= , so that ->private stays non NULL throughout every attach-to-detach process. Add a macro EROFS_ONLINEFOLIO_BIAS=3D1. While at it, fix the comment about ->private bit layout and add EROFS_ONLINEFOLIO_COUNT_MASK. It prepares for a future commit that removes PG_private. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Codex:gpt-5 Signed-off-by: Zi Yan <[email protected]> To: Gao Xiang <[email protected]> To: Chao Yu <[email protected]> Cc: Yue Hu <[email protected]> Cc: Jeffle Xu <[email protected]> Cc: Sandeep Dhavale <[email protected]> Cc: Hongbo Li <[email protected]> Cc: Chunhai Guo <[email protected]> Cc: [email protected] Cc: [email protected] --- fs/erofs/data.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 9aa48c8d67d12..81e9dab247e0f 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -251,19 +251,23 @@ int erofs_map_dev(struct super_block *sb, struct erof= s_map_dev *map) /* * bit 30: I/O error occurred on this folio * bit 29: CPU has dirty data in D-cache (needs aliasing handling); - * bit 0 - 29: remaining parts to complete this folio + * bit 0 - 28: remaining parts to complete this folio, biased by 1 so that + * ->private stays non-NULL while the folio is attached */ #define EROFS_ONLINEFOLIO_EIO 30 #define EROFS_ONLINEFOLIO_DIRTY 29 +#define EROFS_ONLINEFOLIO_COUNT_MASK (BIT(EROFS_ONLINEFOLIO_DIRTY) - 1) +#define EROFS_ONLINEFOLIO_BIAS 1 =20 void erofs_onlinefolio_init(struct folio *folio) { union { atomic_t o; void *v; - } u =3D { .o =3D ATOMIC_INIT(1) }; + } u =3D { .o =3D ATOMIC_INIT(1 + EROFS_ONLINEFOLIO_BIAS) }; =20 - folio->private =3D u.v; /* valid only if file-backed folio is locked */ + /* valid only if file-backed folio is locked */ + folio_attach_private(folio, u.v); } =20 void erofs_onlinefolio_split(struct folio *folio) @@ -277,14 +281,14 @@ void erofs_onlinefolio_end(struct folio *folio, int e= rr, bool dirty) =20 do { orig =3D atomic_read((atomic_t *)&folio->private); - DBG_BUGON(orig <=3D 0); + DBG_BUGON((orig & EROFS_ONLINEFOLIO_COUNT_MASK) <=3D EROFS_ONLINEFOLIO_B= IAS); v =3D dirty << EROFS_ONLINEFOLIO_DIRTY; v |=3D (orig - 1) | (!!err << EROFS_ONLINEFOLIO_EIO); } while (atomic_cmpxchg((atomic_t *)&folio->private, orig, v) !=3D orig); =20 - if (v & (BIT(EROFS_ONLINEFOLIO_DIRTY) - 1)) + if ((v & EROFS_ONLINEFOLIO_COUNT_MASK) !=3D EROFS_ONLINEFOLIO_BIAS) return; - folio->private =3D 0; + folio_detach_private(folio); if (v & BIT(EROFS_ONLINEFOLIO_DIRTY)) flush_dcache_folio(folio); folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO))); --=20 2.53.0 --=20 Best Regards, Yan, Zi