[Devel] [PATCH vz10 v3] fs/ext4: let FALLOC_FL_PREALLOCATE through the vfs_fallocate mode switch

Konstantin Khorenko khorenko at virtuozzo.com
Mon Sep 7 17:10:09 MSK 2026


From: Alexey Kuznetsov <kuznet at virtuozzo.com>

Upstream commit 57413d8e172c ("fs: sort out the fallocate mode vs flag
mess") replaced the FALLOC_FL_SUPPORTED_MASK check in vfs_fallocate()
with a switch over FALLOC_FL_MODE_MASK that rejects unlisted modes with
EOPNOTSUPP, and ext4_fallocate() got a dedicated ALLOCATE_RANGE path.

The vz10 port of FALLOC_FL_PREALLOCATE only added the bit to the mask,
so fallocate(FALLOC_FL_PREALLOCATE) fails with EOPNOTSUPP before it
reaches ext4, and vstorage falls back to the slow path, which halves
its write performance.

Accept the mode in vfs_fallocate() and route it to ext4_do_fallocate()
together with plain allocation; ext4_alloc_file_blocks() already
honours the flag.

The falloc_prealloc description in the commit being fixed has the two
middle cases inverted and states its sizes in bytes where the code
counts blocks. Corrected:

khorenko@: logic is the following:
        if FALLOC_FL_PREALLOCATE
              preallocation enabled for all "len"

        if !FALLOC_FL_PREALLOCATE
           if len <= falloc_prealloc
              preallocation enabled
           if falloc_prealloc < len <= EXT_UNWRITTEN_MAX_LEN
              preallocation disabled
           if len > EXT_UNWRITTEN_MAX_LEN
              preallocation enabled

So if FALLOC_FL_PREALLOCATE is used, fallocate() behaves like write(),
i.e. always uses preallocation, the falloc_prealloc value is ignored.

If FALLOC_FL_PREALLOCATE is NOT used:
 - stock fallocate() disables preallocation for len sizes
   <= EXT_UNWRITTEN_MAX_LEN, that is 32767 blocks.
 - introduced falloc_prealloc allows to make an experiment:
   if we set non-zero falloc_prealloc parameter (in blocks),
   preallocation will be disabled for sizes
   falloc_prealloc .. EXT_UNWRITTEN_MAX_LEN.

   The idea behind: if you perform a small fallocate, you probably do
   not mean to fragment the file.

Fixes: 275be8b96ddf ("fs/ext4: introduce FALLOC_FL_PREALLOCATE flag to fallocate")

https://virtuozzo.atlassian.net/browse/VSTOR-142784

Signed-off-by: Alexey Kuznetsov <kuznet at virtuozzo.com>
Feature: ext4: preallocation flag for small fallocates
---
v2 -> v3: commit message enhanced

---
 fs/ext4/extents.c | 3 ++-
 fs/open.c         | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index b771cb594c061..38f50770f6585 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4769,7 +4769,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	if (ret)
 		goto out_inode_lock;
 
-	if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ALLOCATE_RANGE) {
+	if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ALLOCATE_RANGE ||
+	    (mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_PREALLOCATE) {
 		ret = ext4_do_fallocate(file, offset, len, mode);
 		goto out_inode_lock;
 	}
diff --git a/fs/open.c b/fs/open.c
index 91f4785b89f3c..fc72ad09e7e81 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -267,6 +267,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	case FALLOC_FL_ALLOCATE_RANGE:
 	case FALLOC_FL_UNSHARE_RANGE:
 	case FALLOC_FL_ZERO_RANGE:
+	case FALLOC_FL_PREALLOCATE:
 		break;
 	case FALLOC_FL_PUNCH_HOLE:
 		if (!(mode & FALLOC_FL_KEEP_SIZE))
-- 
2.43.0



More information about the Devel mailing list