* [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents
@ 2025-10-09 15:49 Deepanshu Kartikey
2025-10-09 16:18 ` Mark Fasheh
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Deepanshu Kartikey @ 2025-10-09 15:49 UTC (permalink / raw)
To: mark, jlbec, joseph.qi
Cc: ocfs2-devel, linux-kernel, Deepanshu Kartikey,
syzbot+6fdd8fa3380730a4b22c
The extent map cache can become stale when extents are moved or
defragmented, causing subsequent operations to see outdated extent
flags. This triggers a BUG_ON in ocfs2_refcount_cal_cow_clusters().
The problem occurs when:
1. copy_file_range() creates a reflinked extent with OCFS2_EXT_REFCOUNTED
2. ioctl(FITRIM) triggers ocfs2_move_extents()
3. __ocfs2_move_extents_range() reads and caches the extent (flags=0x2)
4. ocfs2_move_extent()/ocfs2_defrag_extent() calls __ocfs2_move_extent()
which clears OCFS2_EXT_REFCOUNTED flag on disk (flags=0x0)
5. The extent map cache is not invalidated after the move
6. Later write() operations read stale cached flags (0x2) but disk has
updated flags (0x0), causing a mismatch
7. BUG_ON(!(rec->e_flags & OCFS2_EXT_REFCOUNTED)) triggers
Fix by clearing the extent map cache after each extent move/defrag
operation in __ocfs2_move_extents_range(). This ensures subsequent
operations read fresh extent data from disk.
Link: https://lore.kernel.org/all/20251009142917.517229-1-kartikey406@gmail.com/T/
Reported-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
Tested-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?id=2959889e1f6e216585ce522f7e8bc002b46ad9e7
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
Changes in v2:
- Fix moved to __ocfs2_move_extents_range() instead of ocfs2_refcount_cow()
- The real issue is in FITRIM/move_extents code path, not COW path
- COW path already clears cache at end of ocfs2_refcount_cow_hunk()
fs/ocfs2/move_extents.c | 5 +++++
1 file changed, 5 insertions(+)
---
fs/ocfs2/move_extents.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index 86f2631e6360..10923bf7c8b8 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -867,6 +867,11 @@ static int __ocfs2_move_extents_range(struct buffer_head *di_bh,
mlog_errno(ret);
goto out;
}
+ /*
+ * Invalidate extent cache after moving/defragging to prevent
+ * stale cached data with outdated extent flags.
+ */
+ ocfs2_extent_map_trunc(inode, cpos);
context->clusters_moved += alloc_size;
next:
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents
2025-10-09 15:49 [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents Deepanshu Kartikey
@ 2025-10-09 16:18 ` Mark Fasheh
2025-10-10 1:21 ` Joseph Qi
2025-10-10 1:37 ` Andrew Morton
2 siblings, 0 replies; 6+ messages in thread
From: Mark Fasheh @ 2025-10-09 16:18 UTC (permalink / raw)
To: Deepanshu Kartikey
Cc: jlbec, joseph.qi, ocfs2-devel, linux-kernel,
syzbot+6fdd8fa3380730a4b22c
On Thu, Oct 9, 2025 at 8:49 AM Deepanshu Kartikey <kartikey406@gmail.com> wrote:
>
> The extent map cache can become stale when extents are moved or
> defragmented, causing subsequent operations to see outdated extent
> flags. This triggers a BUG_ON in ocfs2_refcount_cal_cow_clusters().
>
> The problem occurs when:
> 1. copy_file_range() creates a reflinked extent with OCFS2_EXT_REFCOUNTED
> 2. ioctl(FITRIM) triggers ocfs2_move_extents()
> 3. __ocfs2_move_extents_range() reads and caches the extent (flags=0x2)
> 4. ocfs2_move_extent()/ocfs2_defrag_extent() calls __ocfs2_move_extent()
> which clears OCFS2_EXT_REFCOUNTED flag on disk (flags=0x0)
> 5. The extent map cache is not invalidated after the move
> 6. Later write() operations read stale cached flags (0x2) but disk has
> updated flags (0x0), causing a mismatch
> 7. BUG_ON(!(rec->e_flags & OCFS2_EXT_REFCOUNTED)) triggers
>
> Fix by clearing the extent map cache after each extent move/defrag
> operation in __ocfs2_move_extents_range(). This ensures subsequent
> operations read fresh extent data from disk.
>
> Link: https://lore.kernel.org/all/20251009142917.517229-1-kartikey406@gmail.com/T/
> Reported-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
> Tested-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?id=2959889e1f6e216585ce522f7e8bc002b46ad9e7
> Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Reviewed-by: Mark Fasheh <mark@fasheh.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents
2025-10-09 15:49 [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents Deepanshu Kartikey
2025-10-09 16:18 ` Mark Fasheh
@ 2025-10-10 1:21 ` Joseph Qi
2025-10-11 7:31 ` Heming Zhao
2025-10-10 1:37 ` Andrew Morton
2 siblings, 1 reply; 6+ messages in thread
From: Joseph Qi @ 2025-10-10 1:21 UTC (permalink / raw)
To: Deepanshu Kartikey, mark, jlbec, akpm
Cc: ocfs2-devel, linux-kernel, syzbot+6fdd8fa3380730a4b22c
On 2025/10/9 23:49, Deepanshu Kartikey wrote:
> The extent map cache can become stale when extents are moved or
> defragmented, causing subsequent operations to see outdated extent
> flags. This triggers a BUG_ON in ocfs2_refcount_cal_cow_clusters().
>
> The problem occurs when:
> 1. copy_file_range() creates a reflinked extent with OCFS2_EXT_REFCOUNTED
> 2. ioctl(FITRIM) triggers ocfs2_move_extents()
> 3. __ocfs2_move_extents_range() reads and caches the extent (flags=0x2)
> 4. ocfs2_move_extent()/ocfs2_defrag_extent() calls __ocfs2_move_extent()
> which clears OCFS2_EXT_REFCOUNTED flag on disk (flags=0x0)
> 5. The extent map cache is not invalidated after the move
> 6. Later write() operations read stale cached flags (0x2) but disk has
> updated flags (0x0), causing a mismatch
> 7. BUG_ON(!(rec->e_flags & OCFS2_EXT_REFCOUNTED)) triggers
>
> Fix by clearing the extent map cache after each extent move/defrag
> operation in __ocfs2_move_extents_range(). This ensures subsequent
> operations read fresh extent data from disk.
>
> Link: https://lore.kernel.org/all/20251009142917.517229-1-kartikey406@gmail.com/T/
> Reported-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
> Tested-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?id=2959889e1f6e216585ce522f7e8bc002b46ad9e7
> Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Looks fine.
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
> ---
> Changes in v2:
> - Fix moved to __ocfs2_move_extents_range() instead of ocfs2_refcount_cow()
> - The real issue is in FITRIM/move_extents code path, not COW path
> - COW path already clears cache at end of ocfs2_refcount_cow_hunk()
>
> fs/ocfs2/move_extents.c | 5 +++++
> 1 file changed, 5 insertions(+)
> ---
> fs/ocfs2/move_extents.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
> index 86f2631e6360..10923bf7c8b8 100644
> --- a/fs/ocfs2/move_extents.c
> +++ b/fs/ocfs2/move_extents.c
> @@ -867,6 +867,11 @@ static int __ocfs2_move_extents_range(struct buffer_head *di_bh,
> mlog_errno(ret);
> goto out;
> }
> + /*
> + * Invalidate extent cache after moving/defragging to prevent
> + * stale cached data with outdated extent flags.
> + */
> + ocfs2_extent_map_trunc(inode, cpos);
>
> context->clusters_moved += alloc_size;
> next:
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents
2025-10-09 15:49 [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents Deepanshu Kartikey
2025-10-09 16:18 ` Mark Fasheh
2025-10-10 1:21 ` Joseph Qi
@ 2025-10-10 1:37 ` Andrew Morton
2 siblings, 0 replies; 6+ messages in thread
From: Andrew Morton @ 2025-10-10 1:37 UTC (permalink / raw)
To: Deepanshu Kartikey
Cc: mark, jlbec, joseph.qi, ocfs2-devel, linux-kernel,
syzbot+6fdd8fa3380730a4b22c
On Thu, 9 Oct 2025 21:19:03 +0530 Deepanshu Kartikey <kartikey406@gmail.com> wrote:
> The extent map cache can become stale when extents are moved or
> defragmented, causing subsequent operations to see outdated extent
> flags. This triggers a BUG_ON in ocfs2_refcount_cal_cow_clusters().
We try to avoid BUG_ONs ;)
>
> ...
>
> The problem occurs when:
>
> ...
>
> --- a/fs/ocfs2/move_extents.c
> +++ b/fs/ocfs2/move_extents.c
> @@ -867,6 +867,11 @@ static int __ocfs2_move_extents_range(struct buffer_head *di_bh,
> mlog_errno(ret);
> goto out;
> }
> + /*
> + * Invalidate extent cache after moving/defragging to prevent
> + * stale cached data with outdated extent flags.
> + */
> + ocfs2_extent_map_trunc(inode, cpos);
>
> context->clusters_moved += alloc_size;
> next:
I assume we should backport this into earlier kernels, so I'll add a
cc:stable to the changelog.
It's very nice (but not essential) to add a Fixes: as well, so -stable
maintainers know how far back in time to backport the fix.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents
@ 2025-10-10 2:00 Deepanshu Kartikey
0 siblings, 0 replies; 6+ messages in thread
From: Deepanshu Kartikey @ 2025-10-10 2:00 UTC (permalink / raw)
To: akpm
Cc: mark, jlbec, joseph.qi, ocfs2-devel, linux-kernel,
syzbot+6fdd8fa3380730a4b22c
Hi Andrew,
Thank you for picking this up!
For the Fixes: tag:
Fixes: 53069d4e76954e2e63c1b3c501051c6fbcf7298c ("Ocfs2/move_extents: move/defrag extents within a certain range.")
This commit introduced __ocfs2_move_extents_range() with the while loop that
calls ocfs2_get_clusters() (which caches extent data) followed by
ocfs2_move_extent()/ocfs2_defrag_extent() (which modify disk), but without
invalidating the extent cache afterwards.
Thanks,
Deepanshu
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents
2025-10-10 1:21 ` Joseph Qi
@ 2025-10-11 7:31 ` Heming Zhao
0 siblings, 0 replies; 6+ messages in thread
From: Heming Zhao @ 2025-10-11 7:31 UTC (permalink / raw)
To: Joseph Qi, Deepanshu Kartikey, mark, jlbec, akpm
Cc: ocfs2-devel, linux-kernel, syzbot+6fdd8fa3380730a4b22c
Hi Joseph,
please check my comments in another mail.
https://lore.kernel.org/all/20251009142917.517229-1-kartikey406@gmail.com/T/#m0c02c884701c12d71206d0f9aba4450879b18e0c
- Heming
On 10/10/25 09:21, Joseph Qi wrote:
>
>
> On 2025/10/9 23:49, Deepanshu Kartikey wrote:
>> The extent map cache can become stale when extents are moved or
>> defragmented, causing subsequent operations to see outdated extent
>> flags. This triggers a BUG_ON in ocfs2_refcount_cal_cow_clusters().
>>
>> The problem occurs when:
>> 1. copy_file_range() creates a reflinked extent with OCFS2_EXT_REFCOUNTED
>> 2. ioctl(FITRIM) triggers ocfs2_move_extents()
>> 3. __ocfs2_move_extents_range() reads and caches the extent (flags=0x2)
>> 4. ocfs2_move_extent()/ocfs2_defrag_extent() calls __ocfs2_move_extent()
>> which clears OCFS2_EXT_REFCOUNTED flag on disk (flags=0x0)
>> 5. The extent map cache is not invalidated after the move
>> 6. Later write() operations read stale cached flags (0x2) but disk has
>> updated flags (0x0), causing a mismatch
>> 7. BUG_ON(!(rec->e_flags & OCFS2_EXT_REFCOUNTED)) triggers
>>
>> Fix by clearing the extent map cache after each extent move/defrag
>> operation in __ocfs2_move_extents_range(). This ensures subsequent
>> operations read fresh extent data from disk.
>>
>> Link: https://lore.kernel.org/all/20251009142917.517229-1-kartikey406@gmail.com/T/
>> Reported-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
>> Tested-by: syzbot+6fdd8fa3380730a4b22c@syzkaller.appspotmail.com
>> Closes: https://syzkaller.appspot.com/bug?id=2959889e1f6e216585ce522f7e8bc002b46ad9e7
>> Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
>
> Looks fine.
> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
>
>> ---
>> Changes in v2:
>> - Fix moved to __ocfs2_move_extents_range() instead of ocfs2_refcount_cow()
>> - The real issue is in FITRIM/move_extents code path, not COW path
>> - COW path already clears cache at end of ocfs2_refcount_cow_hunk()
>>
>> fs/ocfs2/move_extents.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>> ---
>> fs/ocfs2/move_extents.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
>> index 86f2631e6360..10923bf7c8b8 100644
>> --- a/fs/ocfs2/move_extents.c
>> +++ b/fs/ocfs2/move_extents.c
>> @@ -867,6 +867,11 @@ static int __ocfs2_move_extents_range(struct buffer_head *di_bh,
>> mlog_errno(ret);
>> goto out;
>> }
>> + /*
>> + * Invalidate extent cache after moving/defragging to prevent
>> + * stale cached data with outdated extent flags.
>> + */
>> + ocfs2_extent_map_trunc(inode, cpos);
>>
>> context->clusters_moved += alloc_size;
>> next:
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-10-11 7:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-09 15:49 [PATCH v2] ocfs2: clear extent cache after moving/defragmenting extents Deepanshu Kartikey
2025-10-09 16:18 ` Mark Fasheh
2025-10-10 1:21 ` Joseph Qi
2025-10-11 7:31 ` Heming Zhao
2025-10-10 1:37 ` Andrew Morton
-- strict thread matches above, loose matches on Subject: below --
2025-10-10 2:00 Deepanshu Kartikey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox