From: Baoquan He <baoquan.he@linux.dev>
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 <baoquan.he@linux.dev>
Subject: [RFC PATCH 02/10] mm/swap_table: add Redirect entry encoding for ghost swap backend switching
Date: Tue, 7 Jul 2026 16:26:04 +0800 [thread overview]
Message-ID: <20260707082614.95030-3-baoquan.he@linux.dev> (raw)
In-Reply-To: <20260707082614.95030-1-baoquan.he@linux.dev>
Introduce SWP_TB_REDIRECT_MARK (0b101) as a new swap table entry type
that stores a physical swp_entry_t directly. This allows a ghost
swap slot to redirect to a physical swap slot after zswap writeback.
The swp_entry_t has its low 12 bits clear (page-aligned offset), so
the 3-bit mark is ORed directly into the value without shifting and
without losing any type or offset bits.
Add inline helpers:
- swp_tb_is_redirect(): type check
- swp_entry_to_redirect(): encode a swp_entry_t as a Redirect entry
- redirect_to_swp_entry(): decode a Redirect entry back to swp_entry_t
Update the swap table entry type documentation to include the new
Redirect type.
Signed-off-by: Baoquan He <baoquan.he@linux.dev>
---
mm/swap_table.h | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/mm/swap_table.h b/mm/swap_table.h
index 6318bf8aa76b..5a971152cf23 100644
--- a/mm/swap_table.h
+++ b/mm/swap_table.h
@@ -29,6 +29,7 @@ struct swap_memcg_table {
* Shadow: |SWAP_COUNT|Z|---- SHADOW_VAL ---|1| - Swapped out slot
* PFN: |SWAP_COUNT|Z|------ PFN -------|10| - Cached slot
* Pointer: |----------- Pointer ----------|100| - Zswap compressed entry
+ * Redirect: |------- swp_entry_t.val ------|101| - Redirect to phys swap
* Bad: |------------- 1 -------------|1000| - Bad slot
*
* COUNT is `SWP_TB_COUNT_BITS` long, Z is the `SWP_TB_ZERO_FLAG` bit,
@@ -55,6 +56,11 @@ struct swap_memcg_table {
* all upper bits. `0b100` is used as the marker because zswap_entry
* pointers are at least 8-byte aligned, leaving the lower three bits free.
*
+ * - Redirect: Stores a physical swp_entry_t directly, ending with `0b101`.
+ * Used by ghost swapfiles to redirect a virtual slot to a physical swap
+ * slot after zswap writeback. swp_entry_t has bits 0-11 clear (page-aligned
+ * offset), so the 3-bit mark is ORed directly into the value without shifting.
+ *
* - Bad: Swap slot is reserved, protects swap header or holes on swap devices.
*/
@@ -83,6 +89,15 @@ struct swap_memcg_table {
/* Pointer: zswap_entry pointer stored directly, ends with 0b100 */
#define SWP_TB_POINTER_MARK 0b100UL
+/*
+ * Redirect: stores a physical swp_entry_t directly, ends with 0b101.
+ * Used by ghost swapfiles to redirect a virtual slot to a physical
+ * swap slot after writeback. swp_entry_t has its low 12 bits clear
+ * (page-aligned offset), so we can OR the 3-bit mark directly into
+ * the entry value without shifting and without losing type bits.
+ */
+#define SWP_TB_REDIRECT_MARK 0b101UL
+
/* Bad slot: ends with 0b1000 and rests of bits are all 1 */
#define SWP_TB_BAD ((~0UL) << 3)
@@ -176,6 +191,11 @@ static inline bool swp_tb_is_pointer(unsigned long swp_tb)
return (swp_tb & (BIT(3) - 1)) == SWP_TB_POINTER_MARK;
}
+static inline bool swp_tb_is_redirect(unsigned long swp_tb)
+{
+ return (swp_tb & (BIT(3) - 1)) == SWP_TB_REDIRECT_MARK;
+}
+
static inline bool swp_tb_is_countable(unsigned long swp_tb)
{
return (swp_tb_is_shadow(swp_tb) || swp_tb_is_folio(swp_tb) ||
@@ -215,6 +235,24 @@ static inline void *swp_tb_to_pointer(unsigned long swp_tb)
return (void *)(swp_tb & ~((unsigned long)(BIT(3) - 1)));
}
+/*
+ * Redirect encoding: swp_entry_t is stored directly, with the 3-bit
+ * mark ORed into the low bits. swp_entry_t.val has bits 0-11 clear
+ * (page-aligned offset), so no shifting is needed and no type bits
+ * are lost.
+ */
+static inline unsigned long swp_entry_to_redirect(swp_entry_t entry)
+{
+ VM_WARN_ON(entry.val & (BIT(3) - 1));
+ return entry.val | SWP_TB_REDIRECT_MARK;
+}
+
+static inline swp_entry_t redirect_to_swp_entry(unsigned long swp_tb)
+{
+ VM_WARN_ON(!swp_tb_is_redirect(swp_tb));
+ return (swp_entry_t){ .val = swp_tb & ~((unsigned long)(BIT(3) - 1)) };
+}
+
static inline unsigned char __swp_tb_get_count(unsigned long swp_tb)
{
VM_WARN_ON(!swp_tb_is_countable(swp_tb));
--
2.54.0
next prev parent reply other threads:[~2026-07-07 8:26 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 8:26 [RFC PATCH 00/10] mm/swap: ghost swapfile with backend switching via Redirect entries Baoquan He
2026-07-07 8:26 ` [RFC PATCH 01/10] mm: ghost swapfile support for zswap Baoquan He
2026-07-07 8:26 ` Baoquan He [this message]
2026-07-07 8:26 ` [RFC PATCH 03/10] mm/swap: add redirect_xa field and ghost redirect helper declarations Baoquan He
2026-07-07 8:26 ` [RFC PATCH 04/10] mm/swapfile: implement ghost redirect helpers and free-path cascade Baoquan He
2026-07-07 8:26 ` [RFC PATCH 05/10] mm/swap_state: restore Redirect entry when swap cache folio is removed Baoquan He
2026-07-07 8:26 ` [RFC PATCH 06/10] mm/zswap: implement ghost-to-physical writeback for backend switching Baoquan He
2026-07-07 8:26 ` [RFC PATCH 07/10] mm/page_io: forward ghost swap reads to physical device via Redirect Baoquan He
2026-07-07 8:26 ` [RFC PATCH 08/10] mm/swapfile: manage ghost cluster_info via lazy vmalloc Baoquan He
2026-07-07 8:26 ` [RFC PATCH 09/10] mm/swapfile: implement swap_ghost_extend_max() for dynamic growth Baoquan He
2026-07-07 22:36 ` Nhat Pham
2026-07-09 14:52 ` Baoquan He
2026-07-10 1:11 ` Nhat Pham
2026-07-11 9:02 ` Chris Li
2026-07-07 8:26 ` [RFC PATCH 10/10] mm/swapfile: add sysfs interface for ghost swap extension Baoquan He
2026-07-07 8:56 ` [RFC PATCH 00/10] mm/swap: ghost swapfile with backend switching via Redirect entries Baoquan He
2026-07-07 21:23 ` Nhat Pham
2026-07-07 21:25 ` Nhat Pham
2026-07-09 11:38 ` Baoquan He
2026-07-13 0:02 ` Nhat Pham
2026-07-13 17:47 ` Chris Li
2026-07-11 8:49 ` Chris Li
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=20260707082614.95030-3-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=hannes@cmpxchg.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=yosry@kernel.org \
--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.