Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Jihan LIN <linjh22s@gmail.com>
To: kasong@tencent.com, linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>,
	Chris Li <chrisl@kernel.org>, Nhat Pham <nphamcs@gmail.com>,
	Baoquan He <baoquan.he@linux.dev>, Barry Song <baohua@kernel.org>,
	Youngjun Park <youngjun.park@lge.com>,
	Kemeng Shi <shikemeng@huaweicloud.com>
Subject: Re: [PATCH RFC 09/13] mm/swap: add priority queue for swap device allocation
Date: Wed, 15 Jul 2026 23:57:58 +0800	[thread overview]
Message-ID: <77d6da3d-10af-49a1-a356-72aa8b462e85@gmail.com> (raw)
In-Reply-To: <20260714-swap-pcp-priq-v1-9-de9b164ed419@tencent.com>

Hi Kairui,

Thanks for this series! I noticed a few issues in this patch:

[...]

>+static void swap_queue_install_readers(struct swap_queue_reader __percpu *readers)
>+{
>+	int ring_idx, cpu;
>+	struct swap_prio_ring *ring;
>+
>+	free_percpu(swap_queue_readers);
>+	swap_queue_readers = readers;
>+	if (!readers)
>+		return;
>+
>+	/* Distribute each CPU's swap IO fairly across devices. */
>+	for_each_possible_cpu(cpu) {
>+		local_lock_init(&per_cpu_ptr(readers, cpu)->lock);
>+
>+		for (ring_idx = 0; ring_idx < swap_queue_len; ring_idx++) {
>+			ring = swap_queue[ring_idx];
>+			per_cpu_ptr(readers, cpu)->ri[ring_idx].offset =
>+				    cpu % ring->size;
>+		}
>+	}
>+}
>+static struct swap_info_struct *swap_queue_get_device(long nr_alloc, int nr_iter)
>+{
>+	bool rotate = false;
>+	struct swap_info_struct *si;
>+	struct swap_ring_iterator *ri;
>+	struct swap_prio_ring *ring;
>+	unsigned int queue_idx;
>+
>+	if (!swap_queue_len)
>+		return ERR_PTR(-ENOENT);
>+
>+	queue_idx = 0;
>+	while (nr_iter >= swap_queue[queue_idx]->size) {
>+		nr_iter -= swap_queue[queue_idx]->size;
>+		if (++queue_idx >= swap_queue_len)
>+			return ERR_PTR(-ENOENT);
>+	}
>+
>+	ring = swap_queue[queue_idx];
>+	local_lock(&swap_queue_readers->lock);
>+	ri = this_cpu_ptr(&swap_queue_readers->ri[queue_idx]);
>+	/* Rotate while iterating the ring, just not on the first try */
>+	if (nr_iter)
>+		rotate = true;
>+	else if (ri->rr_counter < nr_alloc)
>+		rotate = true;
>+	else if (ri->offset >= ring->size)
>+		rotate = true;
>+	if (rotate) {
>+		ri->offset++;
>+		ri->offset %= ring->size;
>+		ri->rr_counter = SWAP_ROUND_ROBIN_QUOTA;
>+	}
>+	ri->rr_counter -= nr_alloc;

ri->rr_counter is left at 0 so the first allocation on each CPU hits
ri->rr_counter < nr_alloc and rotates, shifting offset away from
intended cpu % ring->size start. Initializing rr_counter to
SWAP_ROUND_ROBIN_QUOTA would avoid this, or is this initial rotation
perhaps intentional?

[...]

> @@ -1245,12 +1580,12 @@ static void add_to_avail_list(struct swap_info_struct *si)
> 	unsigned long pages;
> 
> 	spin_lock(&swap_avail_lock);
>+	spin_lock(&swap_queue_update_lock);
> 
> 	/*
>-	 * Add the device to the avail list if SWP_WRITEOK is set and
>-	 * SWAP_USAGE_OFFLIST_BIT is still set. Swapoff clears
>-	 * SWP_WRITEOK first, so the device won't be re-added after
>-	 * swapoff starts unless swap_device_enable resurrects it.
>+	 * Mark the device as avail if SWP_WRITEOK is set. Swapoff clears
>+	 * SWP_WRITEOK first, so check that first so the device won't be
>+	 * re-added after swapoff started.
> 	 */
> 	if (!(si->flags & SWP_WRITEOK))
> 		goto skip;
>@@ -1261,9 +1596,10 @@ static void add_to_avail_list(struct swap_info_struct *si)
> 	val = atomic_long_fetch_and_relaxed(~SWAP_USAGE_OFFLIST_BIT, &si->inuse_pages);
> 
> 	/*
>-	 * When device is full and device is on the plist, only one updater will
>-	 * see (inuse_pages == si->pages) and will call del_from_avail_list. If
>-	 * that updater happen to be here, just skip adding.
>+	 * When device is full and marked as available, one reader will see
>+	 * (inuse_pages == si->pages) and should mark it as unavailable and
>+	 * set SWAP_USAGE_OFFLIST_BIT. If that updater happens to be here, just
>+	 * skip the rest.
> 	 */
> 	pages = si->pages;
> 	if (val == pages) {
>@@ -1273,10 +1609,10 @@ static void add_to_avail_list(struct swap_info_struct *si)
> 			goto skip;
> 	}
> 
>+	swap_queue_unmask(si);
> 	plist_add(&si->avail_list, &swap_avail_head);
>-
> skip:
>-	spin_unlock(&swap_avail_lock);
>+	spin_unlock(&swap_queue_update_lock);
> }
swap_avail_lock is acquired but never released when add_to_avail_list()
returns.

[...]

>@@ -3700,6 +4035,12 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
>
> 	/* Sets SWP_WRITEOK, resurrect the percpu ref, expose the swap device */
> 	percpu_ref_resurrect(&si->users);
>+	percpu_down_write(&swapon_rwsem);
>+	error = swap_queue_add(si);
>+	percpu_up_write(&swapon_rwsem);
>+	if (error)
>+		goto free_swap_zswap;
>+
>	swap_device_enable(si);
The swapfile is inserted into the ring unmasked before SWP_WRITEOK was set in
swap_device_enable(). Allocators can pick it and get -EBUSY from
get_swap_device_info(). How about adding masked and then letting
swap_device_enable() unmask the new swapfile?

---
Thanks!
Jihan LIN


  parent reply	other threads:[~2026-07-15 15:58 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-13 17:25 [PATCH RFC 00/13] mm/swap: introduce priority queue to remove global cluster cache and plist Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 01/13] mm/swap: remove unused parameter for reading swap header Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 02/13] mm/swap: slightly cleanup the code for hibernation error handling Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 03/13] mm/swap: cleanup and document swap device availability flag usage Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 04/13] mm/swap: introduce swap device iteration helper Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 05/13] mm/swap: change the swapon lock into a percpu rwsem Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 06/13] mm/swap: remove swapon mutex and update proc reader Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 07/13] mm/swap: consolidate swap inuse accounting helpers Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 08/13] mm/swap: change back to use each swap device's percpu cluster Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 09/13] mm/swap: add priority queue for swap device allocation Kairui Song via B4 Relay
2026-07-14 18:09   ` Youngjun Park
2026-07-15 16:32     ` Kairui Song
2026-07-15 15:57   ` Jihan LIN [this message]
2026-07-15 16:38     ` Kairui Song
2026-07-13 17:25 ` [PATCH RFC 10/13] mm/swap: remove available list Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 11/13] mm/swap: perform sync discard on single device more proactively Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 12/13] mm/swap: drop swap active plist Kairui Song via B4 Relay
2026-07-13 17:25 ` [PATCH RFC 13/13] lib/plist.c: remove requeue function Kairui Song via B4 Relay

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=77d6da3d-10af-49a1-a356-72aa8b462e85@gmail.com \
    --to=linjh22s@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=baohua@kernel.org \
    --cc=baoquan.he@linux.dev \
    --cc=chrisl@kernel.org \
    --cc=kasong@tencent.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=nphamcs@gmail.com \
    --cc=shikemeng@huaweicloud.com \
    --cc=youngjun.park@lge.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox