From nobody Tue Sep 29 02:04:00 2026 Received: from mta1.migadu.com (out-80.mta1.migadu.com [95.215.58.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78FE6353A67 for ; Thu, 13 Aug 2026 10:49:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.80 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786618148; cv=none; b=rVlystf6RQvSNhJWiafQjTg8/cgbjMVGFfiJKaJwiqm3dInZST4zrYNiefjSNRLn3GorAnujB10Zx6drJWswwPH9Bg0b383lrkGsLnfHd+79DUlIXM9xiTfjQvtRhHhDkv28aUzHNA8misaNXMf2nfP+CdSjzPe3lXFcoGSlaRw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786618148; c=relaxed/simple; bh=7QhUPTEMcCTIgeBrINpebqppVhXTad6e2zzXL2L7L08=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type: Content-type; b=DUItqXQ0ECpQlydoPHRw+CFPs4ZFzfW4CMVHl6v6lPTETUBaHtWAEdrcU8FfvNhfux0f8xeAGOqhoFXmKOwGqjCjO3YQAhItbPLAA9Ng5l+u8FGQk/w1Oxd32nP88PSljCgRsoT5Kb0vSNivs1WATPzjqx/Jz/ArcEWv6IbYD8w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=linux.dev; arc=none smtp.client-ip=95.215.58.80 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev X-Envelope-To: linux-kernel@vger.kernel.org X-Envelope-To: linux-kernel@vger.kernel.org Received: from localhost (3.112.29.171) by mta11.migadu.com with ESMTPS id 5e9b508ab49f9b79; Thu, 13 Aug 2026 10:49:03 +0000 X-Migadu-Flow: FLOW_OUT From: Baoquan He To: linux-mm@kvack.org Cc: chrisl@kernel.org, nphamcs@gmail.com, kasong@tencent.com, baohua@kernel.org, youngjun.park@lge.com, hannes@cmpxchg.org, yosry@kernel.org, shikemeng@huaweicloud.com, chengming.zhou@linux.dev, baoquan.he@linux.dev, linux-kernel@vger.kernel.org, Baoquan He Subject: [RFC v3 00/15] xswap: extendable (virtual) swap device backed by zswap Date: Thu, 13 Aug 2026 18:48:39 +0800 Message-ID: <20260813104857.3450386-1-hebaoquan@kylinos.cn> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-type: text/plain Content-Transfer-Encoding: quoted-printable xswap is an extendable swap device with no backing storage. Swapped-out pages live only in zswap, so the device wastes no disk space and its size is independent of any physical device. xswap decouples PTE swap entries from physical backing storage. The cluster_info array is backed by a sparse vmalloc (VM_SPARSE) area that is grown and shrunk on demand: - Grow: when cluster allocation runs out of free clusters and the device is below its ceiling, more physical pages are mapped into the VM_SPARSE area and their clusters are added to the free list. - Shrink: when contiguous free clusters accumulate at the tail of the mapped range (tracked in O(1) via nr_free_tail), they are unmapped and the backing pages freed. Shrink is deferred to a workqueue to avoid lock recursion. A per-device ceiling (nr_clusters) bounds growth and is adjustable at runtime via debugfs. Interface: /sys/kernel/mm/xswap/create write a percent of RAM (0 for the default) to create a device /sys/kernel/mm/xswap/destroy write a swap type to tear down a device /sys/kernel/debug/xswap/type_cluster_limit read/write the per-device cluster ceiling Since xswap has no backing, swapped-out pages are stored compressed in zswap: physical writeout is skipped, and zswap writeback is disabled when every swapfile in the system is an xswap device. xswap requires zswap, so device creation is refused when zswap is unavailable. Naming: =3D=3D=3D=3D=3D=3D I'm going with "xswap" (the "x" for extendable/extension) rather than "vswa= p". Chris suggested this name, and this aligns with the "VFS-like swap layers" direction Chris Li described in the first swap abstraction LPC talk (co-hosted with Yosry) =E2=80=94 the swap ops and the xswap extension inter= faces in this series are moving toward exactly that. I don't have a strong preference between xswap and vswap, so if reviewers object to the name, please comment. Note: =3D=3D=3D=3D=3D Most of the added lines come from the switch to a sysfs-based create/destroy interface. v2 created an xswap device by handing swapon() a "header-only" swap file (mkswap followed by dd of just the first 4K), and teardown reused the normal swapoff path. v3 makes xswap truly file-less: /sys/kernel/mm/xswap/{create,destroy} replace that file dance. This patchset only build the base. On top of this, I believe Nhat's core co= de of xswap writeback, rmap etc can be implemented simpler. E.g, we only need = add one field in struct swap_cluster_info to let xs_table point to physical swap entry, or zswap entry etc. No need to introduce struct swap_cluster_info_dy= namic. --- a/mm/swap.h +++ b/mm/swap.h @@ -57,6 +57,9 @@ struct swap_cluster_info { u8 order; atomic_long_t __rcu *table; /* Swap table entries, see mm/swap_= table.h */ unsigned int *extend_table; /* For large swap count, protected = by ci->lock */ +#ifdef CONFIG_XSWAP + unsigned long *xs_table; +#endif Testing: =3D=3D=3D=3D=3D=3D=3D=3D 1. enable zswap # echo 1 > /sys/module/zswap/parameters/enabled 2. create xswap device ~# echo 0 > /sys/kernel/mm/xswap/create ~# swapon NAME TYPE SIZE USED PRIO xswap0 xswap 1.2G 0B -1 ~# echo 80 > /sys/kernel/mm/xswap/create=20 ~# swapon NAME TYPE SIZE USED PRIO xswap0 xswap 1.2G 0B -1 xswap1 xswap 3.1G 0B -1 3. tune the zswap size ~# cat /sys/kernel/debug/xswap/type0_cluster_limit=20 1179 ~# cat /sys/kernel/debug/xswap/type1_cluster_limit=20 3145 ~# echo 2048 > /sys/kernel/debug/xswap/type0_cluster_limit ~# echo 2048 > /sys/kernel/debug/xswap/type1_cluster_limit ~# swapon NAME TYPE SIZE USED PRIO xswap0 xswap 2G 377.9M -1 xswap1 xswap 2G 376.2M -1 4. add memory pressure stress-ng --vm 1 --vm-bytes 4G --vm-keep --timeout 120s & create/destroy and grow/shrink xswap device casually, all passed. Changelog =3D=3D=3D=3D=3D=3D=3D=3D=3D v2->v3: - Replace the "header-only swap file + swapon" creation hack with a proper file-less device created and destroyed via sysfs (/sys/kernel/mm/xswap/{create,destroy}). This required the __swapoff() refactor and the free_swap_cluster_info() signature change (patches 4, 6, 14). - Require zswap: refuse to create an xswap device when zswap is unavailable (patch 15). - Split the unrelated zswap -ENOENT fix out of the series into a standalone patch (patch 1). - Fix nr_free_tail over-counting on concurrent grow, shrink leaking detached clusters on early bail-out, a re-init race on cluster spinlocks in xswap_map_clusters(), the nr_clusters_mapped update ordering, and swapoff accessing the shrinker-unmapped cluster tail. - Minor cleanups (checkpatch, /proc/swaps alignment, commit messages). v1->v2: - Added __GFP_HIGH | __GFP_NOMEMALLOC to alloc_page() and kmalloc_array() in the grow path, plus memalloc_noreclaim_save/restore() wrapping, to prevent the grow path from consuming emergency memory reserves or recursing into swap under PF_MEMALLOC. This is folded into patch 3. This was pointed out by Nhat. - Folded the mutex serialization fix into the cluster grow patch (patch 3). This is suggested by Nhat. - Fixed coding style issues: corrected indentation of declarations in xswap_unmap_clusters(), removed unnecessary block scope around the err variable in xswap_map_clusters(). - Rebased onto mm-unstable Baoquan He (14): mm: zswap: return -ENOENT when the swap device is gone mm, swap: add CONFIG_XSWAP and xswap fields to swap_info_struct mm, swap: refactor free_swap_cluster_info to take swap_info_struct mm, swap: add xswap cluster grow via VM_SPARSE vmalloc mm, swap: add sysfs create interface for xswap mm, swap: add xswap grow trigger on cluster allocation mm, swap: add xswap_try_shrink and shrink trigger on cluster free mm, swap: free backing pages in xswap_unmap_clusters mm, swap: add nr_free_tail for O(1) xswap shrink detection mm, swap: add adjustable runtime ceiling (nr_clusters) for xswap mm, swap: add debugfs knob for xswap per-device cluster limit mm, swap: defer xswap shrink to workqueue to avoid lock recursion mm, swap: refactor swapoff + add xswap_destroy mm, swap: require zswap for xswap devices Chris Li (1): mm: xswap support for zswap include/linux/swap.h | 12 + mm/Kconfig | 9 + mm/page_io.c | 16 + mm/swap_state.c | 7 + mm/swapfile.c | 1012 ++++++++++++++++++++++++++++++++++++++---- mm/zswap.c | 9 +- 6 files changed, 979 insertions(+), 86 deletions(-) --=20 2.54.0