[Devel] [PATCH vz10] fs: move FALLOC_FL_PREALLOCATE to a bit upstream has not taken
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Sep 8 16:38:18 MSK 2026
We had FALLOC_FL_PREALLOCATE == 0x80.
Upstream commit 7bd43cc79cab ("fs: introduce FALLOC_FL_WRITE_ZEROES to
fallocate"), released in v6.17, gives 0x80 to a mode of its own and
adds it to FALLOC_FL_MODE_MASK.
Move the mode to 0x00100000, well above the range upstream allocates
modes from and away from the top of the word, where a future user is
just as likely to start.
The number cannot simply change, though, because userspace carries its
own copy of it. Export the value as a read-only ext4 module parameter,
/sys/module/ext4/parameters/falloc_fl_preallocate, and let userspace
read the mode from there.
The old value stays accepted as FALLOC_FL_PREALLOCATE_OLD, so that
userspace built before this change keeps working. It has to be dropped
before the rebase onto v6.17 or later, otherwise we would take
FALLOC_FL_WRITE_ZEROES requests for our own mode.
Feature: ext4: preallocation flag for small fallocates
https://virtuozzo.atlassian.net/browse/VSTOR-144521
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
Follow-up to the v3 thread of "fs/ext4: let FALLOC_FL_PREALLOCATE
through the vfs_fallocate mode switch": 0x80 is FALLOC_FL_WRITE_ZEROES
upstream since v6.17, so our mode has to move before we rebase onto it,
and the value has to become discoverable instead of hardcoded on both
sides.
---
fs/ext4/extents.c | 14 ++++++++++----
fs/open.c | 1 +
include/linux/falloc.h | 3 ++-
include/uapi/linux/falloc.h | 15 ++++++++++++++-
4 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 38f50770f6585..eca3f0312ac53 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -39,6 +39,10 @@ static unsigned int falloc_prealloc;
module_param(falloc_prealloc, uint, 0644);
MODULE_PARM_DESC(falloc_prealloc, "Preallocate fallocate like it is a write for smaller sizes");
+static unsigned int falloc_fl_preallocate = FALLOC_FL_PREALLOCATE;
+module_param(falloc_fl_preallocate, uint, 0444);
+MODULE_PARM_DESC(falloc_fl_preallocate, "fallocate() mode value asking for preallocation");
+
/*
* used by extent splitting.
*/
@@ -4514,8 +4518,8 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
* that it doesn't get unnecessarily split into multiple
* extents.
*/
- if (!(mode & FALLOC_FL_PREALLOCATE) && len <= EXT_UNWRITTEN_MAX_LEN &&
- len > falloc_prealloc)
+ if (!(mode & (FALLOC_FL_PREALLOCATE | FALLOC_FL_PREALLOCATE_OLD)) &&
+ len <= EXT_UNWRITTEN_MAX_LEN && len > falloc_prealloc)
flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
/*
@@ -4754,7 +4758,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
/* Return error if mode is not supported */
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE |
- FALLOC_FL_INSERT_RANGE | FALLOC_FL_PREALLOCATE))
+ FALLOC_FL_INSERT_RANGE | FALLOC_FL_PREALLOCATE |
+ FALLOC_FL_PREALLOCATE_OLD))
return -EOPNOTSUPP;
inode_lock(inode);
@@ -4770,7 +4775,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
goto out_inode_lock;
if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ALLOCATE_RANGE ||
- (mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_PREALLOCATE) {
+ (mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_PREALLOCATE ||
+ (mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_PREALLOCATE_OLD) {
ret = ext4_do_fallocate(file, offset, len, mode);
goto out_inode_lock;
}
diff --git a/fs/open.c b/fs/open.c
index fc72ad09e7e81..65c96bf03dc93 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -268,6 +268,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
case FALLOC_FL_UNSHARE_RANGE:
case FALLOC_FL_ZERO_RANGE:
case FALLOC_FL_PREALLOCATE:
+ case FALLOC_FL_PREALLOCATE_OLD:
break;
case FALLOC_FL_PUNCH_HOLE:
if (!(mode & FALLOC_FL_KEEP_SIZE))
diff --git a/include/linux/falloc.h b/include/linux/falloc.h
index f6eee099b3fca..58e991ea6771f 100644
--- a/include/linux/falloc.h
+++ b/include/linux/falloc.h
@@ -37,7 +37,8 @@ struct space_resv {
FALLOC_FL_ZERO_RANGE | \
FALLOC_FL_INSERT_RANGE | \
FALLOC_FL_UNSHARE_RANGE | \
- FALLOC_FL_PREALLOCATE)
+ FALLOC_FL_PREALLOCATE | \
+ FALLOC_FL_PREALLOCATE_OLD)
/* on ia32 l_start is on a 32-bit boundary */
#if defined(CONFIG_X86_64)
diff --git a/include/uapi/linux/falloc.h b/include/uapi/linux/falloc.h
index 7ac8ffb8e6523..49aa826ad8f8a 100644
--- a/include/uapi/linux/falloc.h
+++ b/include/uapi/linux/falloc.h
@@ -78,6 +78,19 @@
*/
#define FALLOC_FL_UNSHARE_RANGE 0x40
-#define FALLOC_FL_PREALLOCATE 0x80
+/*
+ * FALLOC_FL_PREALLOCATE tells the filesystem to allocate the range the way a
+ * write would, with mballoc preallocation, rather than trimming the request
+ * down to a single unwritten extent.
+ *
+ * Userspace may read the mode value from
+ * /sys/module/ext4/parameters/falloc_fl_preallocate.
+ *
+ * FALLOC_FL_PREALLOCATE_OLD is the value used before upstream v6.17 claimed
+ * 0x80 for FALLOC_FL_WRITE_ZEROES. It is accepted as an alias of the above,
+ * and has to be dropped before a rebase onto v6.17 or later.
+ */
+#define FALLOC_FL_PREALLOCATE_OLD 0x80
+#define FALLOC_FL_PREALLOCATE 0x00100000
#endif /* _UAPI_FALLOC_H_ */
---
base-commit: 3466ec0b2cdf9d49dbb36d7b5ed9b36dfb2fb04d
change-id: 20260908-pr-khorenko-vstor-144521-falloc_fl_preallocate-cec80ce87000
Best regards,
--
Konstantin Khorenko <khorenko at virtuozzo.com>
More information about the Devel
mailing list