[PATCH] exfat: preserve allocated extents for swap activation
From: Harshit Mogalapalli
Date: Thu Jul 23 2026 - 15:30:03 EST
exFAT reports allocated ranges beyond valid_size as IOMAP_HOLE whenever
IOMAP_REPORT is set. iomap_swapfile_activate() also uses IOMAP_REPORT
while collecting a swapfile's physical extents, so it treats the
preallocated tail as unallocated and rejects the file with -EINVAL.
Allocated space beyond valid_size is not a hole. Keep it as
IOMAP_UNWRITTEN so iomap consumers that need physical extent identity,
such as swap activation, can still use it. The iomap seek helpers
already handle unwritten extents appropriately for SEEK_HOLE and
SEEK_DATA.
Fixes: b4b7fe2c7cbf ("exfat: add support for SEEK_HOLE and SEEK_DATA in llseek")
Assisted-by: Codex:GPT-5.6
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@xxxxxxxxxx>
---
LTP swapon/swapoff tests failed on exFAT, with this patch the tests
pass.
---
fs/exfat/iomap.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/fs/exfat/iomap.c b/fs/exfat/iomap.c
index 190fc6471f84..24d93288a432 100644
--- a/fs/exfat/iomap.c
+++ b/fs/exfat/iomap.c
@@ -105,18 +105,14 @@ static int __exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length
* marks the exact boundary between valid data and
* holes (or unwritten space).
*
- * When IOMAP_REPORT is set (used by lseek(SEEK_HOLE)
- * and SEEK_DATA), we return IOMAP_HOLE. This allows
- * iomap_seek_hole_iter() to directly return the
- * precise byte position.
- *
- * For normal I/O paths (without IOMAP_REPORT) we
- * return IOMAP_UNWRITTEN so the write path can
- * distinguish it from a real hole.
+ * Allocated space beyond valid_size is not a hole. Report it
+ * as IOMAP_UNWRITTEN so iomap consumers that need physical
+ * extent identity, such as swap activation, can still use it.
+ * The iomap seek helpers already handle unwritten extents
+ * appropriately for SEEK_HOLE and SEEK_DATA.
*/
if (offset >= ei->valid_size) {
- iomap->type = flags & IOMAP_REPORT ?
- IOMAP_HOLE : IOMAP_UNWRITTEN;
+ iomap->type = IOMAP_UNWRITTEN;
} else if (offset + iomap->length > ei->valid_size) {
if (flags & IOMAP_REPORT) {
/*
--
2.50.1