[f2fs-dev] [PATCH] f2fs: skip preallocation for mapped buffered overwrites

Wenjie Qi <[email protected]>
Newsgroups net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
For a full-block buffered overwrite, PRE_AIO does not reserve a block if
the target range is already mapped.  It still walks the dnode path under
the node_change read lock.

Skip PRE_AIO when the write is within i_size and the read extent cache
covers the whole range with valid data blocks.

Assisted-by: Codex:gpt-5.5
Signed-off-by: Wenjie Qi <[email protected]>
---
QEMU test on a 1GiB F2FS scratch image:
- mapped 4K overwrite: PRE_AIO traces 20000 -> 0, about
  10.2 -> 2.0 us/write.
- sparse in-i_size hole write miss case: PRE_AIO traces stayed
  8192 -> 8192, median 7.71 -> 7.95 us/write.

 fs/f2fs/file.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 4b52c56d71f0..cb03df086ff3 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -5007,6 +5007,32 @@ static ssize_t f2fs_write_checks(struct kiocb *iocb, struct iov_iter *from)
 	return count;
 }
 
+static bool f2fs_prealloc_mapped_overwrite(struct inode *inode,
+					   loff_t pos, size_t count,
+					   const struct f2fs_map_blocks *map)
+{
+	struct extent_info ei = {};
+	loff_t size = i_size_read(inode);
+	pgoff_t start = map->m_lblk;
+	pgoff_t end = start + map->m_len;
+	pgoff_t ei_end;
+
+	if (pos >= size || count > size - pos)
+		return false;
+	if (f2fs_has_inline_data(inode) || f2fs_compressed_file(inode) ||
+	    f2fs_is_atomic_file(inode) || IS_DEVICE_ALIASING(inode))
+		return false;
+	if (end < start)
+		return false;
+	if (!f2fs_lookup_read_extent_cache(inode, start, &ei))
+		return false;
+	if (!__is_valid_data_blkaddr(ei.blk))
+		return false;
+
+	ei_end = (pgoff_t)ei.fofs + ei.len;
+	return start >= ei.fofs && end <= ei_end;
+}
+
 /*
  * Preallocate blocks for a write request, if it is possible and helpful to do
  * so.  Returns a positive number if blocks may have been preallocated, 0 if no
@@ -5061,6 +5087,9 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter,
 	else
 		return 0;
 
+	if (!dio && f2fs_prealloc_mapped_overwrite(inode, pos, count, &map))
+		return 0;
+
 	if (!IS_DEVICE_ALIASING(inode))
 		map.m_may_create = true;
 	if (dio) {


_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.