In the case of large folio buffered write, if we pre-allocate partial blocks after acquiring the folio lock, it may call f2fs_balance_fs and need to unlock the folio during write.
Re-locking after unlocking can be troublesome because a large folio carries additional f2fs_folio_state metadata, and partial truncate can cause the large folio to be split. At this point, the large folio is still in the inode->mapping. Prellocate partial blocks in advance to avoid handling this. Signed-off-by: Nanzhe Zhao <[email protected]> --- fs/f2fs/file.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index abcf6f486dd7..18a9feccb1f9 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -4995,9 +4995,20 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter, return ret; } - /* Do not preallocate blocks that will be written partially in 4KB. */ - map.m_lblk = F2FS_BLK_ALIGN(pos); - map.m_len = F2FS_BYTES_TO_BLK(pos + count); + if (mapping_large_folio_support(inode->i_mapping)) { + /* preallocate all blocks for large folio inode before write to avoid + * unlocking large folios by balance_fs during write. Rechecking the + * large-folio state is unreliable since partial truncation may split + * the folio. + */ + map.m_lblk = F2FS_BYTES_TO_BLK(pos); + map.m_len = F2FS_BLK_ALIGN(pos + count); + } else { + /* Do not preallocate blocks that will be written partially in 4KB. */ + map.m_lblk = F2FS_BLK_ALIGN(pos); + map.m_len = F2FS_BYTES_TO_BLK(pos + count); + } + if (map.m_len > map.m_lblk) map.m_len -= map.m_lblk; else -- 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
