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 12/19] mm, swap: let swapoff destroy xswap devices by name
Date: Mon, 9 Nov 2026 13:54:48 +0800 [thread overview]
Message-ID: <20261109055455.536925-13-baoquan.he@linux.dev> (raw)
In-Reply-To: <20261109055455.536925-1-baoquan.he@linux.dev>
From: Baoquan He <hebaoquan@kylinos.cn>
An xswap device has no backing file, so /proc/swaps shows a synthetic
name, xswap<id>, that file_open_name() cannot open. Teach swapoff to
fall back to xswap_destroy() when the name is exactly "xswap<digits>"
and the lookup failed with -ENOENT.
A real file or directory keeps precedence; other open errors are
returned unchanged, so a file that exists but cannot be opened is not
mistaken for an xswap device. The ABI documentation is updated, and
the destroy attribute remains the unambiguous teardown interface.
A well-formed name for an id that does not exist asks xswap_destroy()
for a device that is not there. It returns -ENODEV; map that to
-ENOENT so swapoff reports a missing name like it does for a missing
file.
Signed-off-by: Baoquan He <hebaoquan@kylinos.cn>
---
.../ABI/testing/sysfs-kernel-mm-xswap | 11 +++-
mm/swapfile.c | 56 ++++++++++++++++++-
2 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-xswap b/Documentation/ABI/testing/sysfs-kernel-mm-xswap
index 38eead0b1b31..f7e7f3e4d216 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-xswap
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-xswap
@@ -9,9 +9,14 @@ Description: File-less swap devices backed by zswap.
for the lifetime of the device.
The name shown in /proc/swaps, xswap<id>, is synthetic and
- is not a path. It cannot be passed to swapoff(2), so
- swapoff -a reports an error for these entries. Use the
- destroy attribute instead.
+ is not a path. swapoff(2) accepts it, so both "swapoff
+ xswap<id>" and swapoff -a tear the device down. A real
+ file or directory with that name takes precedence: if it
+ opens, it is looked up as a swap file and the synthetic
+ device is not used. Only a name that cannot be opened
+ because it does not exist, including a dangling symlink,
+ is treated as an xswap device. Use the destroy attribute
+ for an unambiguous teardown.
An xswap device requires zswap. Disabling zswap at runtime
(enabled=0, or max_pool_percent=0) while xswap devices
diff --git a/mm/swapfile.c b/mm/swapfile.c
index cb53f9415de8..7b1d16226b7b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -34,6 +34,7 @@
#include <linux/backing-dev.h>
#include <linux/mutex.h>
#include <linux/capability.h>
+#include <linux/ctype.h>
#include <linux/syscalls.h>
#include <linux/memcontrol.h>
#include <linux/poll.h>
@@ -88,6 +89,7 @@ static int xswap_mapped_end(pte_t *pte, unsigned long addr, void *data);
static int xswap_create(int prio);
static int xswap_destroy(u64 id);
+static int xswap_destroy_by_name(const char *name);
/* Stable device id, assigned at create and never reused. */
static atomic64_t xswap_id_counter = ATOMIC64_INIT(0);
@@ -275,6 +277,11 @@ static void xswap_sysfs_init(void)
static inline void xswap_sysfs_init(void)
{
}
+
+static inline int xswap_destroy_by_name(const char *name)
+{
+ return -ENOENT;
+}
#endif /* CONFIG_XSWAP */
static void swap_range_alloc(struct swap_info_struct *si,
@@ -3513,8 +3520,21 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
CLASS(filename, pathname)(specialfile);
victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
- if (IS_ERR(victim))
- return PTR_ERR(victim);
+ if (IS_ERR(victim)) {
+ /*
+ * An xswap device has no file, so /proc/swaps shows a name
+ * that cannot be opened. Accept it here so swapoff -a works.
+ * Only a missing name is taken for a device; a real file or
+ * directory that failed for another reason must not match.
+ */
+ if (PTR_ERR(victim) != -ENOENT)
+ return PTR_ERR(victim);
+
+ err = xswap_destroy_by_name(pathname->name);
+ if (err == -ENOENT)
+ return PTR_ERR(victim);
+ return err;
+ }
mapping = victim->f_mapping;
spin_lock(&swap_lock);
@@ -4504,6 +4524,38 @@ static int xswap_destroy(u64 id)
return __swapoff(p);
}
+
+static int xswap_destroy_by_name(const char *name)
+{
+ const char *p;
+ char buf[24];
+ u64 id;
+ int err;
+
+ /* Strictly "xswap<digits>": no sign, no trailing newline. */
+ if (strncmp(name, "xswap", 5))
+ return -ENOENT;
+
+ p = name + 5;
+ if (!isdigit((unsigned char)*p))
+ return -ENOENT;
+ while (isdigit((unsigned char)*p))
+ p++;
+ if (*p)
+ return -ENOENT;
+
+ if (strscpy(buf, name + 5, sizeof(buf)) < 0)
+ return -ENOENT;
+
+ err = kstrtou64(buf, 10, &id);
+ if (err)
+ return -ENOENT;
+
+ err = xswap_destroy(id);
+ if (err == -ENODEV)
+ return -ENOENT;
+ return err;
+}
#endif /* CONFIG_XSWAP */
SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
--
2.54.0
next prev parent reply other threads:[~2026-11-09 5:57 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 ` [PATCH v5 09/19] mm, swap: use a stable id " Baoquan He
2026-11-10 5:58 ` 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 ` Baoquan He [this message]
2026-11-10 5:58 ` [PATCH v5 12/19] mm, swap: let swapoff destroy xswap devices by name 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-13-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.