mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
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>
This commit is contained in:
parent
563597895e
commit
0df74c1158
|
|
@ -355,13 +355,14 @@ should perform any validation and preparation necessary to ensure that
|
|||
writes can be performed with minimal memory allocation. It should call
|
||||
add_swap_extent(), or the helper iomap_swapfile_activate(), and return
|
||||
the number of extents added. If IO should be submitted through
|
||||
->swap_rw(), it should set SWP_FS_OPS, otherwise IO will be submitted
|
||||
->swap_rw(), it should call swap_fs_activate, otherwise IO will be submitted
|
||||
directly to the block device ``sis->bdev``.
|
||||
|
||||
->swap_deactivate() will be called in the sys_swapoff()
|
||||
path after ->swap_activate() returned success.
|
||||
|
||||
->swap_rw will be called for swap IO if SWP_FS_OPS was set by ->swap_activate().
|
||||
->swap_rw will be called for swap IO if swap_fs_activate was called by
|
||||
->swap_activate().
|
||||
|
||||
file_lock_operations
|
||||
====================
|
||||
|
|
|
|||
|
|
@ -977,7 +977,7 @@ cache in your filesystem. The following members are defined:
|
|||
can be performed with minimal memory allocation. It should call
|
||||
add_swap_extent(), or the helper iomap_swapfile_activate(), and
|
||||
return the number of extents added. If IO should be submitted
|
||||
through ->swap_rw(), it should set SWP_FS_OPS, otherwise IO will
|
||||
through ->swap_rw(), it should call swap_fs_activate, otherwise IO will
|
||||
be submitted directly to the block device ``sis->bdev``.
|
||||
|
||||
``swap_deactivate``
|
||||
|
|
@ -985,7 +985,7 @@ cache in your filesystem. The following members are defined:
|
|||
successful.
|
||||
|
||||
``swap_rw``
|
||||
Called to read or write swap pages when SWP_FS_OPS is set.
|
||||
Called to read or write swap pages when swap_fs_activate was called.
|
||||
|
||||
The File Object
|
||||
===============
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
|||
ret = rpc_clnt_swap_activate(clnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = add_swap_extent(sis, 0, sis->max, 0);
|
||||
ret = swap_fs_activate(sis);
|
||||
if (ret < 0) {
|
||||
rpc_clnt_swap_deactivate(clnt);
|
||||
return ret;
|
||||
|
|
@ -607,8 +607,6 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
|||
|
||||
if (cl->rpc_ops->enable_swap)
|
||||
cl->rpc_ops->enable_swap(inode);
|
||||
|
||||
sis->flags |= SWP_FS_OPS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3451,9 +3451,7 @@ static int cifs_swap_activate(struct swap_info_struct *sis,
|
|||
* but we could add call to grab a byte range lock to prevent others
|
||||
* from reading or writing the file
|
||||
*/
|
||||
|
||||
sis->flags |= SWP_FS_OPS;
|
||||
return add_swap_extent(sis, 0, sis->max, 0);
|
||||
return swap_fs_activate(sis);
|
||||
}
|
||||
|
||||
static void cifs_swap_deactivate(struct file *file)
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@ enum {
|
|||
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 */
|
||||
|
|
@ -343,6 +342,7 @@ extern void __meminit kswapd_stop(int nid);
|
|||
|
||||
#ifdef CONFIG_SWAP
|
||||
|
||||
int swap_fs_activate(struct swap_info_struct *sis);
|
||||
int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
|
||||
unsigned long nr_pages, sector_t start_block);
|
||||
int generic_swapfile_activate(struct swap_info_struct *, struct file *,
|
||||
|
|
@ -468,6 +468,10 @@ static inline bool folio_free_swap(struct folio *folio)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int swap_fs_activate(struct swap_info_struct *sis)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int add_swap_extent(struct swap_info_struct *sis,
|
||||
unsigned long start_page,
|
||||
unsigned long nr_pages, sector_t start_block)
|
||||
|
|
|
|||
10
mm/page_io.c
10
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)
|
||||
|
|
|
|||
22
mm/swap.h
22
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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
15
mm/vmscan.c
15
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user