Commit 78d6a12d authored by Kairui Song's avatar Kairui Song Committed by Andrew Morton
Browse files

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: default avatarKairui Song <kasong@tencent.com>
Reviewed-by: default avatarBaoquan 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: default avatarAndrew Morton <akpm@linux-foundation.org>
parent cda2504c
Loading
Loading
Loading
Loading
+31 −31
Original line number Diff line number Diff line
@@ -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;

	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);
	int i;
	unsigned char count, has_cache;

	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;
}