summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2026-07-13 11:33:43 +0200
committerAndrew Morton <akpm@linux-foundation.org>2026-08-20 18:24:38 -0700
commitebdf5ba19273aa109be8950b5256b19066b412ff (patch)
treeba203a5ffc83e65a35b962e318eaa3362f63480b /mm
parentdb74e94154cd2574f775daeae63c00d164c087a2 (diff)
downloadlinux-next-ebdf5ba19273aa109be8950b5256b19066b412ff.tar.gz
linux-next-ebdf5ba19273aa109be8950b5256b19066b412ff.zip
mm/swap: remove SWP_FS_OPS
Provide a swap_fs_activate helper that directly sets up swap_fs_ops, and a flag in struct swap_ops to indicate of NOFS swapping is allowed. Link: https://lore.kernel.org/20260713093350.2154226-7-hch@lst.de Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Baoquan He <baoquan.he@linux.dev> Cc: Barry Song <baohua@kernel.org> Cc: Chris Li <chrisl@kernel.org> Cc: Kairui Song <kasong@tencent.com> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Youngjun Park <youngjun.park@lge.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_io.c10
-rw-r--r--mm/swap.h22
-rw-r--r--mm/swapfile.c2
-rw-r--r--mm/vmscan.c15
4 files changed, 26 insertions, 23 deletions
diff --git a/mm/page_io.c b/mm/page_io.c
index c36b44ffe947..cea438b66bce 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -686,12 +686,20 @@ static bool swap_fs_can_merge(struct folio *folio, struct folio *prev_folio,
swap_dev_pos(prev_folio->swap) + prev_folio_size;
}
-const struct swap_ops swap_fs_ops = {
+static const struct swap_ops swap_fs_ops = {
+ .flags = SWAP_OPS_F_REQUIRE_NOFS,
.submit_write = swap_fs_submit_write,
.submit_read = swap_fs_submit_read,
.can_merge = swap_fs_can_merge,
};
+int swap_fs_activate(struct swap_info_struct *sis)
+{
+ sis->ops = &swap_fs_ops;
+ return add_swap_extent(sis, 0, sis->max, 0);
+}
+EXPORT_SYMBOL_GPL(swap_fs_activate);
+
void swap_write_submit(struct swap_io_ctx *ctx)
{
if (!ctx->sio)
diff --git a/mm/swap.h b/mm/swap.h
index ffc36695d4ac..1a78578fd067 100644
--- a/mm/swap.h
+++ b/mm/swap.h
@@ -96,7 +96,17 @@ struct swap_io_ctx {
struct swap_info_struct *sis;
};
+/*
+ * SWAP_OPS_F_REQUIRE_NOFS:
+ * When set, all reclaim operations must operated as GFS_NOFS and not
+ * just GFP_NOIO, as GFP_NOIO allocations could recourse into the
+ * file system backing this swap file.
+ */
+#define SWAP_OPS_F_REQUIRE_NOFS (1U << 0)
+
struct swap_ops {
+ unsigned int flags;
+
bool (*can_merge)(struct folio *folio, struct folio *prev_folio,
size_t prev_folio_size, int rw);
void (*submit_write)(struct swap_io_ctx *ctx);
@@ -347,11 +357,6 @@ struct folio *swapin_sync(swp_entry_t entry, gfp_t flag, unsigned long orders,
void swap_update_readahead(struct folio *folio, struct vm_area_struct *vma,
unsigned long addr);
-static inline unsigned int folio_swap_flags(struct folio *folio)
-{
- return __swap_entry_to_info(folio->swap)->flags;
-}
-
#else /* CONFIG_SWAP */
static inline struct swap_cluster_info *swap_cluster_lock(
struct swap_info_struct *si, pgoff_t offset, bool irq)
@@ -482,16 +487,9 @@ static inline void __swap_cache_replace_folio(struct swap_cluster_info *ci,
struct folio *old, struct folio *new)
{
}
-
-static inline unsigned int folio_swap_flags(struct folio *folio)
-{
- return 0;
-}
-
#endif /* CONFIG_SWAP */
extern const struct swap_ops swap_bdev_ops;
-extern const struct swap_ops swap_fs_ops;
int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
struct list_head *folio_list);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index ad623dae483b..dacef34a3ed7 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2975,8 +2975,6 @@ static int setup_swap_extents(struct swap_info_struct *sis,
ret = mapping->a_ops->swap_activate(sis, swap_file, span);
if (ret < 0)
return ret;
- if (sis->flags & SWP_FS_OPS)
- sis->ops = &swap_fs_ops;
sis->flags |= SWP_ACTIVATED;
return ret;
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 4742297693fe..3194da7dcc79 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1040,16 +1040,15 @@ static bool may_enter_fs(struct folio *folio, gfp_t gfp_mask)
{
if (gfp_mask & __GFP_FS)
return true;
- if (!folio_test_swapcache(folio) || !(gfp_mask & __GFP_IO))
- return false;
/*
- * We can "enter_fs" for swap-cache with only __GFP_IO
- * providing this isn't SWP_FS_OPS.
- * ->flags can be updated non-atomically,
- * but that will never affect SWP_FS_OPS, so the data_race
- * is safe.
+ * We can "enter_fs" for swap-cache with only __GFP_IO unless backed by
+ * a swapfile that requires GFP_NOFS I/O.
*/
- return !data_race(folio_swap_flags(folio) & SWP_FS_OPS);
+ if (folio_test_swapcache(folio) && (gfp_mask & __GFP_IO) &&
+ !(__swap_entry_to_info(folio->swap)->ops->flags &
+ SWAP_OPS_F_REQUIRE_NOFS))
+ return true;
+ return false;
}
/*