From: Baoquan He <baoquan.he@linux.dev>
To: linux-mm@kvack.org
Cc: akpm@linux-foundation.org, david@kernel.org, chrisl@kernel.org,
kasong@tencent.com, nphamcs@gmail.com, baohua@kernel.org,
youngjun.park@lge.com, corbet@lwn.net, hannes@cmpxchg.org,
chengming.zhou@linux.dev, kunwu.chan@gmail.com,
klarasmodin@gmail.com, linux-kernel@vger.kernel.org,
Baoquan He <hebaoquan@kylinos.cn>
Subject: [PATCH v5 09/19] mm, swap: use a stable id for xswap devices
Date: Mon, 9 Nov 2026 13:54:45 +0800 [thread overview]
Message-ID: <20261109055455.536925-10-baoquan.he@linux.dev> (raw)
In-Reply-To: <20261109055455.536925-1-baoquan.he@linux.dev>
From: Baoquan He <hebaoquan@kylinos.cn>
Give each xswap device a 64-bit id from a counter. The id is never
reused. Show "xswap<id>" in /proc/swaps and use the same id in
debugfs. Destroy matches the id, so an old name fails with -ENODEV
instead of hitting a new device.
This avoids names based on the swap type, which can be reused after
swapoff. The swap type is still used inside the kernel and in dmesg.
Signed-off-by: Baoquan He <hebaoquan@kylinos.cn>
---
include/linux/swap.h | 1 +
mm/swapfile.c | 59 ++++++++++++++++++++++++++++++--------------
2 files changed, 42 insertions(+), 18 deletions(-)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 569989856c25..f4eb1912d1e6 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -244,6 +244,7 @@ struct swap_info_struct {
struct swap_cluster_info *cluster_info; /* array, one entry per cluster */
#ifdef CONFIG_XSWAP
struct vm_struct *cluster_vm; /* VM_SPARSE area for cluster_info */
+ u64 xswap_id; /* stable id, shown to userspace */
unsigned long nr_clusters_max;/* total clusters in the xswap address space */
unsigned long nr_clusters_mapped; /* currently mapped cluster count */
struct mutex xswap_lock; /* serialize map/unmap operations */
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 35c8aac1e25d..44b54118d10a 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -86,7 +86,10 @@ static void xswap_unmap_clusters(struct swap_info_struct *si,
static int xswap_mapped_end(pte_t *pte, unsigned long addr, void *data);
static int xswap_create(int prio);
-static int xswap_destroy(int type);
+static int xswap_destroy(u64 id);
+
+/* Stable device id, assigned at create and never reused. */
+static atomic64_t xswap_id_counter = ATOMIC64_INIT(0);
static ssize_t xswap_create_store(struct kobject *kobj,
struct kobj_attribute *attr,
@@ -121,19 +124,17 @@ static ssize_t xswap_destroy_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
- unsigned long type;
+ u64 id;
int err;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- err = kstrtoul(buf, 0, &type);
+ err = kstrtoull(buf, 0, &id);
if (err)
return err;
- if (type >= MAX_SWAPFILES)
- return -EINVAL;
- err = xswap_destroy(type);
+ err = xswap_destroy(id);
if (err)
return err;
@@ -3657,9 +3658,15 @@ static int swap_show(struct seq_file *swap, void *v)
if (file)
len = seq_file_path(swap, file, " \t\n\\");
else {
- char name[16];
+ char name[32];
+#ifdef CONFIG_XSWAP
+ len = scnprintf(name, sizeof(name), "xswap%llu",
+ (unsigned long long)si->xswap_id);
+#else
+ /* CONFIG_XSWAP=n has no file-less devices; keep the type. */
len = scnprintf(name, sizeof(name), "xswap%d", si->type);
+#endif
seq_puts(swap, name);
}
seq_printf(swap, "%*s%s\t%lu\t%s%lu\t%s%d\n",
@@ -4295,6 +4302,11 @@ static int xswap_create(int prio)
si->flags |= SWP_XSWAP | SWP_SOLIDSTATE;
si->max = maxpages;
si->pages = maxpages - 1;
+ /*
+ * Set before the device is enabled, for debugfs; destroy only matches
+ * a WRITEOK device, so the create window is not reachable.
+ */
+ si->xswap_id = atomic64_inc_return(&xswap_id_counter);
/*
* No backing file: setup_swap_extents() is only reachable from the
* file-backed swapon() path, so set ops here. Only ops->flags is
@@ -4316,8 +4328,8 @@ static int xswap_create(int prio)
si->list.prio = -si->prio;
si->avail_list.prio = -si->prio;
enable_swap_info(si);
- pr_info("xswap: adding extendable swap type %d (prio %d, %lu pages)\n",
- si->type, prio, si->pages);
+ pr_info("xswap: adding extendable swap device xswap%llu (prio %d, %lu pages)\n",
+ (unsigned long long)si->xswap_id, prio, si->pages);
mutex_unlock(&swapon_mutex);
atomic_inc(&proc_poll_event);
wake_up_interruptible(&proc_poll_wait);
@@ -4336,20 +4348,31 @@ static int xswap_create(int prio)
return error;
}
-/* Tear down a file-less xswap device by its swap type. */
-static int xswap_destroy(int type)
+/* Tear down a file-less xswap device by its stable id. */
+static int xswap_destroy(u64 id)
{
- struct swap_info_struct *p;
+ struct swap_info_struct *p = NULL;
+ unsigned int type;
int err;
- p = swap_type_to_info(type);
- if (!p)
- return -EINVAL;
-
spin_lock(&swap_lock);
- if (!(p->flags & SWP_WRITEOK) || !(p->flags & SWP_XSWAP)) {
+ /*
+ * Match only a device that is fully enabled: one still being created
+ * is not WRITEOK yet, and one being destroyed has lost it. Neither
+ * is a valid target, so both read as "no such device".
+ */
+ for (type = 0; type < nr_swapfiles; type++) {
+ struct swap_info_struct *q = swap_info[type];
+
+ if (q && (q->flags & (SWP_XSWAP | SWP_WRITEOK)) ==
+ (SWP_XSWAP | SWP_WRITEOK) && q->xswap_id == id) {
+ p = q;
+ break;
+ }
+ }
+ if (!p) {
spin_unlock(&swap_lock);
- return -EINVAL;
+ return -ENODEV;
}
/* Refuse swapoff while the device is pinned for hibernation */
if (p->flags & SWP_HIBERNATION) {
--
2.54.0
next prev parent reply other threads:[~2026-11-09 5:56 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 5:54 [PATCH v5 00/19] mm, swap: extendable swap devices (xswap phase I) Baoquan He
2026-11-09 5:54 ` [PATCH v5 01/19] mm: xswap support for zswap Baoquan He
2026-11-10 5:57 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 02/19] mm, swap: refactor free_swap_cluster_info to take swap_info_struct Baoquan He
2026-11-09 5:54 ` [PATCH v5 03/19] mm, swap: add VM_SPARSE cluster-array helpers for xswap Baoquan He
2026-11-09 5:54 ` [PATCH v5 04/19] mm, swap: use a VM_SPARSE cluster array for xswap devices Baoquan He
2026-11-10 5:58 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 05/19] mm, swap: widen swap_info_struct max/pages to unsigned long Baoquan He
2026-11-09 5:54 ` [PATCH v5 06/19] mm, swap: add a sysfs interface to create xswap devices Baoquan He
2026-11-09 5:54 ` [PATCH v5 07/19] mm, swap: refactor swapoff and add xswap_destroy Baoquan He
2026-11-09 5:54 ` [PATCH v5 08/19] mm, swap: require zswap for xswap devices Baoquan He
2026-11-09 5:54 ` Baoquan He [this message]
2026-11-10 5:58 ` [PATCH v5 09/19] mm, swap: use a stable id " sashiko-bot
2026-11-09 5:54 ` [PATCH v5 10/19] mm, swap: let the command line set the xswap device size Baoquan He
2026-11-09 5:54 ` [PATCH v5 11/19] mm, swap: add CONFIG_XSWAP_DEFAULT_MAX Baoquan He
2026-11-09 5:54 ` [PATCH v5 12/19] mm, swap: let swapoff destroy xswap devices by name Baoquan He
2026-11-10 5:58 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 13/19] mm, swap: add xswap grow trigger on cluster allocation Baoquan He
2026-11-10 5:58 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 14/19] mm, swap: add debugfs counters for xswap Baoquan He
2026-11-09 5:54 ` [PATCH v5 15/19] mm, swap: make xswap cluster_info accesses RCU-safe Baoquan He
2026-11-10 5:58 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 16/19] mm, swap: prepare xswap_unmap_clusters for range shrinking Baoquan He
2026-11-09 5:54 ` [PATCH v5 17/19] mm, swap: add xswap shrink trigger and defer it to a workqueue Baoquan He
2026-11-10 5:58 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 18/19] mm, swap: do not give an xswap slot to a cgroup that cannot zswap Baoquan He
2026-11-10 5:58 ` sashiko-bot
2026-11-09 5:54 ` [PATCH v5 19/19] mm, swap: skip the overcommit probe when removing xswap Baoquan He
2026-11-09 6:15 ` [PATCH v5 00/19] mm, swap: extendable swap devices (xswap phase I) Baoquan He
2026-11-12 7:25 ` [syzbot ci] " syzbot ci
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=20261109055455.536925-10-baoquan.he@linux.dev \
--to=baoquan.he@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=chengming.zhou@linux.dev \
--cc=chrisl@kernel.org \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=hebaoquan@kylinos.cn \
--cc=kasong@tencent.com \
--cc=klarasmodin@gmail.com \
--cc=kunwu.chan@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=nphamcs@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.