* Re: [PATCH 12/12] swap: move swap_info_struct to mm/swap.h
From: Damien Le Moal @ 2026-05-12 7:41 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-13-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> swap_info_struct is now internal to the MM subsystem, so remove it from
> the public header.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 11/12] swap: move struct swap_extent to swapfile.c
From: Damien Le Moal @ 2026-05-12 7:36 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-12-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> struct swap_extent is only used inside of mm/swapfile.c, so move it
> there.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 10/12] swap: add a swap_activate_fs_ops helper
From: Damien Le Moal @ 2026-05-12 7:36 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-11-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Add a helper abstracting away the low-level details of enabling
> fs_ops-based swapping. This prepares for taking swap_info_struct
> private.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 09/12] swap: push down setting sis->bdev into ->swap_activate
From: Damien Le Moal @ 2026-05-12 7:34 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-10-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Only the file operation method knows what block device we'll swap
> to. So move down setting sis->bdev and the special blockdev flag
> into ->swap_activate.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
One nit below. Otherwise, looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> @@ -141,7 +141,6 @@ int generic_swap_activate(struct file *swap_file, struct swap_info_struct *sis)
> continue;
> }
> return 0;
> -
whiteline change.
> bad_bmap:
> pr_err("swapon: swapfile has holes\n");
> return -EINVAL;
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 08/12] swap,iomap: simplify iomap_swapfile_iter
From: Damien Le Moal @ 2026-05-12 7:31 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-9-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> add_swap_extent already coalesces multiple extents, no need to duplicate
> that in the caller.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 6/9] fat: Fix possibly missing inode write on fsync(2)
From: Jan Kara @ 2026-05-12 7:29 UTC (permalink / raw)
To: OGAWA Hirofumi
Cc: Jan Kara, linux-fsdevel, Christian Brauner, aivazian.tigran,
Ted Tso, linux-ext4
In-Reply-To: <87v7ctddui.fsf@mail.parknet.co.jp>
On Tue 12-05-26 03:02:13, OGAWA Hirofumi wrote:
> Jan Kara <jack@suse.cz> writes:
>
> > On Mon 11-05-26 23:32:45, OGAWA Hirofumi wrote:
> >> Jan Kara <jack@suse.cz> writes:
> >>
> >> > Use mmb inode buffer writeout infrastructure to reliably write out
> >> > inode's buffer on fsync(2).
> >>
> >> > Signed-off-by: Jan Kara <jack@suse.cz>
> >> > ---
> >> > fs/fat/inode.c | 3 ++-
> >> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >> >
> >> > diff --git a/fs/fat/inode.c b/fs/fat/inode.c
> >> > index 28f78df086ef..4ca00b7a618b 100644
> >> > --- a/fs/fat/inode.c
> >> > +++ b/fs/fat/inode.c
> >> > @@ -907,6 +907,7 @@ static int __fat_write_inode(struct inode *inode, int wait)
> >> > }
> >> > spin_unlock(&sbi->inode_hash_lock);
> >> > mark_buffer_dirty(bh);
> >> > + MSDOS_I(inode)->i_metadata_bhs.inode_blk = bh->b_blocknr;
> >>
> >> When inode position was changed/removed, this will point the wrong
> >> block. And maybe sync a unrelated block and wait.
> >
> > So I didn't realize that e.g. rename does change the backing inode block.
> > But given we set i_metadata_bhs.inode_blk on each inode write, inode_blk
> > should always contain the current position where the inode was written so
> > fsync should be syncing the right block. Or am I still missing something?
>
> I didn't check the case of rename completely, just recalled it when I
> saw this code, need confirm/check. But at least, the case of remove
> will leave it even after the block is reused.
Right. fat_detach() should set i_metadata_bhs.inode_blk to INVALID_BLK,
thanks for catching that. I was thinking whether we should set
i_metadata_bhs.inode_blk in fat_attach() instead of during inode dirtying.
It would be somewhat more obviously correct but it could lead to
unnecessary flushing in case the directory block gets dirtied by some other
entry in it while the inode we are fsyncing got never dirtied. IMHO that's
a sensible tradeoff so I'd do that but what is your opinion?
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 07/12] swap,block: limit swap file size to device size
From: Christoph Hellwig @ 2026-05-12 7:23 UTC (permalink / raw)
To: Damien Le Moal
Cc: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song,
Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <217f91d9-4d5f-47a6-ad20-0404968b8e08@kernel.org>
On Tue, May 12, 2026 at 04:21:47PM +0900, Damien Le Moal wrote:
> On 5/12/26 14:35, Christoph Hellwig wrote:
> > Don't blindly pass the value from the swap header to swap_add_extent,
> > but instead the device size rounded down to page granularity. This
> > activated the sanity checking in the core code that catches a too large
> > value in the swap header.
> >
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Looks OK to me, though this maybe could be folded in the previous patch ?
I prefer to keep behavior changes as isolated as possible.
^ permalink raw reply
* Re: [PATCH 07/12] swap,block: limit swap file size to device size
From: Damien Le Moal @ 2026-05-12 7:21 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-8-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Don't blindly pass the value from the swap header to swap_add_extent,
> but instead the device size rounded down to page granularity. This
> activated the sanity checking in the core code that catches a too large
> value in the swap header.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me, though this maybe could be folded in the previous patch ?
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 01/12] swap: remove the maxpages variable in sys_swapon
From: Christoph Hellwig @ 2026-05-12 7:20 UTC (permalink / raw)
To: Damien Le Moal
Cc: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song,
Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <03dddf72-8755-4ebf-ba79-456377f0f25d@kernel.org>
On Tue, May 12, 2026 at 04:08:35PM +0900, Damien Le Moal wrote:
> On 5/12/26 14:35, Christoph Hellwig wrote:
> > Always use si->max which is updated setup_swap_extents instead of copying
> > into and out of maxpages.
>
> Checking mm/swapfile.c, I see s->max being set only in swapon(). Is this a typo
> or am I misunderstanding this sentence ?
It is updated by the file system methods or the generic implementation
called by setup_swap_extents currently. So the above is a bit imprecise.
The next patch then removes this confusing update.
^ permalink raw reply
* Re: [PATCH 06/12] swap,block: move the block device swapon code into block/fops.c
From: Damien Le Moal @ 2026-05-12 7:20 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-7-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Make use of the abstractions we have. This is a preparation for
> moving more special casing down into block/.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 05/12] swap: cleanup setup_swap_extents
From: Damien Le Moal @ 2026-05-12 7:18 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-6-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Reflow setup_swap_extents so that the flag checking is not conditional on
> a swap_activate method. This is currently a no-op because the swapoff
> code still checks the presence of a swap_deactivate method, but it
> simplifies adding a new check, and also makes the SWP_ACTIVATED flag
> more consistent.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 04/12] swap: restrict to regular files or block devices
From: Damien Le Moal @ 2026-05-12 7:17 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-5-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Various swap code assumes it runs either on a block device or on a
> regular file. Make this restriction explicit using checks right
> after opening the file.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 03/12] swap,fs: move swapfile operations to struct file_operations
From: Damien Le Moal @ 2026-05-12 7:16 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-4-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> The swap operations have nothing to do with the address_space, which is
> used for pagecache operations. Move them to struct file_operations
> instead. This will allow moving the block device special cases into
> block/fops.c subsequently.
>
> Pass struct file first to ->swap_activate as file operations typically
> get the file or iocb as first argument and use swap_activate instead of
> swapfile_activate in all names to be consistent.
>
> Note that while the trivial iomap wrappers are moved to a new file when
> applicable to keep them local to the file operation instances, complex
> implementation are kept in their existing place. It might be worth to
> move them in follow-on patches if the maintainers desire so.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks OK to me.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 02/12] swap: move boilerplate code into the core swap code
From: Damien Le Moal @ 2026-05-12 7:11 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-3-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Make the core swap code calculate sis->pages, nr_extents and the span,
> re-set sis->max based on it and don't require passing the current offset
> into the swap file to swap_add_extent as all that can trivially be
> calculated internally. Also truncate the spans based on the available
> information.
>
> All this removes a lot of boilerplate code in the callers.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
For the zonefs bits,
Acked-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH 01/12] swap: remove the maxpages variable in sys_swapon
From: Damien Le Moal @ 2026-05-12 7:08 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong, Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Naohiro Aota, linux-xfs,
linux-fsdevel, linux-doc, linux-mm, linux-block, linux-btrfs,
linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-2-hch@lst.de>
On 5/12/26 14:35, Christoph Hellwig wrote:
> Always use si->max which is updated setup_swap_extents instead of copying
> into and out of maxpages.
Checking mm/swapfile.c, I see s->max being set only in swapon(). Is this a typo
or am I misunderstanding this sentence ?
Looks good otherwise, but it would be nice to rename ->max to ->maxpages to make
it clear what this is counting.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> mm/swapfile.c | 27 +++++++++++----------------
> 1 file changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 9174f1eeffb0..f7ebd97e28a3 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -3350,10 +3350,9 @@ static unsigned long read_swap_header(struct swap_info_struct *si,
> }
>
> static int setup_swap_clusters_info(struct swap_info_struct *si,
> - union swap_header *swap_header,
> - unsigned long maxpages)
> + union swap_header *swap_header)
> {
> - unsigned long nr_clusters = DIV_ROUND_UP(maxpages, SWAPFILE_CLUSTER);
> + unsigned long nr_clusters = DIV_ROUND_UP(si->max, SWAPFILE_CLUSTER);
> struct swap_cluster_info *cluster_info;
> int err = -ENOMEM;
> unsigned long i;
> @@ -3395,7 +3394,7 @@ static int setup_swap_clusters_info(struct swap_info_struct *si,
> if (err)
> goto err;
> }
> - for (i = maxpages; i < round_up(maxpages, SWAPFILE_CLUSTER); i++) {
> + for (i = si->max; i < round_up(si->max, SWAPFILE_CLUSTER); i++) {
> err = swap_cluster_setup_bad_slot(si, cluster_info, i, true);
> if (err)
> goto err;
> @@ -3425,7 +3424,7 @@ static int setup_swap_clusters_info(struct swap_info_struct *si,
> si->cluster_info = cluster_info;
> return 0;
> err:
> - free_swap_cluster_info(cluster_info, maxpages);
> + free_swap_cluster_info(cluster_info, si->max);
> return err;
> }
>
> @@ -3440,7 +3439,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
> union swap_header *swap_header;
> int nr_extents;
> sector_t span;
> - unsigned long maxpages;
> struct folio *folio = NULL;
> struct inode *inode = NULL;
> bool inced_nr_rotate_swap = false;
> @@ -3512,14 +3510,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
> }
> swap_header = kmap_local_folio(folio, 0);
>
> - maxpages = read_swap_header(si, swap_header, inode);
> - if (unlikely(!maxpages)) {
> + si->max = read_swap_header(si, swap_header, inode);
> + if (unlikely(!si->max)) {
> error = -EINVAL;
> goto bad_swap_unlock_inode;
> }
>
> - si->max = maxpages;
> - si->pages = maxpages - 1;
> + si->pages = si->max - 1;
> nr_extents = setup_swap_extents(si, swap_file, &span);
> if (nr_extents < 0) {
> error = nr_extents;
> @@ -3531,14 +3528,12 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
> goto bad_swap_unlock_inode;
> }
>
> - maxpages = si->max;
> -
> /* Set up the swap cluster info */
> - error = setup_swap_clusters_info(si, swap_header, maxpages);
> + error = setup_swap_clusters_info(si, swap_header);
> if (error)
> goto bad_swap_unlock_inode;
>
> - error = swap_cgroup_swapon(si->type, maxpages);
> + error = swap_cgroup_swapon(si->type, si->max);
> if (error)
> goto bad_swap_unlock_inode;
>
> @@ -3546,7 +3541,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
> * Use kvmalloc_array instead of bitmap_zalloc as the allocation order might
> * be above MAX_PAGE_ORDER incase of a large swap file.
> */
> - si->zeromap = kvmalloc_array(BITS_TO_LONGS(maxpages), sizeof(long),
> + si->zeromap = kvmalloc_array(BITS_TO_LONGS(si->max), sizeof(long),
> GFP_KERNEL | __GFP_ZERO);
> if (!si->zeromap) {
> error = -ENOMEM;
> @@ -3597,7 +3592,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
> }
> }
>
> - error = zswap_swapon(si->type, maxpages);
> + error = zswap_swapon(si->type, si->max);
> if (error)
> goto bad_swap_unlock_inode;
>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH v4 9/9] fstests: btrfs: test UUID consistency for clones with metadata_uuid
From: Christoph Hellwig @ 2026-05-12 5:40 UTC (permalink / raw)
To: Anand Jain
Cc: fstests, linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il,
zlang, djwong
In-Reply-To: <d079b3f7cce446b0c5bc0762226957b960c7a3ac.1777357321.git.asj@kernel.org>
On Tue, Apr 28, 2026 at 02:42:59PM +0800, Anand Jain wrote:
> Btrfs uses the metadata_uuid superblock feature to change the on-disk UUID
> without rewriting every block header. This patch adds a sanity check to
> ensure UUID consistency when a filesystem with metadata_uuid enabled is
> cloned.
xfs does the same.
Can we abstract out the uuid change and generalize the test?
^ permalink raw reply
* Re: [PATCH v4 4/9] fstests: verify fanotify isolation on cloned filesystems
From: Christoph Hellwig @ 2026-05-12 5:38 UTC (permalink / raw)
To: Anand Jain
Cc: fstests, linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il,
zlang, André Almeida
In-Reply-To: <5857d9f33de7f0ea8ddd12c36334c6463c0bfe0f.1777357321.git.asj@kernel.org>
On Tue, Apr 28, 2026 at 02:42:54PM +0800, Anand Jain wrote:
> Verify that fanotify events are correctly routed to the appropriate
> watcher when cloned filesystems are mounted.
> Helps verify kernel's event notification distinguishes between devices
> sharing the same FSID/UUID.
Do these tests pass with all major file systems? Or does this reproduce
the previous btrfs issues in this area?
^ permalink raw reply
* [PATCH 12/12] swap: move swap_info_struct to mm/swap.h
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
swap_info_struct is now internal to the MM subsystem, so remove it from
the public header.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/swap.h | 98 +-------------------------------------------
mm/swap.h | 92 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+), 96 deletions(-)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 95237ee065c2..31eef9b74949 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -16,9 +16,9 @@
#include <uapi/linux/mempolicy.h>
#include <asm/page.h>
-struct notifier_block;
-
struct bio;
+struct notifier_block;
+struct swap_info_struct;
#define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
#define SWAP_FLAG_PRIO_MASK 0x7fff
@@ -178,29 +178,6 @@ struct sysinfo;
struct writeback_control;
struct zone;
-/*
- * Max bad pages in the new format..
- */
-#define MAX_SWAP_BADPAGES \
- ((offsetof(union swap_header, magic.magic) - \
- offsetof(union swap_header, info.badpages)) / sizeof(int))
-
-enum {
- SWP_USED = (1 << 0), /* is slot in swap_info[] used? */
- SWP_WRITEOK = (1 << 1), /* ok to write to this swap? */
- SWP_DISCARDABLE = (1 << 2), /* blkdev support discard */
- SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */
- SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */
- SWP_BLKDEV = (1 << 6), /* its a block device */
- SWP_ACTIVATED = (1 << 7), /* set after swap_activate success */
- SWP_FS_OPS = (1 << 8), /* swapfile operations go through fs */
- SWP_AREA_DISCARD = (1 << 9), /* single-time swap area discards */
- SWP_PAGE_DISCARD = (1 << 10), /* freed swap page-cluster discards */
- SWP_STABLE_WRITES = (1 << 11), /* no overwrite PG_writeback pages */
- SWP_SYNCHRONOUS_IO = (1 << 12), /* synchronous IO is efficient */
- /* add others here before... */
-};
-
#define SWAP_CLUSTER_MAX 32UL
#define SWAP_CLUSTER_MAX_SKIPPED (SWAP_CLUSTER_MAX << 10)
#define COMPACT_CLUSTER_MAX SWAP_CLUSTER_MAX
@@ -219,56 +196,6 @@ enum {
#define SWAP_NR_ORDERS 1
#endif
-/*
- * We keep using same cluster for rotational device so IO will be sequential.
- * The purpose is to optimize SWAP throughput on these device.
- */
-struct swap_sequential_cluster {
- unsigned int next[SWAP_NR_ORDERS]; /* Likely next allocation offset */
-};
-
-/*
- * The in-memory structure used to track swap areas.
- */
-struct swap_info_struct {
- struct percpu_ref users; /* indicate and keep swap device valid. */
- unsigned long flags; /* SWP_USED etc: see above */
- signed short prio; /* swap priority of this type */
- struct plist_node list; /* entry in swap_active_head */
- signed char type; /* strange name for an index */
- unsigned int max; /* size of this swap device */
- unsigned long *zeromap; /* kvmalloc'ed bitmap to track zero pages */
- struct swap_cluster_info *cluster_info; /* cluster info. Only for SSD */
- struct list_head free_clusters; /* free clusters list */
- struct list_head full_clusters; /* full clusters list */
- struct list_head nonfull_clusters[SWAP_NR_ORDERS];
- /* list of cluster that contains at least one free slot */
- struct list_head frag_clusters[SWAP_NR_ORDERS];
- /* list of cluster that are fragmented or contented */
- unsigned int pages; /* total of usable pages of swap */
- atomic_long_t inuse_pages; /* number of those currently in use */
- struct swap_sequential_cluster *global_cluster; /* Use one global cluster for rotating device */
- spinlock_t global_cluster_lock; /* Serialize usage of global cluster */
- struct rb_root swap_extent_root;/* root of the swap extent rbtree */
- struct block_device *bdev; /* swap device or bdev of swap file */
- struct file *swap_file; /* seldom referenced */
- struct completion comp; /* seldom referenced */
- spinlock_t lock; /*
- * protect map scan related fields like
- * inuse_pages and all cluster lists.
- * Other fields are only changed
- * at swapon/swapoff, so are protected
- * by swap_lock. changing flags need
- * hold this lock and swap_lock. If
- * both locks need hold, hold swap_lock
- * first.
- */
- struct work_struct discard_work; /* discard worker */
- struct work_struct reclaim_work; /* reclaim worker */
- struct list_head discard_clusters; /* discard clusters list */
- struct plist_node avail_list; /* entry in swap_avail_head */
-};
-
static inline swp_entry_t page_swap_entry(struct page *page)
{
struct folio *folio = page_folio(page);
@@ -423,10 +350,7 @@ int find_first_swap(dev_t *device);
extern unsigned int count_swap_pages(int, int);
extern sector_t swapdev_block(int, pgoff_t);
extern int __swap_count(swp_entry_t entry);
-extern bool swap_entry_swapped(struct swap_info_struct *si, swp_entry_t entry);
extern int swp_swapcount(swp_entry_t entry);
-struct backing_dev_info;
-extern struct swap_info_struct *get_swap_device(swp_entry_t entry);
sector_t swap_folio_sector(struct folio *folio);
/*
@@ -452,20 +376,7 @@ bool folio_free_swap(struct folio *folio);
swp_entry_t swap_alloc_hibernation_slot(int type);
void swap_free_hibernation_slot(swp_entry_t entry);
-static inline void put_swap_device(struct swap_info_struct *si)
-{
- percpu_ref_put(&si->users);
-}
-
#else /* CONFIG_SWAP */
-static inline struct swap_info_struct *get_swap_device(swp_entry_t entry)
-{
- return NULL;
-}
-
-static inline void put_swap_device(struct swap_info_struct *si)
-{
-}
#define get_nr_swap_pages() 0L
#define total_swap_pages 0L
@@ -497,11 +408,6 @@ static inline int __swap_count(swp_entry_t entry)
return 0;
}
-static inline bool swap_entry_swapped(struct swap_info_struct *si, swp_entry_t entry)
-{
- return false;
-}
-
static inline int swp_swapcount(swp_entry_t entry)
{
return 0;
diff --git a/mm/swap.h b/mm/swap.h
index a77016f2423b..70974495bf15 100644
--- a/mm/swap.h
+++ b/mm/swap.h
@@ -8,6 +8,79 @@ struct swap_iocb;
extern int page_cluster;
+/*
+ * We keep using same cluster for rotational device so IO will be sequential.
+ * The purpose is to optimize SWAP throughput on these device.
+ */
+struct swap_sequential_cluster {
+ unsigned int next[SWAP_NR_ORDERS]; /* Likely next allocation offset */
+};
+
+/*
+ * The in-memory structure used to track swap areas.
+ */
+struct swap_info_struct {
+ struct percpu_ref users; /* indicate and keep swap device valid. */
+ unsigned long flags; /* SWP_USED etc: see above */
+ signed short prio; /* swap priority of this type */
+ struct plist_node list; /* entry in swap_active_head */
+ signed char type; /* strange name for an index */
+ unsigned int max; /* size of this swap device */
+ unsigned long *zeromap; /* kvmalloc'ed bitmap to track zero pages */
+ struct swap_cluster_info *cluster_info; /* cluster info. Only for SSD */
+ struct list_head free_clusters; /* free clusters list */
+ struct list_head full_clusters; /* full clusters list */
+ struct list_head nonfull_clusters[SWAP_NR_ORDERS];
+ /* list of cluster that contains at least one free slot */
+ struct list_head frag_clusters[SWAP_NR_ORDERS];
+ /* list of cluster that are fragmented or contented */
+ unsigned int pages; /* total of usable pages of swap */
+ atomic_long_t inuse_pages; /* number of those currently in use */
+ struct swap_sequential_cluster *global_cluster; /* Use one global cluster for rotating device */
+ spinlock_t global_cluster_lock; /* Serialize usage of global cluster */
+ struct rb_root swap_extent_root;/* root of the swap extent rbtree */
+ struct block_device *bdev; /* swap device or bdev of swap file */
+ struct file *swap_file; /* seldom referenced */
+ struct completion comp; /* seldom referenced */
+ spinlock_t lock; /*
+ * protect map scan related fields like
+ * inuse_pages and all cluster lists.
+ * Other fields are only changed
+ * at swapon/swapoff, so are protected
+ * by swap_lock. changing flags need
+ * hold this lock and swap_lock. If
+ * both locks need hold, hold swap_lock
+ * first.
+ */
+ struct work_struct discard_work; /* discard worker */
+ struct work_struct reclaim_work; /* reclaim worker */
+ struct list_head discard_clusters; /* discard clusters list */
+ struct plist_node avail_list; /* entry in swap_avail_head */
+};
+
+/*
+ * Max bad pages in the new format..
+ */
+#define MAX_SWAP_BADPAGES \
+ ((offsetof(union swap_header, magic.magic) - \
+ offsetof(union swap_header, info.badpages)) / sizeof(int))
+
+enum {
+ SWP_USED = (1 << 0), /* is slot in swap_info[] used? */
+ SWP_WRITEOK = (1 << 1), /* ok to write to this swap? */
+ SWP_DISCARDABLE = (1 << 2), /* blkdev support discard */
+ SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */
+ SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */
+ SWP_BLKDEV = (1 << 6), /* its a block device */
+ SWP_ACTIVATED = (1 << 7), /* set after swap_activate success */
+ SWP_FS_OPS = (1 << 8), /* swapfile operations go through fs */
+ SWP_AREA_DISCARD = (1 << 9), /* single-time swap area discards */
+ SWP_PAGE_DISCARD = (1 << 10), /* freed swap page-cluster discards */
+ SWP_STABLE_WRITES = (1 << 11), /* no overwrite PG_writeback pages */
+ SWP_SYNCHRONOUS_IO = (1 << 12), /* synchronous IO is efficient */
+ /* add others here before... */
+};
+
#ifdef CONFIG_THP_SWAP
#define SWAPFILE_CLUSTER HPAGE_PMD_NR
#define swap_entry_order(order) (order)
@@ -352,6 +425,13 @@ static inline int non_swapcache_batch(swp_entry_t entry, int max_nr)
return i;
}
+bool swap_entry_swapped(struct swap_info_struct *si, swp_entry_t entry);
+struct swap_info_struct *get_swap_device(swp_entry_t entry);
+static inline void put_swap_device(struct swap_info_struct *si)
+{
+ percpu_ref_put(&si->users);
+}
+
#else /* CONFIG_SWAP */
struct swap_iocb;
static inline struct swap_cluster_info *swap_cluster_lock(
@@ -498,5 +578,17 @@ static inline int non_swapcache_batch(swp_entry_t entry, int max_nr)
{
return 0;
}
+static inline bool swap_entry_swapped(struct swap_info_struct *si,
+ swp_entry_t entry)
+{
+ return false;
+}
+static inline struct swap_info_struct *get_swap_device(swp_entry_t entry)
+{
+ return NULL;
+}
+static inline void put_swap_device(struct swap_info_struct *si)
+{
+}
#endif /* CONFIG_SWAP */
#endif /* _MM_SWAP_H */
--
2.53.0
^ permalink raw reply related
* [PATCH 11/12] swap: move struct swap_extent to swapfile.c
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
struct swap_extent is only used inside of mm/swapfile.c, so move it
there.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/swap.h | 15 ---------------
mm/swapfile.c | 15 +++++++++++++++
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 916889738f08..95237ee065c2 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -178,21 +178,6 @@ struct sysinfo;
struct writeback_control;
struct zone;
-/*
- * A swap extent maps a range of a swapfile's PAGE_SIZE pages onto a range of
- * disk blocks. A rbtree of swap extents maps the entire swapfile (Where the
- * term `swapfile' refers to either a blockdevice or an IS_REG file). Apart
- * from setup, they're handled identically.
- *
- * We always assume that blocks are of size PAGE_SIZE.
- */
-struct swap_extent {
- struct rb_node rb_node;
- pgoff_t start_page;
- pgoff_t nr_pages;
- sector_t start_block;
-};
-
/*
* Max bad pages in the new format..
*/
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 26852c2ad36e..c0479533f9ef 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -260,6 +260,21 @@ static int __try_to_reclaim_swap(struct swap_info_struct *si,
return ret;
}
+/*
+ * A swap extent maps a range of a swapfile's PAGE_SIZE pages onto a range of
+ * disk blocks. A rbtree of swap extents maps the entire swapfile (Where the
+ * term `swapfile' refers to either a blockdevice or an IS_REG file). Apart
+ * from setup, they're handled identically.
+ *
+ * We always assume that blocks are of size PAGE_SIZE.
+ */
+struct swap_extent {
+ struct rb_node rb_node;
+ pgoff_t start_page;
+ pgoff_t nr_pages;
+ sector_t start_block;
+};
+
static inline struct swap_extent *first_se(struct swap_info_struct *sis)
{
struct rb_node *rb = rb_first(&sis->swap_extent_root);
--
2.53.0
^ permalink raw reply related
* [PATCH 10/12] swap: add a swap_activate_fs_ops helper
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
Add a helper abstracting away the low-level details of enabling
fs_ops-based swapping. This prepares for taking swap_info_struct
private.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/file.c | 4 +---
fs/smb/client/file.c | 3 +--
include/linux/swap.h | 5 +++++
mm/swapfile.c | 7 +++++++
4 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 10ab2a923835..ce4d860c4e7a 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -588,7 +588,7 @@ int nfs_swap_activate(struct file *file, struct swap_info_struct *sis)
ret = rpc_clnt_swap_activate(clnt);
if (ret)
return ret;
- ret = add_swap_extent(sis, sis->max, NULL, 0);
+ ret = swap_activate_fs_ops(sis);
if (ret < 0) {
rpc_clnt_swap_deactivate(clnt);
return ret;
@@ -596,8 +596,6 @@ int nfs_swap_activate(struct file *file, struct swap_info_struct *sis)
if (cl->rpc_ops->enable_swap)
cl->rpc_ops->enable_swap(inode);
-
- sis->flags |= SWP_FS_OPS;
return 0;
}
EXPORT_SYMBOL_GPL(nfs_swap_activate);
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index e1bbc65ce7f3..e11065be1e64 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -3326,8 +3326,7 @@ int cifs_swap_activate(struct file *swap_file, struct swap_info_struct *sis)
* from reading or writing the file
*/
- sis->flags |= SWP_FS_OPS;
- return add_swap_extent(sis, sis->max, NULL, 0);
+ return swap_activate_fs_ops(sis);
}
void cifs_swap_deactivate(struct file *file)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index b1cbb67ddd8e..916889738f08 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -406,6 +406,7 @@ extern void __meminit kswapd_stop(int nid);
int add_swap_extent(struct swap_info_struct *sis, unsigned long nr_pages,
struct block_device *bdev, sector_t start_block);
int generic_swap_activate(struct file *swap_file, struct swap_info_struct *sis);
+int swap_activate_fs_ops(struct swap_info_struct *sis);
static inline unsigned long total_swapcache_pages(void)
{
@@ -532,6 +533,10 @@ static inline int add_swap_extent(struct swap_info_struct *sis,
{
return -EINVAL;
}
+static inline int swap_activate_fs_ops(struct swap_info_struct *sis)
+{
+ return -EINVAL;
+}
#endif /* CONFIG_SWAP */
#ifdef CONFIG_MEMCG
static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 2c9d2af736c4..26852c2ad36e 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2757,6 +2757,13 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long nr_pages,
}
EXPORT_SYMBOL_GPL(add_swap_extent);
+int swap_activate_fs_ops(struct swap_info_struct *sis)
+{
+ sis->flags |= SWP_FS_OPS;
+ return add_swap_extent(sis, sis->max, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(swap_activate_fs_ops);
+
/*
* A `swap extent' is a simple thing which maps a contiguous range of pages
* onto a contiguous range of disk blocks. A rbtree of swap extents is
--
2.53.0
^ permalink raw reply related
* [PATCH 09/12] swap: push down setting sis->bdev into ->swap_activate
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
Only the file operation method knows what block device we'll swap
to. So move down setting sis->bdev and the special blockdev flag
into ->swap_activate.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/fops.c | 9 ++++++++-
fs/btrfs/inode.c | 7 ++++---
fs/f2fs/data.c | 3 ++-
fs/iomap/swapfile.c | 7 ++-----
fs/nfs/file.c | 2 +-
fs/smb/client/file.c | 2 +-
fs/xfs/xfs_file.c | 6 ------
include/linux/swap.h | 4 ++--
mm/page_io.c | 3 +--
mm/swapfile.c | 38 ++++++++++++--------------------------
10 files changed, 33 insertions(+), 48 deletions(-)
diff --git a/block/fops.c b/block/fops.c
index 067e46299666..da09ce3f072f 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -951,9 +951,16 @@ static int blkdev_mmap_prepare(struct vm_area_desc *desc)
static int blkdev_swap_activate(struct file *file, struct swap_info_struct *sis)
{
+ struct block_device *bdev = I_BDEV(file->f_mapping->host);
loff_t isize = i_size_read(bdev_file_inode(file));
- return add_swap_extent(sis, div_u64(isize, PAGE_SIZE), 0);
+ /*
+ * The swap code performs arbitrary overwrites, which are not supported
+ * on zones with sequential write constraints.
+ */
+ if (bdev_is_zoned(bdev))
+ return -EINVAL;
+ return add_swap_extent(sis, div_u64(isize, PAGE_SIZE), bdev, 0);
}
const struct file_operations def_blk_fops = {
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ee0a7947706a..84003c520530 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -10201,6 +10201,7 @@ static void btrfs_free_swapfile_pins(struct inode *inode)
}
struct btrfs_swap_info {
+ struct btrfs_device *device;
u64 start;
u64 block_start;
u64 block_len;
@@ -10214,7 +10215,8 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis,
first_ppage = PAGE_ALIGN(bsi->block_start) >> PAGE_SHIFT;
next_ppage = PAGE_ALIGN_DOWN(bsi->block_start + bsi->block_len) >> PAGE_SHIFT;
- return add_swap_extent(sis, next_ppage - first_ppage, first_ppage);
+ return add_swap_extent(sis, next_ppage - first_ppage, bsi->device->bdev,
+ first_ppage);
}
void btrfs_swap_deactivate(struct file *file)
@@ -10503,6 +10505,7 @@ int btrfs_swap_activate(struct file *file, struct swap_info_struct *sis)
bsi.start = key.offset;
bsi.block_start = physical_block_start;
bsi.block_len = len;
+ bsi.device = device;
}
if (fatal_signal_pending(current)) {
@@ -10533,8 +10536,6 @@ int btrfs_swap_activate(struct file *file, struct swap_info_struct *sis)
up_write(&BTRFS_I(inode)->i_mmap_lock);
btrfs_free_backref_share_ctx(backref_ctx);
btrfs_free_path(path);
- if (!ret && device)
- sis->bdev = device->bdev;
return ret;
}
#endif
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 8bcf630df557..8d116ff517c9 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -4326,7 +4326,8 @@ static int check_swap_activate(struct swap_info_struct *sis,
/*
* We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks
*/
- ret = add_swap_extent(sis, nr_pblocks, pblock);
+ ret = add_swap_extent(sis, nr_pblocks, inode->i_sb->s_bdev,
+ pblock);
if (ret < 0)
goto out;
cur_lblock += nr_pblocks;
diff --git a/fs/iomap/swapfile.c b/fs/iomap/swapfile.c
index a4e0ca462cc4..862b4c02a8bd 100644
--- a/fs/iomap/swapfile.c
+++ b/fs/iomap/swapfile.c
@@ -50,10 +50,6 @@ static int iomap_swapfile_iter(struct iomap_iter *iter, struct file *file,
if (iomap->flags & IOMAP_F_SHARED)
return iomap_swapfile_fail(file, "has shared extents");
- /* Only one bdev per swap file. */
- if (iomap->bdev != sis->bdev)
- return iomap_swapfile_fail(file, "outside the main device");
-
/*
* Round the start up and the end down so that the physical extent
* aligns to a page boundary.
@@ -61,7 +57,8 @@ static int iomap_swapfile_iter(struct iomap_iter *iter, struct file *file,
first_ppage = ALIGN(iomap->addr, PAGE_SIZE) >> PAGE_SHIFT;
next_ppage = ALIGN_DOWN(iomap->addr + iomap->length, PAGE_SIZE) >>
PAGE_SHIFT;
- error = add_swap_extent(sis, next_ppage - first_ppage, first_ppage);
+ error = add_swap_extent(sis, next_ppage - first_ppage, iomap->bdev,
+ first_ppage);
if (error)
return error;
return iomap_iter_advance_full(iter);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 2bc55d9d71e1..10ab2a923835 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -588,7 +588,7 @@ int nfs_swap_activate(struct file *file, struct swap_info_struct *sis)
ret = rpc_clnt_swap_activate(clnt);
if (ret)
return ret;
- ret = add_swap_extent(sis, sis->max, 0);
+ ret = add_swap_extent(sis, sis->max, NULL, 0);
if (ret < 0) {
rpc_clnt_swap_deactivate(clnt);
return ret;
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 84459f87907e..e1bbc65ce7f3 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -3327,7 +3327,7 @@ int cifs_swap_activate(struct file *swap_file, struct swap_info_struct *sis)
*/
sis->flags |= SWP_FS_OPS;
- return add_swap_extent(sis, sis->max, 0);
+ return add_swap_extent(sis, sis->max, NULL, 0);
}
void cifs_swap_deactivate(struct file *file)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 41f7e19bd31f..74128ebf7161 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -2116,12 +2116,6 @@ xfs_file_swap_activate(
*/
xfs_inodegc_flush(ip->i_mount);
- /*
- * Direct the swap code to the correct block device when this file
- * sits on the RT device.
- */
- sis->bdev = xfs_inode_buftarg(ip)->bt_bdev;
-
return iomap_swap_activate(file, sis, &xfs_read_iomap_ops);
}
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 657779485ae4..b1cbb67ddd8e 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -404,7 +404,7 @@ extern void __meminit kswapd_stop(int nid);
#ifdef CONFIG_SWAP
int add_swap_extent(struct swap_info_struct *sis, unsigned long nr_pages,
- sector_t start_block);
+ struct block_device *bdev, sector_t start_block);
int generic_swap_activate(struct file *swap_file, struct swap_info_struct *sis);
static inline unsigned long total_swapcache_pages(void)
@@ -528,7 +528,7 @@ static inline bool folio_free_swap(struct folio *folio)
static inline int add_swap_extent(struct swap_info_struct *sis,
unsigned long start_page, unsigned long nr_pages,
- sector_t start_block)
+ struct block_device *bdev, sector_t start_block)
{
return -EINVAL;
}
diff --git a/mm/page_io.c b/mm/page_io.c
index 3e1c12649448..2ab8994ed1c2 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -132,7 +132,7 @@ int generic_swap_activate(struct file *swap_file, struct swap_info_struct *sis)
/*
* We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks
*/
- ret = add_swap_extent(sis, 1,
+ ret = add_swap_extent(sis, 1, inode->i_sb->s_bdev,
first_block >> (PAGE_SHIFT - blkbits));
if (ret < 0)
return ret;
@@ -141,7 +141,6 @@ int generic_swap_activate(struct file *swap_file, struct swap_info_struct *sis)
continue;
}
return 0;
-
bad_bmap:
pr_err("swapon: swapfile has holes\n");
return -EINVAL;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index fbf11c8c5c69..2c9d2af736c4 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2707,7 +2707,7 @@ static void destroy_swap_extents(struct swap_info_struct *sis,
*/
int
add_swap_extent(struct swap_info_struct *sis, unsigned long nr_pages,
- sector_t start_block)
+ struct block_device *bdev, sector_t start_block)
{
struct rb_node **link = &sis->swap_extent_root.rb_node, *parent = NULL;
struct swap_extent *se;
@@ -2718,6 +2718,12 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long nr_pages,
return 0;
nr_pages = min(nr_pages, sis->max - sis->pages);
+ /* Only one bdev per swap file for now. */
+ if (!sis->bdev)
+ sis->bdev = bdev;
+ else if (bdev != sis->bdev)
+ return -EINVAL;
+
/*
* place the new node at the right most since the
* function is called in ascending page order.
@@ -2793,6 +2799,8 @@ static int setup_swap_extents(struct swap_info_struct *sis,
sis->flags |= SWP_ACTIVATED;
if (sis->flags & SWP_FS_OPS)
error = sio_pool_init();
+ else if (WARN_ON_ONCE(!sis->bdev))
+ error = -EINVAL;
if (error)
destroy_swap_extents(sis, swap_file);
return error;
@@ -3224,26 +3232,6 @@ static struct swap_info_struct *alloc_swap_info(void)
return p;
}
-static int claim_swapfile(struct swap_info_struct *si, struct inode *inode)
-{
- if (S_ISBLK(inode->i_mode)) {
- si->bdev = I_BDEV(inode);
- /*
- * Zoned block devices contain zones that have a sequential
- * write only restriction. Hence zoned block devices are not
- * suitable for swapping. Disallow them here.
- */
- if (bdev_is_zoned(si->bdev))
- return -EINVAL;
- si->flags |= SWP_BLKDEV;
- } else if (S_ISREG(inode->i_mode)) {
- si->bdev = inode->i_sb->s_bdev;
- }
-
- return 0;
-}
-
-
/*
* Find out how many pages are allowed for a single swap device. There
* are two limiting factors:
@@ -3500,16 +3488,14 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
dentry = swap_file->f_path.dentry;
inode = mapping->host;
- error = claim_swapfile(si, inode);
- if (unlikely(error))
- goto bad_swap;
-
inode_lock(inode);
if (d_unlinked(dentry) || cant_mount(dentry)) {
error = -ENOENT;
goto bad_swap_unlock_inode;
}
- if (!S_ISBLK(inode->i_mode) && !S_ISREG(inode->i_mode)) {
+ if (S_ISBLK(inode->i_mode)) {
+ si->flags |= SWP_BLKDEV;
+ } else if (!S_ISREG(inode->i_mode)) {
error = -EINVAL;
goto bad_swap_unlock_inode;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 08/12] swap,iomap: simplify iomap_swapfile_iter
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
add_swap_extent already coalesces multiple extents, no need to duplicate
that in the caller.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/iomap/swapfile.c | 104 +++++++++++++-------------------------------
1 file changed, 31 insertions(+), 73 deletions(-)
diff --git a/fs/iomap/swapfile.c b/fs/iomap/swapfile.c
index cf354fdfb7c3..a4e0ca462cc4 100644
--- a/fs/iomap/swapfile.c
+++ b/fs/iomap/swapfile.c
@@ -6,57 +6,32 @@
#include <linux/iomap.h>
#include <linux/swap.h>
-/* Swapfile activation */
-
-struct iomap_swapfile_info {
- struct iomap iomap; /* accumulated iomap */
- struct swap_info_struct *sis;
- unsigned long nr_pages; /* number of pages collected */
- struct file *file;
-};
-
-/*
- * Collect physical extents for this swap file. Physical extents reported to
- * the swap code must be trimmed to align to a page boundary. The logical
- * offset within the file is irrelevant since the swapfile code maps logical
- * page numbers of the swap device to the physical page-aligned extents.
- */
-static int iomap_swapfile_add_extent(struct iomap_swapfile_info *isi)
-{
- struct iomap *iomap = &isi->iomap;
- uint64_t first_ppage;
- uint64_t next_ppage;
-
- /*
- * Round the start up and the end down so that the physical
- * extent aligns to a page boundary.
- */
- first_ppage = ALIGN(iomap->addr, PAGE_SIZE) >> PAGE_SHIFT;
- next_ppage = ALIGN_DOWN(iomap->addr + iomap->length, PAGE_SIZE) >>
- PAGE_SHIFT;
- return add_swap_extent(isi->sis, next_ppage - first_ppage, first_ppage);
-}
-
-static int iomap_swapfile_fail(struct iomap_swapfile_info *isi, const char *str)
+static int iomap_swapfile_fail(struct file *file, const char *str)
{
char *buf, *p = ERR_PTR(-ENOMEM);
buf = kmalloc(PATH_MAX, GFP_KERNEL);
if (buf)
- p = file_path(isi->file, buf, PATH_MAX);
+ p = file_path(file, buf, PATH_MAX);
pr_err("swapon: file %s %s\n", IS_ERR(p) ? "<unknown>" : p, str);
kfree(buf);
return -EINVAL;
}
/*
- * Accumulate iomaps for this swap file. We have to accumulate iomaps because
- * swap only cares about contiguous page-aligned physical extents and makes no
- * distinction between written and unwritten extents.
+ * Report physical extents for this swap file. Physical extents reported to the
+ * swap code must be trimmed to align to a page boundary. The logical offset
+ * within the file is irrelevant since the swapfile code maps logical page
+ * numbers of the swap device to the physical page-aligned extents.
*/
-static int iomap_swapfile_iter(struct iomap_iter *iter,
- struct iomap *iomap, struct iomap_swapfile_info *isi)
+static int iomap_swapfile_iter(struct iomap_iter *iter, struct file *file,
+ struct swap_info_struct *sis)
{
+ struct iomap *iomap = &iter->iomap;
+ uint64_t first_ppage;
+ uint64_t next_ppage;
+ int error;
+
switch (iomap->type) {
case IOMAP_MAPPED:
case IOMAP_UNWRITTEN:
@@ -64,35 +39,31 @@ static int iomap_swapfile_iter(struct iomap_iter *iter,
break;
case IOMAP_INLINE:
/* No inline data. */
- return iomap_swapfile_fail(isi, "is inline");
+ return iomap_swapfile_fail(file, "is inline");
default:
- return iomap_swapfile_fail(isi, "has unallocated extents");
+ return iomap_swapfile_fail(file, "has unallocated extents");
}
/* No uncommitted metadata or shared blocks. */
if (iomap->flags & IOMAP_F_DIRTY)
- return iomap_swapfile_fail(isi, "is not committed");
+ return iomap_swapfile_fail(file, "is not committed");
if (iomap->flags & IOMAP_F_SHARED)
- return iomap_swapfile_fail(isi, "has shared extents");
+ return iomap_swapfile_fail(file, "has shared extents");
/* Only one bdev per swap file. */
- if (iomap->bdev != isi->sis->bdev)
- return iomap_swapfile_fail(isi, "outside the main device");
-
- if (isi->iomap.length == 0) {
- /* No accumulated extent, so just store it. */
- memcpy(&isi->iomap, iomap, sizeof(isi->iomap));
- } else if (isi->iomap.addr + isi->iomap.length == iomap->addr) {
- /* Append this to the accumulated extent. */
- isi->iomap.length += iomap->length;
- } else {
- /* Otherwise, add the retained iomap and store this one. */
- int error = iomap_swapfile_add_extent(isi);
- if (error)
- return error;
- memcpy(&isi->iomap, iomap, sizeof(isi->iomap));
- }
+ if (iomap->bdev != sis->bdev)
+ return iomap_swapfile_fail(file, "outside the main device");
+ /*
+ * Round the start up and the end down so that the physical extent
+ * aligns to a page boundary.
+ */
+ first_ppage = ALIGN(iomap->addr, PAGE_SIZE) >> PAGE_SHIFT;
+ next_ppage = ALIGN_DOWN(iomap->addr + iomap->length, PAGE_SIZE) >>
+ PAGE_SHIFT;
+ error = add_swap_extent(sis, next_ppage - first_ppage, first_ppage);
+ if (error)
+ return error;
return iomap_iter_advance_full(iter);
}
@@ -110,10 +81,6 @@ int iomap_swap_activate(struct file *file, struct swap_info_struct *sis,
.len = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE),
.flags = IOMAP_REPORT,
};
- struct iomap_swapfile_info isi = {
- .sis = sis,
- .file = file,
- };
int ret;
/*
@@ -125,16 +92,7 @@ int iomap_swap_activate(struct file *file, struct swap_info_struct *sis,
return ret;
while ((ret = iomap_iter(&iter, ops)) > 0)
- iter.status = iomap_swapfile_iter(&iter, &iter.iomap, &isi);
- if (ret < 0)
- return ret;
-
- if (isi.iomap.length) {
- ret = iomap_swapfile_add_extent(&isi);
- if (ret)
- return ret;
- }
-
- return 0;
+ iter.status = iomap_swapfile_iter(&iter, file, sis);
+ return ret;
}
EXPORT_SYMBOL_GPL(iomap_swap_activate);
--
2.53.0
^ permalink raw reply related
* [PATCH 07/12] swap,block: limit swap file size to device size
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
Don't blindly pass the value from the swap header to swap_add_extent,
but instead the device size rounded down to page granularity. This
activated the sanity checking in the core code that catches a too large
value in the swap header.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/fops.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/block/fops.c b/block/fops.c
index 453141801684..067e46299666 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -951,7 +951,9 @@ static int blkdev_mmap_prepare(struct vm_area_desc *desc)
static int blkdev_swap_activate(struct file *file, struct swap_info_struct *sis)
{
- return add_swap_extent(sis, sis->max, 0);
+ loff_t isize = i_size_read(bdev_file_inode(file));
+
+ return add_swap_extent(sis, div_u64(isize, PAGE_SIZE), 0);
}
const struct file_operations def_blk_fops = {
--
2.53.0
^ permalink raw reply related
* [PATCH 06/12] swap,block: move the block device swapon code into block/fops.c
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
Make use of the abstractions we have. This is a preparation for
moving more special casing down into block/.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/fops.c | 6 ++++++
mm/swapfile.c | 5 -----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/block/fops.c b/block/fops.c
index bb6642b45937..453141801684 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -949,6 +949,11 @@ static int blkdev_mmap_prepare(struct vm_area_desc *desc)
return generic_file_mmap_prepare(desc);
}
+static int blkdev_swap_activate(struct file *file, struct swap_info_struct *sis)
+{
+ return add_swap_extent(sis, sis->max, 0);
+}
+
const struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_release,
@@ -965,6 +970,7 @@ const struct file_operations def_blk_fops = {
.splice_read = filemap_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = blkdev_fallocate,
+ .swap_activate = blkdev_swap_activate,
.uring_cmd = blkdev_uring_cmd,
.fop_flags = FOP_BUFFER_RASYNC,
};
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 1b7fc03612f4..fbf11c8c5c69 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2781,13 +2781,8 @@ EXPORT_SYMBOL_GPL(add_swap_extent);
static int setup_swap_extents(struct swap_info_struct *sis,
struct file *swap_file)
{
- struct address_space *mapping = swap_file->f_mapping;
- struct inode *inode = mapping->host;
int ret, error = 0;
- if (S_ISBLK(inode->i_mode))
- return add_swap_extent(sis, sis->max, 0);
-
if (swap_file->f_op->swap_activate)
ret = swap_file->f_op->swap_activate(swap_file, sis);
else
--
2.53.0
^ permalink raw reply related
* [PATCH 05/12] swap: cleanup setup_swap_extents
From: Christoph Hellwig @ 2026-05-12 5:35 UTC (permalink / raw)
To: Andrew Morton, Chris Li, Kairui Song
Cc: Christian Brauner, Darrick J . Wong , Jens Axboe, David Sterba,
Theodore Ts'o, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Namjae Jeon, Hyunchul Lee, Steve French,
Paulo Alcantara, Carlos Maiolino, Damien Le Moal, Naohiro Aota,
linux-xfs, linux-fsdevel, linux-doc, linux-mm, linux-block,
linux-btrfs, linux-ext4, linux-f2fs-devel, linux-nfs, linux-cifs
In-Reply-To: <20260512053625.2950900-1-hch@lst.de>
Reflow setup_swap_extents so that the flag checking is not conditional on
a swap_activate method. This is currently a no-op because the swapoff
code still checks the presence of a swap_deactivate method, but it
simplifies adding a new check, and also makes the SWP_ACTIVATED flag
more consistent.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/swapfile.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 651c1b59ff9f..1b7fc03612f4 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2783,25 +2783,24 @@ static int setup_swap_extents(struct swap_info_struct *sis,
{
struct address_space *mapping = swap_file->f_mapping;
struct inode *inode = mapping->host;
- int ret;
+ int ret, error = 0;
if (S_ISBLK(inode->i_mode))
return add_swap_extent(sis, sis->max, 0);
- if (swap_file->f_op->swap_activate) {
+ if (swap_file->f_op->swap_activate)
ret = swap_file->f_op->swap_activate(swap_file, sis);
- if (ret < 0)
- return ret;
- sis->flags |= SWP_ACTIVATED;
- if ((sis->flags & SWP_FS_OPS) &&
- sio_pool_init() != 0) {
- destroy_swap_extents(sis, swap_file);
- return -ENOMEM;
- }
+ else
+ ret = generic_swap_activate(swap_file, sis);
+ if (ret < 0)
return ret;
- }
- return generic_swap_activate(swap_file, sis);
+ sis->flags |= SWP_ACTIVATED;
+ if (sis->flags & SWP_FS_OPS)
+ error = sio_pool_init();
+ if (error)
+ destroy_swap_extents(sis, swap_file);
+ return error;
}
static void _enable_swap_info(struct swap_info_struct *si)
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox