From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (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 811EB158538 for ; Fri, 5 Dec 2025 23:17:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764976662; cv=none; b=G67WbJhlWJWw/sJdht0WMg9IEpZNaGHm1+HSj6BOV2SAhitsBuzznHcU/KWNOr9oYWyrYxn7LIr31kMORiCRDt14ry3Rcfi31iWYVW3MOd3gnogvMSweZ/JsrZPn96XdDb7uRIN+PRCMNZE7NlREa331PJg2b6bZMYs/ohJzu+g= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764976662; c=relaxed/simple; bh=nbdQOSMmcL5kIca5xPyt9qSxOnmVttT74rIBXPZxC2s=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=bQkPiu96MJQvCfAGClUgho2+qqM3N3aJB9j7199XkaMWHvwt09KEsNwxE+JJ8URJ+qFyQzzoX0Ng9/d15yW0Fc48ucUmb3uwhFb7A8ZTlrTT151+3j3EXTQ6ZyuNgdifLKeJUekZYjKyxWgTnqy1JF85sw3Q5Wrdl3pgiW/8VY0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=DlnthX6y; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="DlnthX6y" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=7V8zRztr79VObCMoptEPLJbZbtmNllOgLuMS+604U+Y=; b=DlnthX6yrqH/po71lwl4df6RLL 9LcaJDEzxn7KsxL5J/GHmp6EPweTB9P9PHYfMAQBiKmKmSoi1iTAqnpK7ZI9Z/oFrNZvzXZXhoSYW 2B0e7+Qg1f8j/LgOEUhoi6rmEjvnkHD8ez4BenGPlXl1g9w9KSpvZuTBAnWj1S0pbYyxGv4ieIfQn mP2k0pR6aHiTR+qL3kuOnroMl8q/EwyXLgnXWDolUaCBIjvibXfmzu3mm5UUHREgf2AkTIg4pE4Vm u7MIe7uCXOoTYpKUUfxrjM2LAkxAaqv5809PfXb+b/TLEJdS1adCEKXOmj98sikKbATm4M2v5yKhk aHMj2rDg==; Received: from 186-249-144-101.shared.desktop.com.br ([186.249.144.101] helo=t470) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vRf3H-009H1j-46; Sat, 06 Dec 2025 00:17:27 +0100 From: Mauricio Faria de Oliveira To: Andrew Morton , David Hildenbrand Cc: Lorenzo Stoakes , Michal Hocko , Vlastimil Babka , Oscar Salvador , linux-mm@kvack.org, linux-kernel@vger.kernel.org, kernel-dev@igalia.com Subject: [PATCH RFC 0/9] mm/page_owner: add support for pages in swap space Date: Fri, 5 Dec 2025 20:17:12 -0300 Message-ID: <20251205231721.104505-1-mfo@igalia.com> X-Mailer: git-send-email 2.51.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-Transfer-Encoding: 8bit This series extends page_owner to track the allocation stack trace of pages in swap space as well (not just pages in memory), and maintain it over swap-out and swap-in (no longer lost/overriden at swap-out/swap-in). It stores a copy of the allocation stack trace (plus some other fields) at swap-out and loads it back at swap-in, with an xarray by swp_entry_t and the swap hooks used for CONFIG_ARM64_MTE (memory tagging extension). The refcounts of the allocation stack traces (i.e., number of base pages) for the initial allocation and the allocation at swap-in are fixed-up at swap-out and swap-in, to maintain the refcount on the initial allocation (for 'nr_base_pages' in '/sys/kernel/debug/page_owner_stacks/show_*'). The series is split into more, small patches on purpose, just for review (some patches fail to build with '-Werror=unused-function'). - Patches 1-4 add infrastructure. - Patch 5 adds the key functionality. - Patches 6-7 add reporting. - Patches 8-9 add hooks for this. It is basically tested (below); hopefully sufficient for an RFC in order to get comments on the idea, approach, design, problems and suggestions. For future revisions: add pr_debug() and more error messages, and write Documentation; maybe rename functions with 'spo' prefix (swap page_owner). (I'll check a FIXME on the refcount fix-up due to an occasional WARN+OOPS mostly on shutdown; but that is just for 'nr_base_pages', without impact to the key functionality, and can be just commented out.) Thanks, Mauricio # Testing ## Configuration - next-20251205 - x86_64_defconfig - CONFIG_PAGE_OWNER=n / CONFIG_SWAP_PAGE_OWNER=n (build-only) - CONFIG_PAGE_OWNER=y / CONFIG_SWAP_PAGE_OWNER=n (build-only) - CONFIG_PAGE_OWNER=y / CONFIG_SWAP_PAGE_OWNER=y (build/tests) ## Format - Existing file (page_owner) # cat /sys/kernel/debug/page_owner ... Page allocated via order 0, mask 0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), pid 231, tgid 231 (dd), ts 13255570102 ns PFN 0xa35b type Movable Block 81 type Movable Flags 0x10000000002003c(referenced|uptodate|dirty|lru|swapbacked|node=0|zone=1) get_page_from_freelist+0x13b9/0x1530 ... entry_SYSCALL_64_after_hwframe+0x77/0x7f Charged to memcg session-1.scope ... - New file (swap_page_owner) # cat /sys/kernel/debug/swap_page_owner # new ... Page allocated via pid 231, tgid 231 (dd), ts 13255313898 ns SWP entry 0x2e get_page_from_freelist+0x13b9/0x1530 ... entry_SYSCALL_64_after_hwframe+0x77/0x7f ... - Existing file (page_owner), when modified with '(swapped)$' # cat /sys/kernel/debug/page_owner ... Page allocated via order 0, mask 0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), pid 231, tgid 231 (dd), ts 13255427451 ns (swapped) ## Environment: # uname -r 6.18.0-next-20251205-00009-g8042ea636379 # mount | grep /tmpfs none on /tmpfs type tmpfs (rw,relatime,size=1048576k) none on /tmpfs-noswap type tmpfs (rw,relatime,size=1048576k,noswap) ## Before (page_owner without swap support) # grep -o 'page_owner=.*' /proc/cmdline page_owner=on - Mem/Swap usage per page_owner (swap is not reported) # free -m total used free shared buff/cache available Mem: 458 68 367 0 33 389 Swap: 1023 0 1023 # echo $((458-367)) # total - free 91 # cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 91.2578 MiB # cat /sys/kernel/debug/swap_page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=1 } END { print PAGES*4096/1024^2 " MiB" }' cat: /sys/kernel/debug/swap_page_owner: Invalid argument 0 MiB - Use 256 MiB of pages allocated by 'dd' (compare with pages allocated by 'cat') # dd if=/dev/zero of=/tmpfs/file status=none bs=1M count=256 # COMM=dd; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 256.559 MiB # COMM=cat; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 0.464844 MiB - Move that 256 MiB of pages from memory to swap (use 'DD' to differentiate from 'dd's memory) # ln -sf $(which dd) ./DD # ./DD if=/dev/zero of=/tmpfs-noswap/file status=none bs=1M count=384 # free -m total used free shared buff/cache available Mem: 458 445 6 388 405 12 Swap: 1023 264 759 - Mem/Swap usage per page_owner (swap is not reported) # echo $((458-6)) # total - free 452 # cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 450.445 MiB # cat /sys/kernel/debug/swap_page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=1 } END { print PAGES*4096/1024^2 " MiB" }' cat: /sys/kernel/debug/swap_page_owner: Invalid argument 0 MiB - Move that 256 MiB of pages back from swap to memory # rm /tmpfs-noswap/file # cat /tmpfs/file >/dev/null - The 256 MiB of pages is _now_ allocated by 'cat' (instead of 'dd') # COMM=dd; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 1.66016 MiB # COMM=cat; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 258.309 MiB ## After (page_owner with swap support) # grep -o 'page_owner=.*' /proc/cmdline page_owner=on,swap - Mem/Swap usage per page_owner (swap is reported now) # free -m total used free shared buff/cache available Mem: 458 68 360 0 40 389 Swap: 1023 0 1023 # echo $((458-360)) # total - free 98 # cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 97 MiB # cat /sys/kernel/debug/swap_page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=1 } END { print PAGES*4096/1024^2 " MiB" }' 0 MiB - Use 256 MiB of pages allocated by 'dd' (compare with pages allocated by 'cat') # dd if=/dev/zero of=/tmpfs/file status=none bs=1M count=256 # COMM=dd; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 256.504 MiB # COMM=cat; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 0.175781 MiB - Move that 256 MiB of pages from memory to swap (use 'DD' to differentiate from 'dd's memory) # ln -sf $(which dd) ./DD # ./DD if=/dev/zero of=/tmpfs-noswap/file status=none bs=1M count=384 - Mem/Swap usage per page_owner (swap is reported now) # free -m total used free shared buff/cache available Mem: 458 435 6 384 412 22 Swap: 1023 278 745 # echo $((458-6)) # total - free 452 # cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 449.258 MiB # cat /sys/kernel/debug/swap_page_owner | awk -F '[ ,]' '/^Page allocated/ { PAGES+=1 } END { print PAGES*4096/1024^2 " MiB" }' 278.793 MiB - Move that 256 MiB of pages back from swap to memory # rm /tmpfs-noswap/file # cat /tmpfs/file >/dev/null - The 256 MiB of pages is _still_ allocated by 'dd' (instead of 'cat' as above) # COMM=dd; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 256.445 MiB # COMM=cat; cat /sys/kernel/debug/page_owner | awk -F '[ ,]' '/^Page allocated .* \('${COMM}'\)/ { PAGES+=2^$5 } END { print PAGES*4096/1024^2 " MiB" }' 7.80859 MiB Mauricio Faria de Oliveira (9): mm: add config option SWAP_PAGE_OWNER mm/page_owner: add parameter option 'page_owner=on,swap' mm/page_owner: add 'struct swap_page_owner' and helpers mm/page_owner: add 'xarray swap_page_owners' and helpers mm/page_owner: add swap hooks mm/page_owner: report '(swapped)' pages in debugfs file 'page_owner' mm/page_owner: add debugfs file 'swap_page_owner' mm: call arch-specific swap hooks from generic swap hooks mm: call page_owner swap hooks from generic swap hooks include/linux/page_owner.h | 50 ++++++ include/linux/pgtable.h | 30 ++++ mm/Kconfig.debug | 9 + mm/memory.c | 2 +- mm/page_io.c | 2 +- mm/page_owner.c | 338 ++++++++++++++++++++++++++++++++++++- mm/shmem.c | 2 +- mm/swapfile.c | 6 +- 8 files changed, 427 insertions(+), 12 deletions(-) -- 2.51.0