Skip to content

Commit fe9b8b3

Browse files
Yongpeng YangJaegeuk Kim
authored andcommitted
f2fs: fix inline data not being written to disk in writeback path
When f2fs_fiemap() is called with `fileinfo->fi_flags` containing the FIEMAP_FLAG_SYNC flag, it attempts to write data to disk before retrieving file mappings via filemap_write_and_wait(). However, there is an issue where the file does not get mapped as expected. The following scenario can occur: root@vm:/mnt/f2fs# dd if=/dev/zero of=data.3k bs=3k count=1 root@vm:/mnt/f2fs# xfs_io data.3k -c "fiemap -v 0 4096" data.3k: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..5]: 0..5 6 0x307 The root cause of this issue is that f2fs_write_single_data_page() only calls f2fs_write_inline_data() to copy data from the data folio to the inode folio, and it clears the dirty flag on the data folio. However, it does not mark the data folio as writeback. When __filemap_fdatawait_range() checks for folios with the writeback flag, it returns early, causing f2fs_fiemap() to report that the file has no mapping. To fix this issue, the solution is to call f2fs_write_single_node_folio() in f2fs_inline_data_fiemap() when getting fiemap with FIEMAP_FLAG_SYNC flags. This patch ensures that the inode folio is written back and the writeback process completes before proceeding. Cc: stable@kernel.org Fixes: 9ffe0fb ("f2fs: handle inline data operations") Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent c3e238b commit fe9b8b3

3 files changed

Lines changed: 12 additions & 1 deletion

File tree

fs/f2fs/f2fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3946,6 +3946,8 @@ int f2fs_sanity_check_node_footer(struct f2fs_sb_info *sbi,
39463946
enum node_type ntype, bool in_irq);
39473947
struct folio *f2fs_get_inode_folio(struct f2fs_sb_info *sbi, pgoff_t ino);
39483948
struct folio *f2fs_get_xnode_folio(struct f2fs_sb_info *sbi, pgoff_t xnid);
3949+
int f2fs_write_single_node_folio(struct folio *node_folio, int sync_mode,
3950+
bool mark_dirty, enum iostat_type io_type);
39493951
int f2fs_move_node_folio(struct folio *node_folio, int gc_type);
39503952
void f2fs_flush_inline_data(struct f2fs_sb_info *sbi);
39513953
int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,

fs/f2fs/inline.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,15 @@ int f2fs_inline_data_fiemap(struct inode *inode,
814814
goto out;
815815
}
816816

817+
if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC) {
818+
err = f2fs_write_single_node_folio(ifolio, true, false, FS_NODE_IO);
819+
if (err)
820+
return err;
821+
ifolio = f2fs_get_inode_folio(F2FS_I_SB(inode), inode->i_ino);
822+
if (IS_ERR(ifolio))
823+
return PTR_ERR(ifolio);
824+
f2fs_folio_wait_writeback(ifolio, NODE, true, true);
825+
}
817826
ilen = min_t(size_t, MAX_INLINE_DATA(inode), i_size_read(inode));
818827
if (start >= ilen)
819828
goto out;

fs/f2fs/node.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ static bool __write_node_folio(struct folio *folio, bool atomic, bool do_fsync,
18431843
return false;
18441844
}
18451845

1846-
static int f2fs_write_single_node_folio(struct folio *node_folio, int sync_mode,
1846+
int f2fs_write_single_node_folio(struct folio *node_folio, int sync_mode,
18471847
bool mark_dirty, enum iostat_type io_type)
18481848
{
18491849
int err = 0;

0 commit comments

Comments
 (0)