* Re: [PATCH] exfat: implement swap activate
2026-06-18 9:33 [PATCH] exfat: implement swap activate Andrea Cervesato
@ 2026-06-18 18:15 ` David Timber
2026-06-18 19:59 ` David Timber
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: David Timber @ 2026-06-18 18:15 UTC (permalink / raw)
To: Andrea Cervesato, Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, jack, chrubis, Andrea Cervesato
On 6/18/26 18:33, Andrea Cervesato wrote:
> From: Andrea Cervesato <andrea.cervesato@suse.com>
>
> exfat's fallocate allocates clusters without updating valid_size,
> leaving them invisible to bmap(). Extend valid_size to i_size so
> that generic_swapfile_activate() can map all blocks.
>
> This bug has been found during a Linux Test Project regression test
> using swapon/swapoff testing suite.
>
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> Fixes: bf1797960c20 ("exfat: add fallocate FALLOC_FL_ALLOCATE_RANGE support")
> Link: https://patchwork.ozlabs.org/project/ltp/patch/20260608155241.270875-1-japo@linux.ibm.com/
> ---
> bf1797960c20 - ("exfat: add fallocate FALLOC_FL_ALLOCATE_RANGE support")
> introduces fallocate() support in exfat, but omits the swap activate
> implementation, causing EINVAL inside Linux Test Project swapon/swapoff
> testing suites which are testing these syscalls with many filesystems,
> including exfat.
>
> This turned out to be a bug inside the kernel. The patch implements
> swap activate in order to ensure that exfat valid_size is correctly
> updated and the generic_swapfile_activate() doesn't fail with EINVAL
> due to valid_size=0, which is passed to bmap().
> ---
> fs/exfat/exfat_fs.h | 1 +
> fs/exfat/file.c | 2 +-
> fs/exfat/inode.c | 23 +++++++++++++++++++++++
> 3 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
> index aff4dcd4e75a55296d536c19306813a566d6f0bb..18382c661d4358f8b80e6f7b5032a356a5905614 100644
> --- a/fs/exfat/exfat_fs.h
> +++ b/fs/exfat/exfat_fs.h
> @@ -489,6 +489,7 @@ int exfat_trim_fs(struct inode *inode, struct fstrim_range *range);
>
> /* file.c */
> extern const struct file_operations exfat_file_operations;
> +int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size);
> int __exfat_truncate(struct inode *inode);
> void exfat_truncate(struct inode *inode);
> int exfat_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> diff --git a/fs/exfat/file.c b/fs/exfat/file.c
> index 91e5511945d11b12658908dc6287fabd572d1d6a..12ed28c3ff896fb545bad58b47cccf808b48618d 100644
> --- a/fs/exfat/file.c
> +++ b/fs/exfat/file.c
> @@ -642,7 +642,7 @@ int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
> return blkdev_issue_flush(inode->i_sb->s_bdev);
> }
>
> -static int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size)
> +int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size)
> {
> int err;
> loff_t pos;
> diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
> index 1ea4c740fef9ef6932a75e122e1b0130c85533b2..5a395851062e4a14b456fa79546541227d8427e6 100644
> --- a/fs/exfat/inode.c
> +++ b/fs/exfat/inode.c
> @@ -11,6 +11,7 @@
> #include <linux/time.h>
> #include <linux/writeback.h>
> #include <linux/uio.h>
> +#include <linux/swap.h>
> #include <linux/random.h>
> #include <linux/iversion.h>
>
> @@ -534,6 +535,27 @@ int exfat_block_truncate_page(struct inode *inode, loff_t from)
> return block_truncate_page(inode->i_mapping, from, exfat_get_block);
> }
>
> +static int exfat_swap_activate(struct swap_info_struct *sis,
> + struct file *file, sector_t *span)
> +{
> + struct inode *inode = file_inode(file);
> + struct exfat_inode_info *ei = EXFAT_I(inode);
> + int ret;
> +
> + /*
> + * exfat's fallocate allocates clusters without updating valid_size,
> + * leaving them invisible to bmap(). Extend valid_size to i_size so
> + * that generic_swapfile_activate() can map all blocks.
> + */
> + if (ei->valid_size < i_size_read(inode)) {
> + ret = exfat_extend_valid_size(inode, i_size_read(inode));
This incurs uninterruptible write amplification. Say you fallocated()'d
or truncate()'d a 1TB file on a USB stick, it will probably take as long
as it takes to fill the VDL hole. Some people will find that
unacceptible. This is a problem unique to exfat, and not the limitation
of the kernel implementation but rather that of the exfat format itself.
There's nothing we can do about it except somehow we make the write
amplification cases interruptible/cancelable from userspace if need be.
From what I gathered, userland used to dd swap images before doing
mkswap and using them for filesystems without fallocate() support(like
FAT on a live usb stick). Even with the ones that did, there was no
guarantee that the swap would function properly, it was not worth it.
tbh, I genuinely wonder if there's a real use case for using swap images
on exfat. Has any user come forward with this bug with a valid use case?
I think we should ask ourselves if we're patching exfat to just make the
test work rather than fixing the real problems. You can't make
fs-agnostic test cases. Some fs need special treatment, unfortunately.
If we didn't allow that, (x)fstests wouldn't just be possible.
This has been my two cents. Now it's up to maintainers to decide. At the
end of the day, defered write amplification on swapon() could just
become another quirk of exfat.
Davo
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] exfat: implement swap activate
2026-06-18 9:33 [PATCH] exfat: implement swap activate Andrea Cervesato
2026-06-18 18:15 ` David Timber
@ 2026-06-18 19:59 ` David Timber
2026-06-25 13:56 ` Andrea Cervesato
2026-06-24 2:54 ` kernel test robot
2026-06-24 6:02 ` kernel test robot
3 siblings, 1 reply; 6+ messages in thread
From: David Timber @ 2026-06-18 19:59 UTC (permalink / raw)
To: Andrea Cervesato, Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, jack, chrubis, Andrea Cervesato
On 6/18/26 18:33, Andrea Cervesato wrote:
> From: Andrea Cervesato <andrea.cervesato@suse.com>
>
> exfat's fallocate allocates clusters without updating valid_size,
> leaving them invisible to bmap(). Extend valid_size to i_size so
> that generic_swapfile_activate() can map all blocks.
>
> This bug has been found during a Linux Test Project regression test
> using swapon/swapoff testing suite.
>
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> Fixes: bf1797960c20 ("exfat: add fallocate FALLOC_FL_ALLOCATE_RANGE support")
> Link: https://patchwork.ozlabs.org/project/ltp/patch/20260608155241.270875-1-japo@linux.ibm.com/
> ---
> bf1797960c20 - ("exfat: add fallocate FALLOC_FL_ALLOCATE_RANGE support")
> introduces fallocate() support in exfat, but omits the swap activate
> implementation, causing EINVAL inside Linux Test Project swapon/swapoff
> testing suites which are testing these syscalls with many filesystems,
> including exfat.
>
> This turned out to be a bug inside the kernel. The patch implements
> swap activate in order to ensure that exfat valid_size is correctly
> updated and the generic_swapfile_activate() doesn't fail with EINVAL
> due to valid_size=0, which is passed to bmap().
> ---
> fs/exfat/exfat_fs.h | 1 +
> fs/exfat/file.c | 2 +-
> fs/exfat/inode.c | 23 +++++++++++++++++++++++
> 3 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
> index aff4dcd4e75a55296d536c19306813a566d6f0bb..18382c661d4358f8b80e6f7b5032a356a5905614 100644
> --- a/fs/exfat/exfat_fs.h
> +++ b/fs/exfat/exfat_fs.h
> @@ -489,6 +489,7 @@ int exfat_trim_fs(struct inode *inode, struct fstrim_range *range);
>
> /* file.c */
> extern const struct file_operations exfat_file_operations;
> +int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size);
> int __exfat_truncate(struct inode *inode);
> void exfat_truncate(struct inode *inode);
> int exfat_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> diff --git a/fs/exfat/file.c b/fs/exfat/file.c
> index 91e5511945d11b12658908dc6287fabd572d1d6a..12ed28c3ff896fb545bad58b47cccf808b48618d 100644
> --- a/fs/exfat/file.c
> +++ b/fs/exfat/file.c
> @@ -642,7 +642,7 @@ int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
> return blkdev_issue_flush(inode->i_sb->s_bdev);
> }
>
> -static int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size)
> +int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size)
> {
> int err;
> loff_t pos;
> diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
> index 1ea4c740fef9ef6932a75e122e1b0130c85533b2..5a395851062e4a14b456fa79546541227d8427e6 100644
> --- a/fs/exfat/inode.c
> +++ b/fs/exfat/inode.c
> @@ -11,6 +11,7 @@
> #include <linux/time.h>
> #include <linux/writeback.h>
> #include <linux/uio.h>
> +#include <linux/swap.h>
> #include <linux/random.h>
> #include <linux/iversion.h>
>
> @@ -534,6 +535,27 @@ int exfat_block_truncate_page(struct inode *inode, loff_t from)
> return block_truncate_page(inode->i_mapping, from, exfat_get_block);
> }
>
> +static int exfat_swap_activate(struct swap_info_struct *sis,
> + struct file *file, sector_t *span)
> +{
> + struct inode *inode = file_inode(file);
> + struct exfat_inode_info *ei = EXFAT_I(inode);
> + int ret;
> +
> + /*
> + * exfat's fallocate allocates clusters without updating valid_size,
> + * leaving them invisible to bmap(). Extend valid_size to i_size so
> + * that generic_swapfile_activate() can map all blocks.
> + */
> + if (ei->valid_size < i_size_read(inode)) {
Also, if we want to do this, please ensure that ei->valid_size is cached
in by locking the inode or etc before referencing it.
I'll see if I can make exfat_extend_valid_size() interruptible by
placing missing fatal_signal_pending(current) check in both stable and
iomap branches.
Davo
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] exfat: implement swap activate
2026-06-18 19:59 ` David Timber
@ 2026-06-25 13:56 ` Andrea Cervesato
0 siblings, 0 replies; 6+ messages in thread
From: Andrea Cervesato @ 2026-06-25 13:56 UTC (permalink / raw)
To: David Timber
Cc: Andrea Cervesato, Namjae Jeon, Sungjong Seo, Yuezhang Mo,
linux-fsdevel, linux-kernel, jack, chrubis
Hi David,
thanks for explaining your point of view. I will wait for other
maintainers to decide if this feature can be integrated into the
kernel or not, before proceding with the v2.
Best regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] exfat: implement swap activate
2026-06-18 9:33 [PATCH] exfat: implement swap activate Andrea Cervesato
2026-06-18 18:15 ` David Timber
2026-06-18 19:59 ` David Timber
@ 2026-06-24 2:54 ` kernel test robot
2026-06-24 6:02 ` kernel test robot
3 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2026-06-24 2:54 UTC (permalink / raw)
To: Andrea Cervesato, Namjae Jeon, Sungjong Seo, Yuezhang Mo,
David Timber
Cc: oe-kbuild-all, linux-fsdevel, linux-kernel, jack, chrubis,
Andrea Cervesato
Hi Andrea,
kernel test robot noticed the following build errors:
[auto build test ERROR on e771677c937da5808f7b6c1f0e4a97ec1a84f8a8]
url: https://github.com/intel-lab-lkp/linux/commits/Andrea-Cervesato/exfat-implement-swap-activate/20260622-172327
base: e771677c937da5808f7b6c1f0e4a97ec1a84f8a8
patch link: https://lore.kernel.org/r/20260618-exfat_swap_activate-v1-1-4c6a465df295%40suse.com
patch subject: [PATCH] exfat: implement swap activate
config: microblaze-allyesconfig (https://download.01.org/0day-ci/archive/20260624/202606241018.4N100hSQ-lkp@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 16.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260624/202606241018.4N100hSQ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606241018.4N100hSQ-lkp@intel.com/
All errors (new ones prefixed by >>):
fs/exfat/inode.c: In function 'exfat_swap_activate':
>> fs/exfat/inode.c:556:16: error: implicit declaration of function 'generic_swapfile_activate' [-Wimplicit-function-declaration]
556 | return generic_swapfile_activate(sis, file, span);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
vim +/generic_swapfile_activate +556 fs/exfat/inode.c
537
538 static int exfat_swap_activate(struct swap_info_struct *sis,
539 struct file *file, sector_t *span)
540 {
541 struct inode *inode = file_inode(file);
542 struct exfat_inode_info *ei = EXFAT_I(inode);
543 int ret;
544
545 /*
546 * exfat's fallocate allocates clusters without updating valid_size,
547 * leaving them invisible to bmap(). Extend valid_size to i_size so
548 * that generic_swapfile_activate() can map all blocks.
549 */
550 if (ei->valid_size < i_size_read(inode)) {
551 ret = exfat_extend_valid_size(inode, i_size_read(inode));
552 if (ret)
553 return ret;
554 }
555
> 556 return generic_swapfile_activate(sis, file, span);
557 }
558
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] exfat: implement swap activate
2026-06-18 9:33 [PATCH] exfat: implement swap activate Andrea Cervesato
` (2 preceding siblings ...)
2026-06-24 2:54 ` kernel test robot
@ 2026-06-24 6:02 ` kernel test robot
3 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2026-06-24 6:02 UTC (permalink / raw)
To: Andrea Cervesato, Namjae Jeon, Sungjong Seo, Yuezhang Mo,
David Timber
Cc: llvm, oe-kbuild-all, linux-fsdevel, linux-kernel, jack, chrubis,
Andrea Cervesato
Hi Andrea,
kernel test robot noticed the following build errors:
[auto build test ERROR on e771677c937da5808f7b6c1f0e4a97ec1a84f8a8]
url: https://github.com/intel-lab-lkp/linux/commits/Andrea-Cervesato/exfat-implement-swap-activate/20260622-172327
base: e771677c937da5808f7b6c1f0e4a97ec1a84f8a8
patch link: https://lore.kernel.org/r/20260618-exfat_swap_activate-v1-1-4c6a465df295%40suse.com
patch subject: [PATCH] exfat: implement swap activate
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20260624/202606241341.hkQXa0PG-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project a9b492db3d50683e446cd1a5c9ffaf4e92cb77a7)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260624/202606241341.hkQXa0PG-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606241341.hkQXa0PG-lkp@intel.com/
All errors (new ones prefixed by >>, old ones prefixed by <<):
>> ERROR: modpost: "generic_swapfile_activate" [fs/exfat/exfat.ko] undefined!
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread