* [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods
@ 2026-03-28 7:58 Barry Song
2026-03-28 7:58 ` [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c Barry Song
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Barry Song @ 2026-03-28 7:58 UTC (permalink / raw)
To: akpm, linux-mm
Cc: bhe, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park,
linux-kernel
From: Barry Song <baohua@kernel.org>
-v2:
* lots of cleanup for patch 2/3: renaming, moving data
structures, and using const properly
* collected tags from Kairui, Nhat and Barry
-v1:
https://lore.kernel.org/linux-mm/20260302104016.163542-1-bhe@redhat.com/
This can simplify the code logic and benefit any new type of swap device
added later.
And also do renaming in this patchset:
-------
file renaming:
---
mm/page_io.c to mm/swap_io.c
function renaming:
---
swap_writepage_* to swap_write_folio_* in file mm/swap_io.c
Baoquan He (3):
mm/swap: rename mm/page_io.c to mm/swap_io.c
mm/swap: use swap_ops to register swap device's methods
mm/swap_io.c: rename swap_writepage_* to swap_write_folio_*
MAINTAINERS | 2 +-
include/linux/swap.h | 2 +
mm/Makefile | 2 +-
mm/swap.h | 12 ++++-
mm/{page_io.c => swap_io.c} | 101 ++++++++++++++++++++----------------
mm/swapfile.c | 1 +
mm/zswap.c | 3 +-
7 files changed, 73 insertions(+), 50 deletions(-)
rename mm/{page_io.c => swap_io.c} (89%)
--
2.39.3 (Apple Git-146)
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c 2026-03-28 7:58 [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Barry Song @ 2026-03-28 7:58 ` Barry Song 2026-03-29 14:31 ` Chris Li 2026-03-28 7:58 ` [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods Barry Song ` (2 subsequent siblings) 3 siblings, 1 reply; 13+ messages in thread From: Barry Song @ 2026-03-28 7:58 UTC (permalink / raw) To: akpm, linux-mm Cc: bhe, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel From: Baoquan He <bhe@redhat.com> Codes in mm/page_io.c are only related to swap io, it has nothing to do with other page io. Rename it to avoid confusion. Reviewed-by: Nhat Pham <nphamcs@gmail.com> Reviewed-by: Barry Song <baohua@kernel.org> Acked-by: Kairui Song <kasong@tencent.com> Signed-off-by: Baoquan He <bhe@redhat.com> Signed-off-by: Barry Song <baohua@kernel.org> --- MAINTAINERS | 2 +- mm/Makefile | 2 +- mm/swap.h | 2 +- mm/{page_io.c => swap_io.c} | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) rename mm/{page_io.c => swap_io.c} (99%) diff --git a/MAINTAINERS b/MAINTAINERS index 16874c32e288..bb7c1031886d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16915,7 +16915,7 @@ F: Documentation/mm/swap-table.rst F: include/linux/swap.h F: include/linux/swapfile.h F: include/linux/swapops.h -F: mm/page_io.c +F: mm/swap_io.c F: mm/swap.c F: mm/swap.h F: mm/swap_table.h diff --git a/mm/Makefile b/mm/Makefile index 8ad2ab08244e..a65ac900096a 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -75,7 +75,7 @@ ifdef CONFIG_MMU obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o endif -obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o +obj-$(CONFIG_SWAP) += swap_io.o swap_state.o swapfile.o obj-$(CONFIG_ZSWAP) += zswap.o obj-$(CONFIG_HAS_DMA) += dmapool.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o hugetlb_sysfs.o hugetlb_sysctl.o diff --git a/mm/swap.h b/mm/swap.h index a77016f2423b..161185057993 100644 --- a/mm/swap.h +++ b/mm/swap.h @@ -214,7 +214,7 @@ extern void __swap_cluster_free_entries(struct swap_info_struct *si, struct swap_cluster_info *ci, unsigned int ci_off, unsigned int nr_pages); -/* linux/mm/page_io.c */ +/* linux/mm/swap_io.c */ int sio_pool_init(void); struct swap_iocb; void swap_read_folio(struct folio *folio, struct swap_iocb **plug); diff --git a/mm/page_io.c b/mm/swap_io.c similarity index 99% rename from mm/page_io.c rename to mm/swap_io.c index 70cea9e24d2f..91b33d955e63 100644 --- a/mm/page_io.c +++ b/mm/swap_io.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 /* - * linux/mm/page_io.c - * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * * Swap reorganised 29.12.95, -- 2.39.3 (Apple Git-146) ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c 2026-03-28 7:58 ` [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c Barry Song @ 2026-03-29 14:31 ` Chris Li 0 siblings, 0 replies; 13+ messages in thread From: Chris Li @ 2026-03-29 14:31 UTC (permalink / raw) To: Barry Song Cc: akpm, linux-mm, bhe, baohua, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel Hi Barry, Thanks for the patch. Acked-by: Chris Li <chrisl@kernel.org> Chris On Sat, Mar 28, 2026 at 12:58 AM Barry Song <21cnbao@gmail.com> wrote: > > From: Baoquan He <bhe@redhat.com> > > Codes in mm/page_io.c are only related to swap io, it has > nothing to do with other page io. > > Rename it to avoid confusion. > > Reviewed-by: Nhat Pham <nphamcs@gmail.com> > Reviewed-by: Barry Song <baohua@kernel.org> > Acked-by: Kairui Song <kasong@tencent.com> > Signed-off-by: Baoquan He <bhe@redhat.com> > Signed-off-by: Barry Song <baohua@kernel.org> > --- > MAINTAINERS | 2 +- > mm/Makefile | 2 +- > mm/swap.h | 2 +- > mm/{page_io.c => swap_io.c} | 2 -- > 4 files changed, 3 insertions(+), 5 deletions(-) > rename mm/{page_io.c => swap_io.c} (99%) > > diff --git a/MAINTAINERS b/MAINTAINERS > index 16874c32e288..bb7c1031886d 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -16915,7 +16915,7 @@ F: Documentation/mm/swap-table.rst > F: include/linux/swap.h > F: include/linux/swapfile.h > F: include/linux/swapops.h > -F: mm/page_io.c > +F: mm/swap_io.c > F: mm/swap.c > F: mm/swap.h > F: mm/swap_table.h > diff --git a/mm/Makefile b/mm/Makefile > index 8ad2ab08244e..a65ac900096a 100644 > --- a/mm/Makefile > +++ b/mm/Makefile > @@ -75,7 +75,7 @@ ifdef CONFIG_MMU > obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o > endif > > -obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o > +obj-$(CONFIG_SWAP) += swap_io.o swap_state.o swapfile.o > obj-$(CONFIG_ZSWAP) += zswap.o > obj-$(CONFIG_HAS_DMA) += dmapool.o > obj-$(CONFIG_HUGETLBFS) += hugetlb.o hugetlb_sysfs.o hugetlb_sysctl.o > diff --git a/mm/swap.h b/mm/swap.h > index a77016f2423b..161185057993 100644 > --- a/mm/swap.h > +++ b/mm/swap.h > @@ -214,7 +214,7 @@ extern void __swap_cluster_free_entries(struct swap_info_struct *si, > struct swap_cluster_info *ci, > unsigned int ci_off, unsigned int nr_pages); > > -/* linux/mm/page_io.c */ > +/* linux/mm/swap_io.c */ > int sio_pool_init(void); > struct swap_iocb; > void swap_read_folio(struct folio *folio, struct swap_iocb **plug); > diff --git a/mm/page_io.c b/mm/swap_io.c > similarity index 99% > rename from mm/page_io.c > rename to mm/swap_io.c > index 70cea9e24d2f..91b33d955e63 100644 > --- a/mm/page_io.c > +++ b/mm/swap_io.c > @@ -1,7 +1,5 @@ > // SPDX-License-Identifier: GPL-2.0 > /* > - * linux/mm/page_io.c > - * > * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds > * > * Swap reorganised 29.12.95, > -- > 2.39.3 (Apple Git-146) > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-28 7:58 [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Barry Song 2026-03-28 7:58 ` [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c Barry Song @ 2026-03-28 7:58 ` Barry Song 2026-03-29 10:49 ` kernel test robot ` (2 more replies) 2026-03-28 7:58 ` [PATCH v2 3/3] mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* Barry Song 2026-03-30 0:54 ` [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Baoquan He 3 siblings, 3 replies; 13+ messages in thread From: Barry Song @ 2026-03-28 7:58 UTC (permalink / raw) To: akpm, linux-mm Cc: bhe, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel From: Baoquan He <bhe@redhat.com> This simplifies codes and makes logic clearer. And also makes later any new swap device type being added easier to handle. Currently there are three types of swap devices: bdev_fs, bdev_sync and bdev_async, and only operations read_folio and write_folio are included. In the future, there could be more swap device types added and more appropriate opeations adapted into swap_ops. Suggested-by: Chris Li <chrisl@kernel.org> Signed-off-by: Baoquan He <bhe@redhat.com> Co-developed-by: Barry Song <baohua@kernel.org> Signed-off-by: Barry Song <baohua@kernel.org> --- include/linux/swap.h | 2 + mm/swap.h | 10 ++++- mm/swap_io.c | 99 +++++++++++++++++++++++++------------------- mm/swapfile.c | 1 + mm/zswap.c | 3 +- 5 files changed, 70 insertions(+), 45 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 1930f81e6be4..b52f30dad72b 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -243,6 +243,7 @@ struct swap_sequential_cluster { unsigned int next[SWAP_NR_ORDERS]; /* Likely next allocation offset */ }; +struct swap_ops; /* * The in-memory structure used to track swap areas. */ @@ -283,6 +284,7 @@ struct swap_info_struct { 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 */ + const struct swap_ops *ops; }; static inline swp_entry_t page_swap_entry(struct page *page) diff --git a/mm/swap.h b/mm/swap.h index 161185057993..219dbcb3ffb1 100644 --- a/mm/swap.h +++ b/mm/swap.h @@ -217,6 +217,15 @@ extern void __swap_cluster_free_entries(struct swap_info_struct *si, /* linux/mm/swap_io.c */ int sio_pool_init(void); struct swap_iocb; +struct swap_ops { + void (*read_folio)(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug); + void (*write_folio)(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug); +}; +void setup_swap_ops(struct swap_info_struct *sis); void swap_read_folio(struct folio *folio, struct swap_iocb **plug); void __swap_read_unplug(struct swap_iocb *plug); static inline void swap_read_unplug(struct swap_iocb *plug) @@ -226,7 +235,6 @@ static inline void swap_read_unplug(struct swap_iocb *plug) } void swap_write_unplug(struct swap_iocb *sio); int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug); -void __swap_writepage(struct folio *folio, struct swap_iocb **swap_plug); /* linux/mm/swap_state.c */ extern struct address_space swap_space __read_mostly; diff --git a/mm/swap_io.c b/mm/swap_io.c index 91b33d955e63..ad0895af6ed8 100644 --- a/mm/swap_io.c +++ b/mm/swap_io.c @@ -238,6 +238,7 @@ static void swap_zeromap_folio_clear(struct folio *folio) int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug) { int ret = 0; + struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); if (folio_free_swap(folio)) goto out_unlock; @@ -283,7 +284,8 @@ int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug) } rcu_read_unlock(); - __swap_writepage(folio, swap_plug); + VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); + sis->ops->write_folio(sis, folio, swap_plug); return 0; out_unlock: folio_unlock(folio); @@ -373,10 +375,11 @@ static void sio_write_complete(struct kiocb *iocb, long ret) mempool_free(sio, sio_pool); } -static void swap_writepage_fs(struct folio *folio, struct swap_iocb **swap_plug) +static void swap_writepage_fs(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **swap_plug) { struct swap_iocb *sio = swap_plug ? *swap_plug : NULL; - struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); struct file *swap_file = sis->swap_file; loff_t pos = swap_dev_pos(folio->swap); @@ -409,8 +412,9 @@ static void swap_writepage_fs(struct folio *folio, struct swap_iocb **swap_plug) *swap_plug = sio; } -static void swap_writepage_bdev_sync(struct folio *folio, - struct swap_info_struct *sis) +static void swap_writepage_bdev_sync(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug) { struct bio_vec bv; struct bio bio; @@ -429,8 +433,9 @@ static void swap_writepage_bdev_sync(struct folio *folio, __end_swap_bio_write(&bio); } -static void swap_writepage_bdev_async(struct folio *folio, - struct swap_info_struct *sis) +static void swap_writepage_bdev_async(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug) { struct bio *bio; @@ -446,29 +451,6 @@ static void swap_writepage_bdev_async(struct folio *folio, submit_bio(bio); } -void __swap_writepage(struct folio *folio, struct swap_iocb **swap_plug) -{ - struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); - - VM_BUG_ON_FOLIO(!folio_test_swapcache(folio), folio); - /* - * ->flags can be updated non-atomically, - * but that will never affect SWP_FS_OPS, so the data_race - * is safe. - */ - if (data_race(sis->flags & SWP_FS_OPS)) - swap_writepage_fs(folio, swap_plug); - /* - * ->flags can be updated non-atomically, - * but that will never affect SWP_SYNCHRONOUS_IO, so the data_race - * is safe. - */ - else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO)) - swap_writepage_bdev_sync(folio, sis); - else - swap_writepage_bdev_async(folio, sis); -} - void swap_write_unplug(struct swap_iocb *sio) { struct iov_iter from; @@ -537,9 +519,10 @@ static bool swap_read_folio_zeromap(struct folio *folio) return true; } -static void swap_read_folio_fs(struct folio *folio, struct swap_iocb **plug) +static void swap_read_folio_fs(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug) { - struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); struct swap_iocb *sio = NULL; loff_t pos = swap_dev_pos(folio->swap); @@ -571,8 +554,9 @@ static void swap_read_folio_fs(struct folio *folio, struct swap_iocb **plug) *plug = sio; } -static void swap_read_folio_bdev_sync(struct folio *folio, - struct swap_info_struct *sis) +static void swap_read_folio_bdev_sync(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug) { struct bio_vec bv; struct bio bio; @@ -593,8 +577,9 @@ static void swap_read_folio_bdev_sync(struct folio *folio, put_task_struct(current); } -static void swap_read_folio_bdev_async(struct folio *folio, - struct swap_info_struct *sis) +static void swap_read_folio_bdev_async(struct swap_info_struct *sis, + struct folio *folio, + struct swap_iocb **plug) { struct bio *bio; @@ -608,6 +593,39 @@ static void swap_read_folio_bdev_async(struct folio *folio, submit_bio(bio); } +static const struct swap_ops bdev_fs_swap_ops = { + .read_folio = swap_read_folio_fs, + .write_folio = swap_writepage_fs, +}; + +static const struct swap_ops bdev_sync_swap_ops = { + .read_folio = swap_read_folio_bdev_sync, + .write_folio = swap_writepage_bdev_sync, +}; + +static const struct swap_ops bdev_async_swap_ops = { + .read_folio = swap_read_folio_bdev_async, + .write_folio = swap_writepage_bdev_async, +}; + +void setup_swap_ops(struct swap_info_struct *sis) +{ + /* + * ->flags can be updated non-atomically, but that will + * never affect SWP_FS_OPS, so the data_race is safe. + */ + if (data_race(sis->flags & SWP_FS_OPS)) + sis->ops = &bdev_fs_swap_ops; + /* + * ->flags can be updated non-atomically, but that will + * never affect SWP_SYNCHRONOUS_IO, so the data_race is safe. + */ + else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO)) + sis->ops = &bdev_sync_swap_ops; + else + sis->ops = &bdev_async_swap_ops; +} + void swap_read_folio(struct folio *folio, struct swap_iocb **plug) { struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); @@ -642,13 +660,8 @@ void swap_read_folio(struct folio *folio, struct swap_iocb **plug) /* We have to read from slower devices. Increase zswap protection. */ zswap_folio_swapin(folio); - if (data_race(sis->flags & SWP_FS_OPS)) { - swap_read_folio_fs(folio, plug); - } else if (synchronous) { - swap_read_folio_bdev_sync(folio, sis); - } else { - swap_read_folio_bdev_async(folio, sis); - } + VM_WARN_ON_ONCE(!sis->ops || !sis->ops->read_folio); + sis->ops->read_folio(sis, folio, plug); finish: if (workingset) { diff --git a/mm/swapfile.c b/mm/swapfile.c index ff315b752afd..c9eb95141c8f 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -3732,6 +3732,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) si->list.prio = -si->prio; si->avail_list.prio = -si->prio; si->swap_file = swap_file; + setup_swap_ops(si); /* Sets SWP_WRITEOK, resurrect the percpu ref, expose the swap device */ enable_swap_info(si); diff --git a/mm/zswap.c b/mm/zswap.c index 4b5149173b0e..9bacb1733e1c 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -1054,7 +1054,8 @@ static int zswap_writeback_entry(struct zswap_entry *entry, folio_set_reclaim(folio); /* start writeback */ - __swap_writepage(folio, NULL); + VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); + si->ops->write_folio(si, folio, NULL); out: if (ret && ret != -EEXIST) { -- 2.39.3 (Apple Git-146) ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-28 7:58 ` [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods Barry Song @ 2026-03-29 10:49 ` kernel test robot 2026-03-29 11:44 ` Barry Song 2026-03-29 11:10 ` kernel test robot 2026-03-31 3:30 ` Chris Li 2 siblings, 1 reply; 13+ messages in thread From: kernel test robot @ 2026-03-29 10:49 UTC (permalink / raw) To: Barry Song, akpm, linux-mm Cc: llvm, oe-kbuild-all, bhe, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel Hi Barry, kernel test robot noticed the following build errors: [auto build test ERROR on akpm-mm/mm-everything] url: https://github.com/intel-lab-lkp/linux/commits/Barry-Song/mm-swap-rename-mm-page_io-c-to-mm-swap_io-c/20260328-170852 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/20260328075812.11060-3-21cnbao%40gmail.com patch subject: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods config: arm-randconfig-001-20260329 (https://download.01.org/0day-ci/archive/20260329/202603291844.TWh2Ellp-lkp@intel.com/config) compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 054e11d1a17e5ba88bb1a8ef32fad3346e80b186) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260329/202603291844.TWh2Ellp-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/202603291844.TWh2Ellp-lkp@intel.com/ All errors (new ones prefixed by >>): >> mm/zswap.c:1057:19: error: use of undeclared identifier 'sis'; did you mean 'si'? 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); | ^~~ | si include/linux/mmdebug.h:133:52: note: expanded from macro 'VM_WARN_ON_ONCE' 133 | #define VM_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond) | ^~~~ include/linux/build_bug.h:30:63: note: expanded from macro 'BUILD_BUG_ON_INVALID' 30 | #define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e)))) | ^ mm/zswap.c:995:27: note: 'si' declared here 995 | struct swap_info_struct *si; | ^ mm/zswap.c:1057:32: error: use of undeclared identifier 'sis'; did you mean 'si'? 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); | ^~~ | si include/linux/mmdebug.h:133:52: note: expanded from macro 'VM_WARN_ON_ONCE' 133 | #define VM_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond) | ^~~~ include/linux/build_bug.h:30:63: note: expanded from macro 'BUILD_BUG_ON_INVALID' 30 | #define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e)))) | ^ mm/zswap.c:995:27: note: 'si' declared here 995 | struct swap_info_struct *si; | ^ 2 errors generated. vim +1057 mm/zswap.c 971 972 /********************************* 973 * writeback code 974 **********************************/ 975 /* 976 * Attempts to free an entry by adding a folio to the swap cache, 977 * decompressing the entry data into the folio, and issuing a 978 * bio write to write the folio back to the swap device. 979 * 980 * This can be thought of as a "resumed writeback" of the folio 981 * to the swap device. We are basically resuming the same swap 982 * writeback path that was intercepted with the zswap_store() 983 * in the first place. After the folio has been decompressed into 984 * the swap cache, the compressed version stored by zswap can be 985 * freed. 986 */ 987 static int zswap_writeback_entry(struct zswap_entry *entry, 988 swp_entry_t swpentry) 989 { 990 struct xarray *tree; 991 pgoff_t offset = swp_offset(swpentry); 992 struct folio *folio; 993 struct mempolicy *mpol; 994 bool folio_was_allocated; 995 struct swap_info_struct *si; 996 int ret = 0; 997 998 /* try to allocate swap cache folio */ 999 si = get_swap_device(swpentry); 1000 if (!si) 1001 return -EEXIST; 1002 1003 mpol = get_task_policy(current); 1004 folio = swap_cache_alloc_folio(swpentry, GFP_KERNEL, mpol, 1005 NO_INTERLEAVE_INDEX, &folio_was_allocated); 1006 put_swap_device(si); 1007 if (!folio) 1008 return -ENOMEM; 1009 1010 /* 1011 * Found an existing folio, we raced with swapin or concurrent 1012 * shrinker. We generally writeback cold folios from zswap, and 1013 * swapin means the folio just became hot, so skip this folio. 1014 * For unlikely concurrent shrinker case, it will be unlinked 1015 * and freed when invalidated by the concurrent shrinker anyway. 1016 */ 1017 if (!folio_was_allocated) { 1018 ret = -EEXIST; 1019 goto out; 1020 } 1021 1022 /* 1023 * folio is locked, and the swapcache is now secured against 1024 * concurrent swapping to and from the slot, and concurrent 1025 * swapoff so we can safely dereference the zswap tree here. 1026 * Verify that the swap entry hasn't been invalidated and recycled 1027 * behind our backs, to avoid overwriting a new swap folio with 1028 * old compressed data. Only when this is successful can the entry 1029 * be dereferenced. 1030 */ 1031 tree = swap_zswap_tree(swpentry); 1032 if (entry != xa_load(tree, offset)) { 1033 ret = -ENOMEM; 1034 goto out; 1035 } 1036 1037 if (!zswap_decompress(entry, folio)) { 1038 ret = -EIO; 1039 goto out; 1040 } 1041 1042 xa_erase(tree, offset); 1043 1044 count_vm_event(ZSWPWB); 1045 if (entry->objcg) 1046 count_objcg_events(entry->objcg, ZSWPWB, 1); 1047 1048 zswap_entry_free(entry); 1049 1050 /* folio is up to date */ 1051 folio_mark_uptodate(folio); 1052 1053 /* move it to the tail of the inactive list after end_writeback */ 1054 folio_set_reclaim(folio); 1055 1056 /* start writeback */ > 1057 VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); 1058 si->ops->write_folio(si, folio, NULL); 1059 1060 out: 1061 if (ret && ret != -EEXIST) { 1062 swap_cache_del_folio(folio); 1063 folio_unlock(folio); 1064 } 1065 folio_put(folio); 1066 return ret; 1067 } 1068 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-29 10:49 ` kernel test robot @ 2026-03-29 11:44 ` Barry Song 0 siblings, 0 replies; 13+ messages in thread From: Barry Song @ 2026-03-29 11:44 UTC (permalink / raw) To: lkp Cc: 21cnbao, akpm, baohua, bhe, chrisl, kasong, linux-kernel, linux-mm, llvm, nphamcs, oe-kbuild-all, shikemeng, youngjun.park On Sun, Mar 29, 2026 at 6:49 PM kernel test robot <lkp@intel.com> wrote: > > Hi Barry, > > kernel test robot noticed the following build errors: > > [auto build test ERROR on akpm-mm/mm-everything] > > url: https://github.com/intel-lab-lkp/linux/commits/Barry-Song/mm-swap-rename-mm-page_io-c-to-mm-swap_io-c/20260328-170852 > base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything > patch link: https://lore.kernel.org/r/20260328075812.11060-3-21cnbao%40gmail.com > patch subject: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods > config: arm-randconfig-001-20260329 (https://download.01.org/0day-ci/archive/20260329/202603291844.TWh2Ellp-lkp@intel.com/config) > compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 054e11d1a17e5ba88bb1a8ef32fad3346e80b186) > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260329/202603291844.TWh2Ellp-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/202603291844.TWh2Ellp-lkp@intel.com/ > > All errors (new ones prefixed by >>): > > >> mm/zswap.c:1057:19: error: use of undeclared identifier 'sis'; did you mean 'si'? > 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); > | ^~~ > | si > include/linux/mmdebug.h:133:52: note: expanded from macro 'VM_WARN_ON_ONCE' > 133 | #define VM_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond) > | ^~~~ > include/linux/build_bug.h:30:63: note: expanded from macro 'BUILD_BUG_ON_INVALID' > 30 | #define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e)))) > | ^ > mm/zswap.c:995:27: note: 'si' declared here > 995 | struct swap_info_struct *si; > | ^ > mm/zswap.c:1057:32: error: use of undeclared identifier 'sis'; did you mean 'si'? > 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); > | ^~~ > | si Deeply sorry for the last-minute edit—I fat-fingered it. It should be si, not sis. My sincere apologies. diff --git a/mm/zswap.c b/mm/zswap.c index 9bacb1733e1c..b60821758169 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -1054,7 +1054,7 @@ static int zswap_writeback_entry(struct zswap_entry *entry, folio_set_reclaim(folio); /* start writeback */ - VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); + VM_WARN_ON_ONCE(!si->ops || !si->ops->write_folio); si->ops->write_folio(si, folio, NULL); out: -- Best Regards Barry ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-28 7:58 ` [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods Barry Song 2026-03-29 10:49 ` kernel test robot @ 2026-03-29 11:10 ` kernel test robot 2026-03-31 3:30 ` Chris Li 2 siblings, 0 replies; 13+ messages in thread From: kernel test robot @ 2026-03-29 11:10 UTC (permalink / raw) To: Barry Song, akpm, linux-mm Cc: oe-kbuild-all, bhe, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel Hi Barry, kernel test robot noticed the following build errors: [auto build test ERROR on akpm-mm/mm-everything] url: https://github.com/intel-lab-lkp/linux/commits/Barry-Song/mm-swap-rename-mm-page_io-c-to-mm-swap_io-c/20260328-170852 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/20260328075812.11060-3-21cnbao%40gmail.com patch subject: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods config: um-randconfig-r072-20260329 (https://download.01.org/0day-ci/archive/20260329/202603291919.Y8MwFsok-lkp@intel.com/config) compiler: gcc-14 (Debian 14.2.0-19) 14.2.0 smatch: v0.5.0-9004-gb810ac53 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260329/202603291919.Y8MwFsok-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/202603291919.Y8MwFsok-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from include/asm-generic/bug.h:7, from ./arch/um/include/generated/asm/bug.h:1, from arch/x86/include/asm/alternative.h:9, from arch/x86/um/asm/barrier.h:6, from include/linux/list.h:11, from include/linux/module.h:12, from mm/zswap.c:16: mm/zswap.c: In function 'zswap_writeback_entry': >> mm/zswap.c:1057:26: error: 'sis' undeclared (first use in this function); did you mean 'si'? 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); | ^~~ include/linux/once_lite.h:28:41: note: in definition of macro 'DO_ONCE_LITE_IF' 28 | bool __ret_do_once = !!(condition); \ | ^~~~~~~~~ include/linux/mmdebug.h:123:37: note: in expansion of macro 'WARN_ON_ONCE' 123 | #define VM_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond) | ^~~~~~~~~~~~ mm/zswap.c:1057:9: note: in expansion of macro 'VM_WARN_ON_ONCE' 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); | ^~~~~~~~~~~~~~~ mm/zswap.c:1057:26: note: each undeclared identifier is reported only once for each function it appears in 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); | ^~~ include/linux/once_lite.h:28:41: note: in definition of macro 'DO_ONCE_LITE_IF' 28 | bool __ret_do_once = !!(condition); \ | ^~~~~~~~~ include/linux/mmdebug.h:123:37: note: in expansion of macro 'WARN_ON_ONCE' 123 | #define VM_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond) | ^~~~~~~~~~~~ mm/zswap.c:1057:9: note: in expansion of macro 'VM_WARN_ON_ONCE' 1057 | VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); | ^~~~~~~~~~~~~~~ vim +1057 mm/zswap.c 971 972 /********************************* 973 * writeback code 974 **********************************/ 975 /* 976 * Attempts to free an entry by adding a folio to the swap cache, 977 * decompressing the entry data into the folio, and issuing a 978 * bio write to write the folio back to the swap device. 979 * 980 * This can be thought of as a "resumed writeback" of the folio 981 * to the swap device. We are basically resuming the same swap 982 * writeback path that was intercepted with the zswap_store() 983 * in the first place. After the folio has been decompressed into 984 * the swap cache, the compressed version stored by zswap can be 985 * freed. 986 */ 987 static int zswap_writeback_entry(struct zswap_entry *entry, 988 swp_entry_t swpentry) 989 { 990 struct xarray *tree; 991 pgoff_t offset = swp_offset(swpentry); 992 struct folio *folio; 993 struct mempolicy *mpol; 994 bool folio_was_allocated; 995 struct swap_info_struct *si; 996 int ret = 0; 997 998 /* try to allocate swap cache folio */ 999 si = get_swap_device(swpentry); 1000 if (!si) 1001 return -EEXIST; 1002 1003 mpol = get_task_policy(current); 1004 folio = swap_cache_alloc_folio(swpentry, GFP_KERNEL, mpol, 1005 NO_INTERLEAVE_INDEX, &folio_was_allocated); 1006 put_swap_device(si); 1007 if (!folio) 1008 return -ENOMEM; 1009 1010 /* 1011 * Found an existing folio, we raced with swapin or concurrent 1012 * shrinker. We generally writeback cold folios from zswap, and 1013 * swapin means the folio just became hot, so skip this folio. 1014 * For unlikely concurrent shrinker case, it will be unlinked 1015 * and freed when invalidated by the concurrent shrinker anyway. 1016 */ 1017 if (!folio_was_allocated) { 1018 ret = -EEXIST; 1019 goto out; 1020 } 1021 1022 /* 1023 * folio is locked, and the swapcache is now secured against 1024 * concurrent swapping to and from the slot, and concurrent 1025 * swapoff so we can safely dereference the zswap tree here. 1026 * Verify that the swap entry hasn't been invalidated and recycled 1027 * behind our backs, to avoid overwriting a new swap folio with 1028 * old compressed data. Only when this is successful can the entry 1029 * be dereferenced. 1030 */ 1031 tree = swap_zswap_tree(swpentry); 1032 if (entry != xa_load(tree, offset)) { 1033 ret = -ENOMEM; 1034 goto out; 1035 } 1036 1037 if (!zswap_decompress(entry, folio)) { 1038 ret = -EIO; 1039 goto out; 1040 } 1041 1042 xa_erase(tree, offset); 1043 1044 count_vm_event(ZSWPWB); 1045 if (entry->objcg) 1046 count_objcg_events(entry->objcg, ZSWPWB, 1); 1047 1048 zswap_entry_free(entry); 1049 1050 /* folio is up to date */ 1051 folio_mark_uptodate(folio); 1052 1053 /* move it to the tail of the inactive list after end_writeback */ 1054 folio_set_reclaim(folio); 1055 1056 /* start writeback */ > 1057 VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); 1058 si->ops->write_folio(si, folio, NULL); 1059 1060 out: 1061 if (ret && ret != -EEXIST) { 1062 swap_cache_del_folio(folio); 1063 folio_unlock(folio); 1064 } 1065 folio_put(folio); 1066 return ret; 1067 } 1068 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-28 7:58 ` [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods Barry Song 2026-03-29 10:49 ` kernel test robot 2026-03-29 11:10 ` kernel test robot @ 2026-03-31 3:30 ` Chris Li 2026-03-31 9:21 ` Barry Song 2 siblings, 1 reply; 13+ messages in thread From: Chris Li @ 2026-03-31 3:30 UTC (permalink / raw) To: Barry Song Cc: akpm, linux-mm, bhe, baohua, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel On Sat, Mar 28, 2026 at 12:58 AM Barry Song <21cnbao@gmail.com> wrote: > > From: Baoquan He <bhe@redhat.com> > > This simplifies codes and makes logic clearer. And also makes later any > new swap device type being added easier to handle. > > Currently there are three types of swap devices: bdev_fs, bdev_sync > and bdev_async, and only operations read_folio and write_folio are > included. In the future, there could be more swap device types added > and more appropriate opeations adapted into swap_ops. Should add that there is no functional change expected from this patch. > Suggested-by: Chris Li <chrisl@kernel.org> > Signed-off-by: Baoquan He <bhe@redhat.com> > Co-developed-by: Barry Song <baohua@kernel.org> > Signed-off-by: Barry Song <baohua@kernel.org> Have some nitpicks follows. > --- > include/linux/swap.h | 2 + > mm/swap.h | 10 ++++- > mm/swap_io.c | 99 +++++++++++++++++++++++++------------------- > mm/swapfile.c | 1 + > mm/zswap.c | 3 +- > 5 files changed, 70 insertions(+), 45 deletions(-) > > diff --git a/include/linux/swap.h b/include/linux/swap.h > index 1930f81e6be4..b52f30dad72b 100644 > --- a/include/linux/swap.h > +++ b/include/linux/swap.h > @@ -243,6 +243,7 @@ struct swap_sequential_cluster { > unsigned int next[SWAP_NR_ORDERS]; /* Likely next allocation offset */ > }; > > +struct swap_ops; > /* > * The in-memory structure used to track swap areas. > */ > @@ -283,6 +284,7 @@ struct swap_info_struct { > 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 */ > + const struct swap_ops *ops; > }; > > static inline swp_entry_t page_swap_entry(struct page *page) > diff --git a/mm/swap.h b/mm/swap.h > index 161185057993..219dbcb3ffb1 100644 > --- a/mm/swap.h > +++ b/mm/swap.h > @@ -217,6 +217,15 @@ extern void __swap_cluster_free_entries(struct swap_info_struct *si, > /* linux/mm/swap_io.c */ > int sio_pool_init(void); > struct swap_iocb; > +struct swap_ops { > + void (*read_folio)(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug); > + void (*write_folio)(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug); > +}; > +void setup_swap_ops(struct swap_info_struct *sis); > void swap_read_folio(struct folio *folio, struct swap_iocb **plug); > void __swap_read_unplug(struct swap_iocb *plug); > static inline void swap_read_unplug(struct swap_iocb *plug) > @@ -226,7 +235,6 @@ static inline void swap_read_unplug(struct swap_iocb *plug) > } > void swap_write_unplug(struct swap_iocb *sio); > int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug); > -void __swap_writepage(struct folio *folio, struct swap_iocb **swap_plug); > > /* linux/mm/swap_state.c */ > extern struct address_space swap_space __read_mostly; > diff --git a/mm/swap_io.c b/mm/swap_io.c > index 91b33d955e63..ad0895af6ed8 100644 > --- a/mm/swap_io.c > +++ b/mm/swap_io.c > @@ -238,6 +238,7 @@ static void swap_zeromap_folio_clear(struct folio *folio) > int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug) > { > int ret = 0; > + struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); > > if (folio_free_swap(folio)) > goto out_unlock; > @@ -283,7 +284,8 @@ int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug) > } > rcu_read_unlock(); > > - __swap_writepage(folio, swap_plug); > + VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); > + sis->ops->write_folio(sis, folio, swap_plug); > return 0; > out_unlock: > folio_unlock(folio); > @@ -373,10 +375,11 @@ static void sio_write_complete(struct kiocb *iocb, long ret) > mempool_free(sio, sio_pool); > } > > -static void swap_writepage_fs(struct folio *folio, struct swap_iocb **swap_plug) > +static void swap_writepage_fs(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **swap_plug) > { > struct swap_iocb *sio = swap_plug ? *swap_plug : NULL; > - struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); > struct file *swap_file = sis->swap_file; > loff_t pos = swap_dev_pos(folio->swap); > > @@ -409,8 +412,9 @@ static void swap_writepage_fs(struct folio *folio, struct swap_iocb **swap_plug) > *swap_plug = sio; > } > > -static void swap_writepage_bdev_sync(struct folio *folio, > - struct swap_info_struct *sis) > +static void swap_writepage_bdev_sync(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug) > { > struct bio_vec bv; > struct bio bio; > @@ -429,8 +433,9 @@ static void swap_writepage_bdev_sync(struct folio *folio, > __end_swap_bio_write(&bio); > } > > -static void swap_writepage_bdev_async(struct folio *folio, > - struct swap_info_struct *sis) > +static void swap_writepage_bdev_async(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug) > { > struct bio *bio; > > @@ -446,29 +451,6 @@ static void swap_writepage_bdev_async(struct folio *folio, > submit_bio(bio); > } > > -void __swap_writepage(struct folio *folio, struct swap_iocb **swap_plug) > -{ > - struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); > - > - VM_BUG_ON_FOLIO(!folio_test_swapcache(folio), folio); > - /* > - * ->flags can be updated non-atomically, > - * but that will never affect SWP_FS_OPS, so the data_race > - * is safe. > - */ > - if (data_race(sis->flags & SWP_FS_OPS)) > - swap_writepage_fs(folio, swap_plug); > - /* > - * ->flags can be updated non-atomically, > - * but that will never affect SWP_SYNCHRONOUS_IO, so the data_race > - * is safe. > - */ > - else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO)) > - swap_writepage_bdev_sync(folio, sis); > - else > - swap_writepage_bdev_async(folio, sis); > -} > - > void swap_write_unplug(struct swap_iocb *sio) > { > struct iov_iter from; > @@ -537,9 +519,10 @@ static bool swap_read_folio_zeromap(struct folio *folio) > return true; > } > > -static void swap_read_folio_fs(struct folio *folio, struct swap_iocb **plug) > +static void swap_read_folio_fs(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug) > { > - struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); > struct swap_iocb *sio = NULL; > loff_t pos = swap_dev_pos(folio->swap); > > @@ -571,8 +554,9 @@ static void swap_read_folio_fs(struct folio *folio, struct swap_iocb **plug) > *plug = sio; > } > > -static void swap_read_folio_bdev_sync(struct folio *folio, > - struct swap_info_struct *sis) > +static void swap_read_folio_bdev_sync(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug) > { > struct bio_vec bv; > struct bio bio; > @@ -593,8 +577,9 @@ static void swap_read_folio_bdev_sync(struct folio *folio, > put_task_struct(current); > } > > -static void swap_read_folio_bdev_async(struct folio *folio, > - struct swap_info_struct *sis) > +static void swap_read_folio_bdev_async(struct swap_info_struct *sis, > + struct folio *folio, > + struct swap_iocb **plug) > { > struct bio *bio; > > @@ -608,6 +593,39 @@ static void swap_read_folio_bdev_async(struct folio *folio, > submit_bio(bio); > } > > +static const struct swap_ops bdev_fs_swap_ops = { > + .read_folio = swap_read_folio_fs, > + .write_folio = swap_writepage_fs, > +}; > + > +static const struct swap_ops bdev_sync_swap_ops = { > + .read_folio = swap_read_folio_bdev_sync, > + .write_folio = swap_writepage_bdev_sync, > +}; > + > +static const struct swap_ops bdev_async_swap_ops = { > + .read_folio = swap_read_folio_bdev_async, > + .write_folio = swap_writepage_bdev_async, > +}; > + > +void setup_swap_ops(struct swap_info_struct *sis) setup_swap_ops()` needs to return an indication of an error. The error is that sis->ops is NULL or op->read_folio == NULL or op->write_folio == NULL. If there is an error, we should fail the swapon. See my other comments regardin g the error checking at the dereference side. > +{ > + /* > + * ->flags can be updated non-atomically, but that will > + * never affect SWP_FS_OPS, so the data_race is safe. > + */ > + if (data_race(sis->flags & SWP_FS_OPS)) > + sis->ops = &bdev_fs_swap_ops; > + /* > + * ->flags can be updated non-atomically, but that will > + * never affect SWP_SYNCHRONOUS_IO, so the data_race is safe. > + */ > + else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO)) > + sis->ops = &bdev_sync_swap_ops; > + else > + sis->ops = &bdev_async_swap_ops; > +} > + > void swap_read_folio(struct folio *folio, struct swap_iocb **plug) > { > struct swap_info_struct *sis = __swap_entry_to_info(folio->swap); > @@ -642,13 +660,8 @@ void swap_read_folio(struct folio *folio, struct swap_iocb **plug) > /* We have to read from slower devices. Increase zswap protection. */ > zswap_folio_swapin(folio); > > - if (data_race(sis->flags & SWP_FS_OPS)) { > - swap_read_folio_fs(folio, plug); > - } else if (synchronous) { > - swap_read_folio_bdev_sync(folio, sis); > - } else { > - swap_read_folio_bdev_async(folio, sis); > - } > + VM_WARN_ON_ONCE(!sis->ops || !sis->ops->read_folio); WARN_ON_ONCE is not enough. If we hit a WARN here, the kernel will crash on the next dereference of ops->read_folios(). In other words, we will get kernel OOPS immediately after the warning. This makes no make sense. We should refuse to swapon at setup_swap_ops() above. Then no checking here is needed. > + sis->ops->read_folio(sis, folio, plug); > > finish: > if (workingset) { > diff --git a/mm/swapfile.c b/mm/swapfile.c > index ff315b752afd..c9eb95141c8f 100644 > --- a/mm/swapfile.c > +++ b/mm/swapfile.c > @@ -3732,6 +3732,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) > si->list.prio = -si->prio; > si->avail_list.prio = -si->prio; > si->swap_file = swap_file; > + setup_swap_ops(si); > > /* Sets SWP_WRITEOK, resurrect the percpu ref, expose the swap device */ > enable_swap_info(si); > diff --git a/mm/zswap.c b/mm/zswap.c > index 4b5149173b0e..9bacb1733e1c 100644 > --- a/mm/zswap.c > +++ b/mm/zswap.c > @@ -1054,7 +1054,8 @@ static int zswap_writeback_entry(struct zswap_entry *entry, > folio_set_reclaim(folio); > > /* start writeback */ > - __swap_writepage(folio, NULL); > + VM_WARN_ON_ONCE(!sis->ops || !sis->ops->write_folio); Again, WARN_ON is not enough, the kernel will panic here if a warning is triggered. Check at setup_swap_ops() and refuse to swapon if ops->write_folio is NULL. With the other "sis" fix, the patch looks good otherwise. Chris > + si->ops->write_folio(si, folio, NULL); > > out: > if (ret && ret != -EEXIST) { > -- > 2.39.3 (Apple Git-146) > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-31 3:30 ` Chris Li @ 2026-03-31 9:21 ` Barry Song 2026-03-31 16:10 ` Chris Li 0 siblings, 1 reply; 13+ messages in thread From: Barry Song @ 2026-03-31 9:21 UTC (permalink / raw) To: Chris Li Cc: akpm, linux-mm, bhe, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel On Tue, Mar 31, 2026 at 4:31 PM Chris Li <chrisl@kernel.org> wrote: > > On Sat, Mar 28, 2026 at 12:58 AM Barry Song <21cnbao@gmail.com> wrote: > > > > From: Baoquan He <bhe@redhat.com> > > > > This simplifies codes and makes logic clearer. And also makes later any > > new swap device type being added easier to handle. > > > > Currently there are three types of swap devices: bdev_fs, bdev_sync > > and bdev_async, and only operations read_folio and write_folio are > > included. In the future, there could be more swap device types added > > and more appropriate opeations adapted into swap_ops. > > Should add that there is no functional change expected from this patch. Sounds good to me. [...] > > +static const struct swap_ops bdev_async_swap_ops = { > > + .read_folio = swap_read_folio_bdev_async, > > + .write_folio = swap_writepage_bdev_async, > > +}; > > + > > +void setup_swap_ops(struct swap_info_struct *sis) > > setup_swap_ops()` needs to return an indication of an error. > The error is that sis->ops is NULL or op->read_folio == NULL or > op->write_folio == NULL. > If there is an error, we should fail the swapon. Right now there is no possibility for any of the ops (read_folio or write_folio) to be NULL, so I was using VM_WARN_ON as an assertion to catch bugs in kernel code. That said, I agree we can return an error earlier instead of letting swapon fail later. I think it may still make sense to keep a VM_WARN_ON in setup_swap_ops() before returning -EINVAL or a similar error? Thanks Barry ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods 2026-03-31 9:21 ` Barry Song @ 2026-03-31 16:10 ` Chris Li 0 siblings, 0 replies; 13+ messages in thread From: Chris Li @ 2026-03-31 16:10 UTC (permalink / raw) To: Barry Song Cc: akpm, linux-mm, bhe, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel On Tue, Mar 31, 2026 at 2:22 AM Barry Song <baohua@kernel.org> wrote: > > On Tue, Mar 31, 2026 at 4:31 PM Chris Li <chrisl@kernel.org> wrote: > > > > On Sat, Mar 28, 2026 at 12:58 AM Barry Song <21cnbao@gmail.com> wrote: > > > > > > From: Baoquan He <bhe@redhat.com> > > > > > > This simplifies codes and makes logic clearer. And also makes later any > > > new swap device type being added easier to handle. > > > > > > Currently there are three types of swap devices: bdev_fs, bdev_sync > > > and bdev_async, and only operations read_folio and write_folio are > > > included. In the future, there could be more swap device types added > > > and more appropriate opeations adapted into swap_ops. > > > > Should add that there is no functional change expected from this patch. > > Sounds good to me. Ack > > > > +static const struct swap_ops bdev_async_swap_ops = { > > > + .read_folio = swap_read_folio_bdev_async, > > > + .write_folio = swap_writepage_bdev_async, > > > +}; > > > + > > > +void setup_swap_ops(struct swap_info_struct *sis) > > > > setup_swap_ops()` needs to return an indication of an error. > > The error is that sis->ops is NULL or op->read_folio == NULL or > > op->write_folio == NULL. > > If there is an error, we should fail the swapon. > > Right now there is no possibility for any of the ops (read_folio or > write_folio) to be NULL, so I was using VM_WARN_ON as an assertion > to catch bugs in kernel code. Ack. Someone might register a new swap_ops later that introduces a NULL swap_write_folio. The check is for catching that. > > That said, I agree we can return an error earlier instead of letting > swapon fail later. > > I think it may still make sense to keep a VM_WARN_ON in > setup_swap_ops() before returning -EINVAL or a similar error? Sure. We can just print pr_err() rather than VM_WARN_ON. VM_WARN_ON is nop when VM debug is disabled. It is a kernel swap code bug on the swapon path, so the back trace portion of the warning is not very valuable. A normal error print will suffice. Because the swapon failed, the user will notice this error. Chris ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 3/3] mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* 2026-03-28 7:58 [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Barry Song 2026-03-28 7:58 ` [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c Barry Song 2026-03-28 7:58 ` [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods Barry Song @ 2026-03-28 7:58 ` Barry Song 2026-03-29 14:31 ` Chris Li 2026-03-30 0:54 ` [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Baoquan He 3 siblings, 1 reply; 13+ messages in thread From: Barry Song @ 2026-03-28 7:58 UTC (permalink / raw) To: akpm, linux-mm Cc: bhe, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel From: Baoquan He <bhe@redhat.com> All these swap_writepage_* functions are hanlding passed in folio, but not page. And this renaming make them consistent with the their counterpart swap_read_folio_* functions. Reviewed-by: Barry Song <baohua@kernel.org> Reviewed-by: Nhat Pham <nphamcs@gmail.com> Signed-off-by: Baoquan He <bhe@redhat.com> Signed-off-by: Barry Song <baohua@kernel.org> --- mm/swap_io.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mm/swap_io.c b/mm/swap_io.c index ad0895af6ed8..063cd005ca0d 100644 --- a/mm/swap_io.c +++ b/mm/swap_io.c @@ -375,7 +375,7 @@ static void sio_write_complete(struct kiocb *iocb, long ret) mempool_free(sio, sio_pool); } -static void swap_writepage_fs(struct swap_info_struct *sis, +static void swap_write_folio_fs(struct swap_info_struct *sis, struct folio *folio, struct swap_iocb **swap_plug) { @@ -412,7 +412,7 @@ static void swap_writepage_fs(struct swap_info_struct *sis, *swap_plug = sio; } -static void swap_writepage_bdev_sync(struct swap_info_struct *sis, +static void swap_write_folio_bdev_sync(struct swap_info_struct *sis, struct folio *folio, struct swap_iocb **plug) { @@ -433,7 +433,7 @@ static void swap_writepage_bdev_sync(struct swap_info_struct *sis, __end_swap_bio_write(&bio); } -static void swap_writepage_bdev_async(struct swap_info_struct *sis, +static void swap_write_folio_bdev_async(struct swap_info_struct *sis, struct folio *folio, struct swap_iocb **plug) { @@ -595,17 +595,17 @@ static void swap_read_folio_bdev_async(struct swap_info_struct *sis, static const struct swap_ops bdev_fs_swap_ops = { .read_folio = swap_read_folio_fs, - .write_folio = swap_writepage_fs, + .write_folio = swap_write_folio_fs, }; static const struct swap_ops bdev_sync_swap_ops = { .read_folio = swap_read_folio_bdev_sync, - .write_folio = swap_writepage_bdev_sync, + .write_folio = swap_write_folio_bdev_sync, }; static const struct swap_ops bdev_async_swap_ops = { .read_folio = swap_read_folio_bdev_async, - .write_folio = swap_writepage_bdev_async, + .write_folio = swap_write_folio_bdev_async, }; void setup_swap_ops(struct swap_info_struct *sis) -- 2.39.3 (Apple Git-146) ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 3/3] mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* 2026-03-28 7:58 ` [PATCH v2 3/3] mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* Barry Song @ 2026-03-29 14:31 ` Chris Li 0 siblings, 0 replies; 13+ messages in thread From: Chris Li @ 2026-03-29 14:31 UTC (permalink / raw) To: Barry Song Cc: akpm, linux-mm, bhe, baohua, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel Acked-by: Chris Li <chrisl@kernel.org> Chris On Sat, Mar 28, 2026 at 12:58 AM Barry Song <21cnbao@gmail.com> wrote: > > From: Baoquan He <bhe@redhat.com> > > All these swap_writepage_* functions are hanlding passed in folio, but > not page. And this renaming make them consistent with the their > counterpart swap_read_folio_* functions. > > Reviewed-by: Barry Song <baohua@kernel.org> > Reviewed-by: Nhat Pham <nphamcs@gmail.com> > Signed-off-by: Baoquan He <bhe@redhat.com> > Signed-off-by: Barry Song <baohua@kernel.org> > --- > mm/swap_io.c | 12 ++++++------ > 1 file changed, 6 insertions(+), 6 deletions(-) > > diff --git a/mm/swap_io.c b/mm/swap_io.c > index ad0895af6ed8..063cd005ca0d 100644 > --- a/mm/swap_io.c > +++ b/mm/swap_io.c > @@ -375,7 +375,7 @@ static void sio_write_complete(struct kiocb *iocb, long ret) > mempool_free(sio, sio_pool); > } > > -static void swap_writepage_fs(struct swap_info_struct *sis, > +static void swap_write_folio_fs(struct swap_info_struct *sis, > struct folio *folio, > struct swap_iocb **swap_plug) > { > @@ -412,7 +412,7 @@ static void swap_writepage_fs(struct swap_info_struct *sis, > *swap_plug = sio; > } > > -static void swap_writepage_bdev_sync(struct swap_info_struct *sis, > +static void swap_write_folio_bdev_sync(struct swap_info_struct *sis, > struct folio *folio, > struct swap_iocb **plug) > { > @@ -433,7 +433,7 @@ static void swap_writepage_bdev_sync(struct swap_info_struct *sis, > __end_swap_bio_write(&bio); > } > > -static void swap_writepage_bdev_async(struct swap_info_struct *sis, > +static void swap_write_folio_bdev_async(struct swap_info_struct *sis, > struct folio *folio, > struct swap_iocb **plug) > { > @@ -595,17 +595,17 @@ static void swap_read_folio_bdev_async(struct swap_info_struct *sis, > > static const struct swap_ops bdev_fs_swap_ops = { > .read_folio = swap_read_folio_fs, > - .write_folio = swap_writepage_fs, > + .write_folio = swap_write_folio_fs, > }; > > static const struct swap_ops bdev_sync_swap_ops = { > .read_folio = swap_read_folio_bdev_sync, > - .write_folio = swap_writepage_bdev_sync, > + .write_folio = swap_write_folio_bdev_sync, > }; > > static const struct swap_ops bdev_async_swap_ops = { > .read_folio = swap_read_folio_bdev_async, > - .write_folio = swap_writepage_bdev_async, > + .write_folio = swap_write_folio_bdev_async, > }; > > void setup_swap_ops(struct swap_info_struct *sis) > -- > 2.39.3 (Apple Git-146) > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods 2026-03-28 7:58 [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Barry Song ` (2 preceding siblings ...) 2026-03-28 7:58 ` [PATCH v2 3/3] mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* Barry Song @ 2026-03-30 0:54 ` Baoquan He 3 siblings, 0 replies; 13+ messages in thread From: Baoquan He @ 2026-03-30 0:54 UTC (permalink / raw) To: Barry Song Cc: akpm, linux-mm, baohua, chrisl, kasong, nphamcs, shikemeng, youngjun.park, linux-kernel On 03/28/26 at 03:58pm, Barry Song wrote: > From: Barry Song <baohua@kernel.org> > > -v2: > * lots of cleanup for patch 2/3: renaming, moving data > structures, and using const properly > * collected tags from Kairui, Nhat and Barry Thanks a lot for taking care of this, Barry. I took several days off for family reason. Sorry for the inconvenience caused by my leave. > > -v1: > https://lore.kernel.org/linux-mm/20260302104016.163542-1-bhe@redhat.com/ > > This can simplify the code logic and benefit any new type of swap device > added later. > > And also do renaming in this patchset: > ------- > file renaming: > --- > mm/page_io.c to mm/swap_io.c > > function renaming: > --- > swap_writepage_* to swap_write_folio_* in file mm/swap_io.c > > Baoquan He (3): > mm/swap: rename mm/page_io.c to mm/swap_io.c > mm/swap: use swap_ops to register swap device's methods > mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* > > MAINTAINERS | 2 +- > include/linux/swap.h | 2 + > mm/Makefile | 2 +- > mm/swap.h | 12 ++++- > mm/{page_io.c => swap_io.c} | 101 ++++++++++++++++++++---------------- > mm/swapfile.c | 1 + > mm/zswap.c | 3 +- > 7 files changed, 73 insertions(+), 50 deletions(-) > rename mm/{page_io.c => swap_io.c} (89%) > > -- > 2.39.3 (Apple Git-146) > ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-03-31 16:10 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-28 7:58 [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Barry Song 2026-03-28 7:58 ` [PATCH v2 1/3] mm/swap: rename mm/page_io.c to mm/swap_io.c Barry Song 2026-03-29 14:31 ` Chris Li 2026-03-28 7:58 ` [PATCH v2 2/3] mm/swap: use swap_ops to register swap device's methods Barry Song 2026-03-29 10:49 ` kernel test robot 2026-03-29 11:44 ` Barry Song 2026-03-29 11:10 ` kernel test robot 2026-03-31 3:30 ` Chris Li 2026-03-31 9:21 ` Barry Song 2026-03-31 16:10 ` Chris Li 2026-03-28 7:58 ` [PATCH v2 3/3] mm/swap_io.c: rename swap_writepage_* to swap_write_folio_* Barry Song 2026-03-29 14:31 ` Chris Li 2026-03-30 0:54 ` [PATCH v2 0/3] mm/swap: use swap_ops to register swap device's methods Baoquan He
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox