mm, swap: split locked entry duplicating into a standalone helper

No feature change, split the common logic into a stand alone helper to be
reused later.

Link: https://lkml.kernel.org/r/20251220-swap-table-p2-v5-11-8862a265a033@tencent.com
Signed-off-by: Kairui Song <kasong@tencent.com>
Reviewed-by: Baoquan He <bhe@redhat.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Chris Li <chrisl@kernel.org>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Rafael J. Wysocki (Intel) <rafael@kernel.org>
Cc: Yosry Ahmed <yosry.ahmed@linux.dev>
Cc: Deepanshu Kartikey <kartikey406@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kairui Song <ryncsn@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Kairui Song
2025-12-20 03:43:40 +08:00
committed by Andrew Morton
parent cda2504c51
commit 78d6a12dd9

View File

@@ -3667,26 +3667,14 @@ void si_swapinfo(struct sysinfo *val)
* - swap-cache reference is requested but the entry is not used. -> ENOENT
* - swap-mapped reference requested but needs continued swap count. -> ENOMEM
*/
static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
static int swap_dup_entries(struct swap_info_struct *si,
struct swap_cluster_info *ci,
unsigned long offset,
unsigned char usage, int nr)
{
struct swap_info_struct *si;
struct swap_cluster_info *ci;
unsigned long offset;
unsigned char count;
unsigned char has_cache;
int err, i;
int i;
unsigned char count, has_cache;
si = swap_entry_to_info(entry);
if (WARN_ON_ONCE(!si)) {
pr_err("%s%08lx\n", Bad_file, entry.val);
return -EINVAL;
}
offset = swp_offset(entry);
VM_WARN_ON(nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER);
ci = swap_cluster_lock(si, offset);
err = 0;
for (i = 0; i < nr; i++) {
count = si->swap_map[offset + i];
@@ -3694,25 +3682,20 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
* For swapin out, allocator never allocates bad slots. for
* swapin, readahead is guarded by swap_entry_swapped.
*/
if (WARN_ON(swap_count(count) == SWAP_MAP_BAD)) {
err = -ENOENT;
goto unlock_out;
}
if (WARN_ON(swap_count(count) == SWAP_MAP_BAD))
return -ENOENT;
has_cache = count & SWAP_HAS_CACHE;
count &= ~SWAP_HAS_CACHE;
if (!count && !has_cache) {
err = -ENOENT;
return -ENOENT;
} else if (usage == SWAP_HAS_CACHE) {
if (has_cache)
err = -EEXIST;
return -EEXIST;
} else if ((count & ~COUNT_CONTINUED) > SWAP_MAP_MAX) {
err = -EINVAL;
return -EINVAL;
}
if (err)
goto unlock_out;
}
for (i = 0; i < nr; i++) {
@@ -3731,14 +3714,31 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
* Don't need to rollback changes, because if
* usage == 1, there must be nr == 1.
*/
err = -ENOMEM;
goto unlock_out;
return -ENOMEM;
}
WRITE_ONCE(si->swap_map[offset + i], count | has_cache);
}
unlock_out:
return 0;
}
static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
{
int err;
struct swap_info_struct *si;
struct swap_cluster_info *ci;
unsigned long offset = swp_offset(entry);
si = swap_entry_to_info(entry);
if (WARN_ON_ONCE(!si)) {
pr_err("%s%08lx\n", Bad_file, entry.val);
return -EINVAL;
}
VM_WARN_ON(nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER);
ci = swap_cluster_lock(si, offset);
err = swap_dup_entries(si, ci, offset, usage, nr);
swap_cluster_unlock(ci);
return err;
}