On 10/27/25 17:23, Xiaole He wrote:
> The age extent cache uses last_blocks (derived from
> allocated_data_blocks) to determine data age. However, there's a
> conflict between the deletion
> marker (last_blocks=0) and legitimate last_blocks=0 cases when
> allocated_data_blocks overflows to 0 after reaching ULLONG_MAX.
>
> In this case, valid extents are incorrectly skipped due to the
> "if (!tei->last_blocks)" check in __update_extent_tree_range().
>
> This patch fixes the issue by:
> 1. Reserving ULLONG_MAX as an invalid/deletion marker
> 2. Limiting allocated_data_blocks to range [0, ULLONG_MAX-1]
> 3. Using F2FS_EXTENT_AGE_INVALID for deletion scenarios
> 4. Adjusting overflow age calculation from ULLONG_MAX to (ULLONG_MAX-1)
>
> Reproducer (using a patched kernel with allocated_data_blocks
> initialized to ULLONG_MAX - 3 for quick testing):
>
> Step 1: Mount and check initial state
> # dd if=/dev/zero of=/tmp/test.img bs=1M count=100
> # mkfs.f2fs -f /tmp/test.img
> # mkdir -p /mnt/f2fs_test
> # mount -t f2fs -o loop,age_extent_cache /tmp/test.img /mnt/f2fs_test
> # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age"
> Allocated Data Blocks: 18446744073709551612 # ULLONG_MAX - 3
> Inner Struct Count: tree: 1(0), node: 0
>
> Step 2: Create files and write data to trigger overflow
> # touch /mnt/f2fs_test/{1,2,3,4}.txt; sync
> # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age"
> Allocated Data Blocks: 18446744073709551613 # ULLONG_MAX - 2
> Inner Struct Count: tree: 5(0), node: 1
>
> # dd if=/dev/urandom of=/mnt/f2fs_test/1.txt bs=4K count=1; sync
> # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age"
> Allocated Data Blocks: 18446744073709551614 # ULLONG_MAX - 1
> Inner Struct Count: tree: 5(0), node: 2
>
> # dd if=/dev/urandom of=/mnt/f2fs_test/2.txt bs=4K count=1; sync
> # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age"
> Allocated Data Blocks: 18446744073709551615 # ULLONG_MAX
> Inner Struct Count: tree: 5(0), node: 3
>
> # dd if=/dev/urandom of=/mnt/f2fs_test/3.txt bs=4K count=1; sync
> # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age"
> Allocated Data Blocks: 0 # Counter overflowed!
> Inner Struct Count: tree: 5(0), node: 4
>
> Step 3: Trigger the bug - next write should create node but gets skipped
> # dd if=/dev/urandom of=/mnt/f2fs_test/4.txt bs=4K count=1; sync
> # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age"
> Allocated Data Blocks: 1
> Inner Struct Count: tree: 5(0), node: 4
>
> Expected: node: 5 (new extent node for 4.txt)
> Actual: node: 4 (extent insertion was incorrectly skipped due to
> last_blocks = allocated_data_blocks = 0 in __get_new_block_age)
>
> After this fix, the extent node is correctly inserted and node count
> becomes 5 as expected.
>
> Fixes: 71644dff4811 ("f2fs: add block_age-based extent cache")
> Cc: [email protected]
> Signed-off-by: Xiaole He <[email protected]>
Reviewed-by: Chao Yu <[email protected]>
Thanks,
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel