From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-189.mta1.migadu.com (out-189.mta1.migadu.com [95.215.58.189]) (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 8EBB93290D0 for ; Mon, 13 Jul 2026 16:18:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.189 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783959495; cv=none; b=WPLa/HYa1BuvRrwr/PkaZakW0bUvba+9+rB1eV3VPCumtdxJBMejgthn7dPDvTdFyZRwlQ0HxK0QRhI38teSVoEd87mB9vKmAO37x+ZucXHW+0sqvE/30mBTx7vG7Y66GslXsRELAGUuU3XR6Vd7TOJTVWfGxt8q8BxecC4goAI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783959495; c=relaxed/simple; bh=XUF9kiHaKLjWHyQDKIAeLmJXUn/JVsp0GMu0MIIdPVw=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=adwEX4ZZYCe8jrtWHJt2CE5/kRtGUN2gkcTQFlQSRZPhsDZU4lBRwFUYiEXmTBYj6rYwMrqjbm6wQmLIX1wBsODGHkxJGnX5uf1CKQsiCbWNUOjg3EeURMsmccMgyrRZ+0IPlCoOg6Y0yz92Wj4aW+fjBORuVVscyOAlmXR+gYM= 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=Ia1C88PO; arc=none smtp.client-ip=95.215.58.189 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="Ia1C88PO" Message-ID: <03a20b9a-2984-4666-832d-0e35df919a7d@linux.dev> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1783959488; 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-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NE/5A5qkR6uAqQiCbOoPzdzcNr6Exfk7cAXEitmmrI0=; b=Ia1C88POnfJWrehgtJH6hSDce7pnx2cVNEFya3NdYsLuxozRTM1E5DnT5nWldTjrWQZkM1 hF2ehYIrLZzj7kDXyGBtwMsDXrPznZLRKyz37HLJbu7psPRzQhgtQiQhqMmF8sT2Q1V6qI 4dOJKPLlVONdcPX4+8y6ZtfcRoAc+FU= Date: Mon, 13 Jul 2026 17:17:57 +0100 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Subject: Re: [PATCH v4 00/11] mm: PMD-level swap entries for anonymous THPs To: Yosry Ahmed Cc: Andrew Morton , david@kernel.org, chrisl@kernel.org, kasong@tencent.com, ljs@kernel.org, ziy@nvidia.com, linux-mm@kvack.org, ying.huang@linux.alibaba.com, Baoquan He , willy@infradead.org, youngjun.park@lge.com, hannes@cmpxchg.org, riel@surriel.com, shakeel.butt@linux.dev, alex@ghiti.fr, kas@kernel.org, baohua@kernel.org, dev.jain@arm.com, baolin.wang@linux.alibaba.com, npache@redhat.com, "Liam R. Howlett" , ryan.roberts@arm.com, Vlastimil Babka , lance.yang@linux.dev, linux-kernel@vger.kernel.org, nphamcs@gmail.com, shikemeng@huaweicloud.com, kernel-team@meta.com References: <20260713133613.2707815-1-usama.arif@linux.dev> Content-Language: en-US X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Usama Arif In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT On 13/07/2026 16:56, Yosry Ahmed wrote: > On Mon, Jul 13, 2026 at 6:36 AM Usama Arif wrote: >> >> This is the PMD swap entry core series. The preparatory PMD softleaf [1] >> cleanup series has been merged in akpm/mm-new, so this series is now >> based directly on akpm/mm-new. >> >> When reclaim swaps out a PMD-mapped anonymous THP today, the PMD is >> split into HPAGE_PMD_NR PTE-level swap entries via TTU_SPLIT_HUGE_PMD >> before unmap. This series introduces a PMD-level swap entry so the >> huge mapping can survive the swap round-trip and do_huge_pmd_swap_page() >> can restore the PMD mapping directly on swap-in, without waiting for >> khugepaged to collapse the range later. >> >> The PMD swap entry is a compact page-table encoding for HPAGE_PMD_NR >> consecutive swap slots. swap_map accounting remains per-slot and is >> unchanged. Importantly, a PMD swap entry does not promise that the swap >> cache always contains one PMD-sized folio. While the cache is empty or >> contains one PMD-sized folio, PMD-level handling can proceed. Once the >> cache has split/per-slot state, users either inspect the individual >> slots directly (mincore) or split the PMD swap entry and retry through >> the PTE path (fault, swapoff, MADV_WILLNEED, UFFDIO_MOVE). Likewise, >> if any slot is still backed by zswap's per-page store, PMD-order >> swap-in consumers split and let the PTE path load the range page by page; >> an all-on-disk range can still be read back as one PMD-sized folio. >> >> The series is ordered so every consumer can handle PMD swap entries >> before the swap-out producer starts installing them. The swap-out patch >> is the last functional change. >> >> Patch breakdown: >> >> 1. mm: add PMD swap entry detection support >> Add pmd_is_swap_entry(), teach the softleaf layer that PMD swap >> entries are valid PMD softleaf entries, and add per-arch >> pmd_swp_*exclusive helpers. >> >> 2. mm: add PMD swap entry splitting support >> Teach __split_huge_pmd_locked() to split a PMD swap entry into >> HPAGE_PMD_NR PTE swap entries. This is the common fallback path >> whenever PMD-level handling is unsafe or unavailable. >> >> 3. mm: handle PMD swap entries in fork path >> Copy a PMD swap entry in fork via one >> swap_dup_entries_direct(HPAGE_PMD_NR) operation, with the same >> swapoff/mmlist preparation rules used by PTE entries. >> >> 4. mm: zswap: add range lookup for large-folio swapin >> Teach zswap_load() to let all-on-disk large folio reads proceed to >> the backing swap device, and add zswap_range_has_entry() so PMD >> swap-entry consumers can split only when a specific range has >> per-page zswap state. >> >> 5. mm: swap in PMD swap entries as whole THPs during swapoff >> Add swap_pmd_cache_lookup() and use it from swapoff. Empty cache >> and PMD-sized cache state can be handled at PMD order; split cache >> state, zswap-backed slots, allocation/read failure, or non-uptodate >> folios split the PMD and fall back to unuse_pte_range(). >> >> 6. mm: handle PMD swap entries in non-present PMD walkers >> Teach zap, mprotect, soft-dirty, uffd-wp, smaps, mincore, >> mempolicy, khugepaged, HMM, and madvise walkers about PMD swap >> entries. mincore reports PMD-sized cache state directly and checks >> per-page slots after the cache has split. >> >> 7. mm: handle PMD swap entries in MADV_WILLNEED >> Let MADV_WILLNEED prefetch a PMD swap entry at PMD order when safe, >> treat an already cached PMD-sized folio as complete, and split/retry >> through PTEs for split cache state, zswap-backed slots, or races >> with per-slot cache population. >> >> 8. mm: handle PMD swap entries in UFFDIO_MOVE >> Move PMD swap entries whole when the covered range is empty or >> backed by one PMD-sized folio. Split/per-slot cache state returns >> -EAGAIN after splitting so retry can use the PTE move path and >> update per-page rmap metadata. >> >> 9. mm: handle PMD swap entry faults on swap-in >> Add do_huge_pmd_swap_page(). It maps a PMD-sized cached folio >> directly, or allocates/reads at PMD order when the cache is empty >> and the range has no zswap entries. Split cache state, zswap-backed >> slots, and PMD-order resource failures fall back to the PTE path. >> >> 10. mm: install PMD swap entries on swap-out >> Stop forcing TTU_SPLIT_HUGE_PMD for PMD-mappable swapcache folios >> and install one PMD swap entry instead. Zswap still stores the THP >> as per-page compressed entries; PMD-order swap-in consumers preserve >> a PMD-sized cached folio or read an all-on-disk range as a whole THP, >> and split before reading per-page zswap state. >> >> 11. selftests/mm: add PMD swap entry tests >> Add pmd_swap selftests covering swap-out/in, fork, fork+COW, >> repeated cycles, write fault, munmap, mprotect, mremap, pagemap, >> mincore, MADV_FREE, MADV_WILLNEED, UFFDIO_MOVE, and swapoff. >> >> Notes on zswap: >> >> Native PMD-order zswap load/store is intentionally left for a follow-up. >> Alexandre Ghiti is currently working this. >> This series can still preserve PMD swap entries while zswap is enabled: >> zswap stores the THP as order-0 entries, and PMD-order swap-in >> consumers split any range that has zswap entries before reading it. If >> zswap has written the whole range back to disk, or the swap cache still >> contains one PMD-sized folio, PMD-level handling can proceed. > > So in the swapout path, a single PMD swap entry is created, but > order-0 pages are compressed and stored independently in zswap? Just > checking I understood this correctly. Yes that is correct, swapout installs PMD swap entry in try_to_unmap_one(). When the swapped-out THP reaches zswap, current zswap still stores it as independent order-0 entries keyed by the individual swap slots. On PMD-order swap-in, we only proceed as a THP if the swap cache still has one PMD-sized folio, or if none of the covered slots is present in zswap and the whole range can be read from disk. If any slot is still backed by zswap, we split the PMD swap entry and retry through the normal PTE path.