From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-170.mta0.migadu.com (out-170.mta0.migadu.com [91.218.175.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 795802C027B for ; Tue, 7 Jul 2026 08:26:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783412786; cv=none; b=TN2WU9iYnY38QtnVmAgsQ/SQkiWBQ0PdBejJxjt9uovcrRuU1Vs2CiBnS5YwTvrzShqhBSX7YHm5tz9C5mD0uPnHSm//ijAGcpWTpIQrh4A3zG4V2wmQWRI5ktNobyYiq7o9rdkV3qcH2PUgOYso4xVs5NdspogncJEMdU6ANZM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783412786; c=relaxed/simple; bh=gD5Ws3fDuWeScq5v/FW+DlFEpVLg3UBASn3UjxzsHdQ=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type: Content-type; b=D3KmRU/Y3augKUTYkF1Eaa8ruMBMzZByroICX423+FCkVT4euGgMihdetZVpokvb4DmXyJkVTtQ8GO/UGbvQImnUbSHyYqob/Pca7zkN3DxWUGaCSNHDH0Jppg7+DNU7JH/Ctqem1Q4xLBMa+rLCzhXugIwx3XtPHkesgzY8AqY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Qb2NMapP; arc=none smtp.client-ip=91.218.175.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Qb2NMapP" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1783412782; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=47HDgQybI+3t5P+eb3AQpo+jGwETFx3wSiNf2a7otpQ=; b=Qb2NMapPhOb2KOQ3rJlfqhuKlRoAbITD0I7wmfCox+Ny8QM6YwO6fsZcZz5Ct6QotTK50F hLXs0XGQnMbmjXKZdScN+ruY4MFHetQ8nIblM22UXvcvMnaxN+QPsUUkkqIy0v2TD5rAPI KM28kDxW6Xl/EtggVHp1zkFD5DCSvbY= From: Baoquan He To: linux-mm@kvack.org Cc: akpm@linux-foundation.org, chrisl@kernel.org, kasong@tencent.com, shikemeng@huaweicloud.com, nphamcs@gmail.com, baohua@kernel.org, youngjun.park@lge.com, hannes@cmpxchg.org, yosry@kernel.org, chengming.zhou@linux.dev, linux-kernel@vger.kernel.org, Baoquan He Subject: [RFC PATCH 00/10] mm/swap: ghost swapfile with backend switching via Redirect entries Date: Tue, 7 Jul 2026 16:26:02 +0800 Message-ID: <20260707082614.95030-1-baoquan.he@linux.dev> 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: 8bit X-Migadu-Flow: FLOW_OUT This series introduces a virtual "ghost" swapfile that can be backed by multiple physical swap devices, switching between them at runtime using a new "Redirect" swap table entry type. Motivation ---------- Physical swap devices have fixed, large sizes but a machine may only need a fraction at any given time. Ghost swap decouples the logical swap capacity from physical swap allocation: it presents a large virtual swap device to userspace while lazily mapping slots to physical devices only when data must leave zswap (writeback). This enables overcommit of swap capacity without wasting physical disk space, and allows the ghost device to grow dynamically at runtime. Ghost swapfile characteristics -------------------------------- Ghost swap decouples logical swap capacity from physical swap allocation. Key properties: - No backing store required. A ghost swap device can operate purely as a zswap container — compressed pages stay in the zswap pool without ever touching a physical swap device. No physical swap device needs to be attached. - Optional physical backing. One or more physical swap devices can be swapon'd alongside the ghost device, acting as writeback targets when the zswap pool needs to evict cold pages. The Redirect entry in the ghost swap table links each evicted slot to its physical destination. - Dynamic size growth. The ghost device can be extended at runtime via sysfs, up to a current maximum of 1TB. This is implemented through lazy vmalloc: a sparse 64MB virtual address space is reserved at swapon time to cover the full 1TB range, but physical pages for cluster_info[] structures are allocated only on demand as the device grows. The cluster_info pointer never changes, so all existing accessors (__swap_offset_to_cluster, cluster_index) work unchanged. - sysfs control. Each ghost device exposes attributes under /sys/kernel/mm/ghost_swap/ghost_/: path (RO) — backing device name max (RW) — current max pages; writing a larger value triggers swap_ghost_extend_max() Design overview --------------- A swap table slot can now hold a Redirect entry: Redirect: |----- physical swp_entry_t -----|101| This stores a plain swp_entry_t pointing to a slot on a real (physical) swap device. The low 3-bit mark (0b101) distinguishes it from Pointer (0b100), PFN (0b10), Shadow (0b1), and NULL (0) entries. The lifecycle is: 1. swapon a ghost device — reserves sparse vmalloc area (64MB virtual) and physically backs only the initial range. The device starts with no physical backing store: pages swapped out go to zswap, and zswap pool evictions go to any concurrently attached physical device. 2. zswap writeback from ghost: when the zswap pool needs to evict, zswap_writeback_ghost() allocates a physical slot from any real swap device, writes the data there, and plants a Redirect entry in the ghost's swap table pointing to the physical slot. 3. Swap-in from ghost: swap_read_folio() detects the ghost device (SWP_GHOST), resolves the Redirect to the physical swp_entry_t, and forwards the read I/O to the physical device. 4. When the swap cache folio is removed, the Redirect entry is restored from an xarray (redirect_xa) that persists the mapping, so subsequent reads still find the physical backing. 5. When the physical slot is freed, the ghost slot is also freed, cascading through swap_range_free(). Note: ------ Ghost swapfile is a proof of concept. Compared with the other patchset: [RFC PATCH v2 0/7] mm, swap: Virtual Swap Space (Swap Table Edition), it explores a different approach to implementing virtual swap on top of the existing swap table infrastructure, with a simpler implementation. It builds on Chris Li's earlier ghost swapfile work and is currently tentatively named "ghost swapfile" — alternative naming suggestions are welcome. Ghost swapfile setup can also be integrated through modifications to the swapon API and the swapon command in util-linux, for example: swapon --ghost ghost_1:2G -p 5. Baoquan He (9): mm/swap_table: add Redirect entry encoding for ghost swap backend switching mm/swap: add redirect_xa field and ghost redirect helper declarations mm/swapfile: implement ghost redirect helpers and free-path cascade mm/swap_state: restore Redirect entry when swap cache folio is removed mm/zswap: implement ghost-to-physical writeback for backend switching mm/page_io: forward ghost swap reads to physical device via Redirect mm/swapfile: manage ghost cluster_info via lazy vmalloc mm/swapfile: implement swap_ghost_extend_max() for dynamic growth mm/swapfile: add sysfs interface for ghost swap extension Chris Li (1): mm: ghost swapfile support for zswap include/linux/swap.h | 10 + mm/page_io.c | 51 +++- mm/swap.h | 16 +- mm/swap_state.c | 28 +++ mm/swap_table.h | 38 +++ mm/swapfile.c | 579 ++++++++++++++++++++++++++++++++++++++++--- mm/zswap.c | 98 +++++++- 7 files changed, 772 insertions(+), 48 deletions(-) -- 2.54.0