On 3/12/26 18:49, Chao Yu via Linux-f2fs-devel wrote:
> On 2026/3/12 18:41, Chao Yu wrote:
>> On 2026/3/12 11:56, Yongpeng Yang wrote:
>>>
>>> On 3/12/26 08:49, Chao Yu via Linux-f2fs-devel wrote:
>>>> On 2026/2/16 19:27, Yongpeng Yang wrote:
>>>>> From: Yongpeng Yang <[email protected]>
>>>>>
>>>>> Neither F2FS nor VFS invalidates the block device page cache, which
>>>>> results in reading stale metadata. An example scenario is shown below:
>>>>>
>>>>> Terminal A Terminal B
>>>>> mount /dev/vdb /mnt/f2fs
>>>>> touch mx // ino = 4
>>>>> sync
>>>>> dump.f2fs -i 4 /dev/vdb// block on "[Y/N]"
>>>>> touch mx2 // ino = 5
>>>>> sync
>>>>> umount /mnt/f2fs
>>>>> dump.f2fs -i 5 /dev/vdb // block addr
>>>>> is 0
>>>>>
>>>>> After umount, the block device page cache is not purged, causing
>>>>> `dump.f2fs -i 5 /dev/vdb` to read stale metadata and see inode 5 with
>>>>> block address 0.
>>>>>
>>>>> This patch calls invalidate_bdev during umount to invalidate the block
>>>>> device page cache, preventing stale metadata from being read.
>>>>>
>>>>> Signed-off-by: Yongpeng Yang <[email protected]>
>>>>> ---
>>>>> fs/f2fs/super.c | 6 ++++++
>>>>> 1 file changed, 6 insertions(+)
>>>>>
>>>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>>>> index 1a755997aff5..39d3b52ceac1 100644
>>>>> --- a/fs/f2fs/super.c
>>>>> +++ b/fs/f2fs/super.c
>>>>> @@ -2091,6 +2091,12 @@ static void f2fs_put_super(struct
>>>>> super_block *sb)
>>>>> #if IS_ENABLED(CONFIG_UNICODE)
>>>>> utf8_unload(sb->s_encoding);
>>>>> #endif
>>>>> + sync_blockdev(sb->s_bdev);
>>>>
>>>> We will call sync_blockdev in below path?
>>>>
>>>> - kill_f2fs_super
>>>> - kill_block_super
>>>> - generic_shutdown_super
>>>> - put_super
>>>> - sync_blockdev
>>>>
>>>> 1721 void kill_block_super(struct super_block *sb)
>>>> 1722 {
>>>> 1723 struct block_device *bdev = sb->s_bdev;
>>>> 1724
>>>> 1725 generic_shutdown_super(sb);
>>>> 1726 if (bdev) {
>>>> 1727 sync_blockdev(bdev);
>>>> 1728 bdev_fput(sb->s_bdev_file);
>>>> 1729 }
>>>> 1730 }
>>>>
>>>>> + invalidate_bdev(sb->s_bdev);
>>>
>>> This works for an f2fs instance mounted on a single device, but it does
>>> not work for multi-device configurations, because the vfs cannot be
>>> aware of FDEV(1).
>>
>> Yeah, I meant we can avoid duplicated sync_blockdev() for main device in
>> f2fs_put_super().
>>
The call trace corresponding to this patch is as follows:
kill_block_super
- generic_shutdown_super
- f2fs_put_super
- sync_blockdev
- invalidate_bdev
- sync_blockdev
There is indeed a duplicated call to sync_blockdev(). However, since all
data must be written to disk before invalidate_bdev() is called,
f2fs_put_super() must call sync_blockdev(). Because invalidate_bdev()
has already cleared the page cache, the second call to sync_blockdev()
does nothing.
>>>
>>>>
>>>> I guess we can leave the device w/ uptodate cache, in case if there are
>>>> multiple user on the device?
>>>
>>> The page cache of the block device file may contain data that is not
>>> uptodate. For example, data may first be read directly through the block
>> > device file, and then the same blocks may be written through f2fs.
>> Since> f2fs writes to the block device via the submit_bio path, it
>> does not
>>> update the page cache of the block device file. As a result, the data in
>>> the block device file’s page cache may become stale. Therefore, the page
>>> cache must be invalidated during unmount.
>>
>> Well, can we call ioctl(fd, BLKFLSBUF) for all devices belong to f2fs
>> img like
>> you did in ("f2fs-tools: invalidate block device page cache before
>> reading
>> metadata"), does that fix the issue?
>
> Oh, you already called the ioctl for all devices. Does that fix the issue?
>
Yes, that can fix this issue. From a system robustness perspective, both
the kernel and f2fs-tools should ensure that the uptodate data is read.
Therefore, I made changes in both.
Thanks
Yongpeng,
> Thanks,
>
>>
>> Thanks,
>>
>>>
>>> Thanks
>>> Yongpeng,
>>>
>>>>
>>>> Thanks,
>>>>
>>>>> + for (i = 1; i < sbi->s_ndevs; i++) {
>>>>> + sync_blockdev(FDEV(i).bdev);
>>>>> + invalidate_bdev(FDEV(i).bdev);
>>>>> + }
>>>>> }
>>>>> int f2fs_sync_fs(struct super_block *sb, int sync)
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Linux-f2fs-devel mailing list
>>>> [email protected]
>>>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
>>>
>>
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel