From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 47776C624DA for ; Thu, 3 Sep 2026 18:29:57 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id DEF2F6B0092; Thu, 3 Sep 2026 14:29:55 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id D51B46B0095; Thu, 3 Sep 2026 14:29:55 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BF2D26B0096; Thu, 3 Sep 2026 14:29:55 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 829B66B0092 for ; Thu, 3 Sep 2026 14:29:55 -0400 (EDT) Received: from smtpin11.hostedemail.com (lb01a-stub [10.200.18.249]) by unirelay02.hostedemail.com (Postfix) with ESMTP id EBD8C120605 for ; Thu, 3 Sep 2026 18:29:54 +0000 (UTC) X-FDA: 85173289908.11.6FC167C Received: from flow-a3-smtp.messagingengine.com (flow-a3-smtp.messagingengine.com [103.168.172.138]) by imf03.hostedemail.com (Postfix) with ESMTP id E87D520005 for ; Thu, 3 Sep 2026 18:29:52 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=shutemov.name header.s=fm2 header.b="b JdZVe6"; dkim=pass header.d=messagingengine.com header.s=fm1 header.b=kbCRJOxh; spf=pass (imf03.hostedemail.com: domain of kirill@shutemov.name designates 103.168.172.138 as permitted sender) smtp.mailfrom=kirill@shutemov.name; dmarc=none ARC-Seal: i=1; a=rsa-sha256; d=hostedemail.com; s=arc-20220608; cv=none; t=1788460193; b=dQKR980KIeqNpIYGluUoSVoJUwFEqSY+efM9Mmm9VIClUzcWrmUrvy6aOc3ug9EBE1h97S YqKzTG+E1k7s5uUL1wvD1MlIrp0Yjp9AAJpNH3uIR91XMrlT3KmKR5Ked9wTlmuS+ro3an G8cMvSjLHQAlG/FI2nidH53xg6Evxzg= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=shutemov.name header.s=fm2 header.b="b JdZVe6"; dkim=pass header.d=messagingengine.com header.s=fm1 header.b=kbCRJOxh; spf=pass (imf03.hostedemail.com: domain of kirill@shutemov.name designates 103.168.172.138 as permitted sender) smtp.mailfrom=kirill@shutemov.name; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1788460193; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=IXAbT3RhlQhLzfRcazVV9LtEcGIthgKmvu2c4KjzvuY=; b=g8lUMyjJRHtoBkBJseOovRQ9x9wRC2a7IVtu0tbP7W9EIFE3IpjvsdjURwc5lq9AgtZE8K XbE0a+9VAt/qMkGslrVh2Qi05I+4F1Hctw18hqXFXSgd+02RZGSUzmWEAB/8+m/MfqO2/k vH1FUpebME8sPA8zvCVeqC+3tZtE2FA= Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailflow.phl.internal (Postfix) with ESMTP id 6F8C61380127; Thu, 3 Sep 2026 14:29:52 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Thu, 03 Sep 2026 14:29:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1788460192; x= 1788467392; bh=IXAbT3RhlQhLzfRcazVV9LtEcGIthgKmvu2c4KjzvuY=; b=b JdZVe6I4o5MKZYcnL79xg8tI+zVR1JDmMZgYVFSYtR8SqW35SnCD7g/95joxvX5X aXeiCt5fmfyFzCFRue3W5UV8XRQiKuUdwWOZwCtQqvOZT3DWv3JVv9JcG0K0dy6z +1IVzKjiCAydrk/jYoZ1N3nIx389GaoHaCK2qtKzAVusk0BCT4q9ut3ribRdqaFG 3HOpf7GrmP3YSG5BASFZXnNUluqBvZ5WDJcF3TCq0hn7D6N+dW0IClv4L2Igw1yN 0SRbbPhLWrY43keGKQ6H09PipuQM+A3hWHhhodd3Kn23f1D/Bpqli04sb3NZY55g qRsG7UEihGe/b4uDG3AVw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1788460192; x=1788467392; bh=I XAbT3RhlQhLzfRcazVV9LtEcGIthgKmvu2c4KjzvuY=; b=kbCRJOxh0BQ9soMyK QxcADm17Z9hOm4OlolGPi0SrnBWReUD2ckX/nmzuoJlifUXT6nVBhFveGt7kp86I BnaLnr/WTe6DmCjOeP6bgSptQ3TrHOtcweAgVyJsMM4FEVVowAsHxo9HZh2GYxJP uhkXHeZIiWJoRdjnor/KDYrMnLyDXy8aPN9AaPhwQlrA9WGNax8Z6gR43tQYVFt7 SI8w6ywcrUIaoGlEkDxAbqrzOTz/u+xfjzqrsLxoJU2QUR5Na6pquTBGZUvF+Svo GjArvPzD9Y1qBtyLUEtcEeooiKmLA9xiMHAKAYthIN241qIz4BAMOTGEXD1cJLv/ JZoHg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFt7tpQ23d6ma5ZKwjaUeV/XmiCXSwfUJTD/UMTaTx+tQ6P98fG4/H3PFA7hJFxaU SY7i6N6X86D7HaHpdbLHvMivEhulOmq3NoSfdg1pBrJA6v+lfq2ALheALUZjz6o7Nf8BIz DWIHLTWCbkC3w9bMwM7vsWb978omVdOmMplVzO2fLHjMRy1E/CxFkmf+2uWv7frAXfMOWG H/vdAXIPTaxMrzbmklMnL5PmRnZSJQIp5M1ihNDwszNqcLBuKJXCEkMPvIWqkfKnePof3W BlQ363pN/8dtwFHD474IAw0kAsBZ9JYvF7V9lEJnX7ro/M4XAHwxRodQrXyCYUn1NLN+PM 0vfdcaBQjLc+HudZy9eIbs9FNURWggrBI09gzzjkvwtrJdKDbJanKkcjjxbA2wXLW5vmPV JHY7vjUWVS+tCavA8PcCB9/d4IboR/rmYFx7WSmkm5HX3rO99EzxgghTPold4UY7N8MLio ckoVvpjoVQYAuSOMa6WiILvVCXgNSpWb0YmrSVSnYN92LolbIS1ZBUCtfZZgzD+yHUUE+T 3FBZrWGSTxV07/NgqDrk6AcNrJhpdb5ML5pWJ3Z4RwgqVY2AvQVvFXk+au178of9NJo1VX Jwuxz1BTVNt4FUyEe/8GbpTWtyYMn6RCqGxKo1ht9sgk2Nnrd0PTSdbQ5Fwg X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 3 Sep 2026 14:29:51 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, "Matthew Wilcox (Oracle)" , David Hildenbrand Cc: Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jan Kara , Rik van Riel , Harry Yoo , Lance Yang , Jann Horn , Alexander Viro , Christian Brauner , "Darrick J. Wong" , Carlos Maiolino , Usama Arif , Pedro Falcato , linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [RFC PATCH 1/5] mm: let folio_mkclean() report which pages had dirty PTEs Date: Thu, 3 Sep 2026 19:29:39 +0100 Message-ID: <20260903182943.662461-2-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903182943.662461-1-kirill@shutemov.name> References: <20260903182943.662461-1-kirill@shutemov.name> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspam-User: X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: E87D520005 X-Stat-Signature: 1bw84tcsbc65oxsskrx8nrgzo815ewmj X-HE-Tag: 1788460192-136007 X-HE-Meta: U2FsdGVkX1+zaPLyidtyHmMOoL3U/MnHMVXRsK7Oz7l+SbONlGzOfnzy6w4LxAN/+2RdMh+bN6q57UA49Dd6sVMQZv/NmbLSIzebDrjD4Q+yMk2YhzEng/hmxuIW27+iB756tjY3jxuX3oG42IazvzX0qjRO9dea/7MLU/tIHJRf9W4iqEplzq7O+VJnq9HL4NDQzXhxCIBX/jGpfkySyjJNTgAU6NahQ6MHB85KtgE/ZRwn2BfbKDpJOg8vHDxPAi5MjsJmUw+2lMHh4qggh1a0hjFD/Yi0MnnncmpNr+ZLBUazrATIruTolP/auTLx0aT5uhJm0PZ8yVCpVEByqel5fDlOqZeWFzmiiUiQCCb+6AGCHeE4SeWJfCBtpqyjFiGza7wTVRxWTWmld8RNHPZZ+VNyR0H6QUhqThFbffznvgqIYfdkQwQpN1eIRWN7QaYsUHrUoI+6Zk2GfY7JRss2Ah4154lUzFsO+qk5Fhe45m1NEpk4VmAyLked7Wfn+6QUhGyGzZrkDmyCRPumrl5j9kFKf7SYJemRBjliytAFjsU4sY6hCtFbMBr4MjnUg/Mu1YIvjH0Mx5SazBF2PpLlP/krqVSDm6zlhykuxamefY+PdKcM7lPLwvp43T0QVg1s+uCFx4xGaf4RhShFKrYDHmGfAIRfyyhn/cpbbPrtpGiAGwyz9kOfBrohBnTpuj14yXOm0B9i2A4qZsFhRxFze/4mA/HrxU+Ioi+9vpHQ3w/8bpq+m9Sx+umE6EYi4aMbDWgL/BC5lPUjzEJTdj0Nw3XrBtrMZNP5AhfFqgGEeBC4YH9OBHroUGkxZjd4cGg+NuLD8tNWf/U0SKBy74OaRNNQxADXlD17bEaJOa9OPKtuJawmNc5oSDzwxQD86Yp7KjwESZ54SeomO3sjS5kKhfe5CE6DYaJpzAlkHwk3U69uMzYsGFoq3ws5ESsSj4zx/1OOo9/u5MGkXJo r2Glagwc ff9FPX0k2V7S3hDoxDj2EPqytmMswtHMYwkWWOuhssYaeJHP5xL902M2p1ncGMyftDVLZhZkIYDSXzN043o7Q6HN2IKu8BwKHpL+e5tQXkOb5Yq2SnsS4lod8/UW/RsNiFQlFleRIAMaOmI/x9cFtKNO+bYHybXLWV/7ar8KcUv3NezS6cd8U8FnvFdHcIWsZtRionTsKoIq3X5HhWLbm3DP9uueySsXvfddSxSxFbx4PL7Qa9GhshyKTyq1pG/G3wf+Gr4aE79n1TMY2l1j3nZjSBMwtjJOwiLQjokEHekwoLUepiEmxUZzu3DOH1Ed31NAgHDt5abPHENhwp7EM1EBQ577+vd5htkDpVu4Tb5c8u5MQj9KoIuctVHYaajvzdDSO9HmVZfq6J1m8GRdUJRoRB9P9YdKV7oLFmPWfWaQJxKiz+qXVVcR8Z/NcgPAGxRvmgM7rGmWECNC2MflQSxSedvv72KnkKxR3cEjOWbuogj5EAoDi2Tqv2g== Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: "Kiryl Shutsemau (Meta)" folio_mkclean() walks every mapping of a folio and clears the dirty and write bits of each page table entry. It has the per-entry dirty bit in hand while doing that, but only counts how many entries it cleaned. For a large folio those bits are the only record of which parts of the folio were written through a mapping. Everything downstream has to assume the whole folio changed because that information is dropped here. Add folio_mkclean_dirtymap(), which takes a bitmap and sets a bit for every page of the folio whose entry was dirty. folio_mkclean() becomes a wrapper that passes no bitmap, so there is no change in behaviour yet. A PMD entry has one dirty bit for the whole folio, so a PMD-mapped folio reports all of its pages as dirty. That is the best that can be done: the hardware does not track anything finer for a PMD. Assisted-by: Claude:claude-opus-5 Signed-off-by: Kiryl Shutsemau (Meta) --- include/linux/rmap.h | 7 ++++++ mm/rmap.c | 56 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 8dc0871e5f00..6fc0a6020252 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -927,6 +927,7 @@ unsigned long page_address_in_vma(const struct folio *folio, * returns the number of cleaned PTEs. */ int folio_mkclean(struct folio *); +int folio_mkclean_dirtymap(struct folio *folio, unsigned long *dirty_map); int mapping_wrprotect_range(struct address_space *mapping, pgoff_t pgoff, unsigned long pfn, unsigned long nr_pages); @@ -990,6 +991,12 @@ static inline int folio_mkclean(struct folio *folio) { return 0; } + +static inline int folio_mkclean_dirtymap(struct folio *folio, + unsigned long *dirty_map) +{ + return 0; +} #endif /* CONFIG_MMU */ #endif /* _LINUX_RMAP_H */ diff --git a/mm/rmap.c b/mm/rmap.c index 1f72d279ba68..aaf45ac79fa8 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1100,12 +1100,18 @@ int folio_referenced(struct folio *folio, int is_locked, return rwc.contended ? -1 : pra.referenced; } -static int page_vma_mkclean_one(struct page_vma_mapped_walk *pvmw) +struct mkclean_state { + unsigned long *dirty_map; + int cleaned; +}; + +static int page_vma_mkclean_one(struct page_vma_mapped_walk *pvmw, + unsigned long *dirty_map) { - int cleaned = 0; struct vm_area_struct *vma = pvmw->vma; - struct mmu_notifier_range range; unsigned long address = pvmw->address; + struct mmu_notifier_range range; + int cleaned = 0; /* * We have to assume the worse case ie pmd for invalidation. Note that @@ -1134,6 +1140,15 @@ static int page_vma_mkclean_one(struct page_vma_mapped_walk *pvmw) if (!pte_dirty(entry) && !pte_write(entry)) continue; + if (dirty_map && pte_dirty(entry)) { + pgoff_t idx = linear_page_index(vma, address) - + pvmw->pgoff; + + /* The walk only visits pages of this folio */ + VM_WARN_ON_ONCE(idx >= pvmw->nr_pages); + __set_bit(idx, dirty_map); + } + flush_cache_page(vma, address, pte_pfn(entry)); entry = ptep_clear_flush(vma, address, pte); entry = pte_wrprotect(entry); @@ -1155,6 +1170,9 @@ static int page_vma_mkclean_one(struct page_vma_mapped_walk *pvmw) if (!pmd_dirty(entry) && !pmd_write(entry)) continue; + if (dirty_map && pmd_dirty(entry)) + bitmap_set(dirty_map, 0, pvmw->nr_pages); + flush_cache_range(vma, address, address + HPAGE_PMD_SIZE); entry = pmdp_invalidate(vma, address, pmd); @@ -1181,9 +1199,9 @@ static bool page_mkclean_one(struct folio *folio, struct vm_area_struct *vma, unsigned long address, void *arg) { DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, PVMW_SYNC); - int *cleaned = arg; + struct mkclean_state *state = arg; - *cleaned += page_vma_mkclean_one(&pvmw); + state->cleaned += page_vma_mkclean_one(&pvmw, state->dirty_map); return true; } @@ -1196,12 +1214,23 @@ static bool invalid_mkclean_vma(struct vm_area_struct *vma, void *arg) return true; } -int folio_mkclean(struct folio *folio) +/** + * folio_mkclean_dirtymap - Write-protect a folio and report what was dirty. + * @folio: The folio to clean. + * @dirty_map: Bitmap of at least folio_nr_pages(@folio) bits, or NULL. + * + * Write-protects and cleans every mapping of @folio. With @dirty_map, sets a + * bit for each page whose entry was dirty; a PMD-mapped folio has one dirty + * bit for all of it, so every page is reported. + * + * Return: the number of page table entries cleaned. + */ +int folio_mkclean_dirtymap(struct folio *folio, unsigned long *dirty_map) { - int cleaned = 0; + struct mkclean_state state = { .dirty_map = dirty_map }; struct address_space *mapping; struct rmap_walk_control rwc = { - .arg = (void *)&cleaned, + .arg = (void *)&state, .rmap_one = page_mkclean_one, .invalid_vma = invalid_mkclean_vma, }; @@ -1217,7 +1246,12 @@ int folio_mkclean(struct folio *folio) rmap_walk(folio, &rwc); - return cleaned; + return state.cleaned; +} + +int folio_mkclean(struct folio *folio) +{ + return folio_mkclean_dirtymap(folio, NULL); } EXPORT_SYMBOL_GPL(folio_mkclean); @@ -1241,7 +1275,7 @@ static bool mapping_wrprotect_range_one(struct folio *folio, .flags = PVMW_SYNC, }; - state->cleaned += page_vma_mkclean_one(&pvmw); + state->cleaned += page_vma_mkclean_one(&pvmw, NULL); return true; } @@ -1324,7 +1358,7 @@ int pfn_mkclean_range(unsigned long pfn, unsigned long nr_pages, pgoff_t pgoff, pvmw.address = vma_address(vma, pgoff, nr_pages); VM_BUG_ON_VMA(pvmw.address == -EFAULT, vma); - return page_vma_mkclean_one(&pvmw); + return page_vma_mkclean_one(&pvmw, NULL); } static void __folio_mod_stat(struct folio *folio, int nr, int nr_pmdmapped) -- 2.54.0