From: Chris Down <chris@chrisdown.name>
To: Pasha Tatashin <pasha.tatashin@soleen.com>,
Mike Rapoport <rppt@kernel.org>,
Pratyush Yadav <pratyush@kernel.org>
Cc: Alexander Graf <graf@amazon.com>,
Baoquan He <baoquan.he@linux.dev>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
kexec@lists.infradead.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kselftest@vger.kernel.org, kernel-team@meta.com
Subject: [PATCH 7/9] kho: Report how much handover memory is preserved and restored
Date: Tue, 10 Nov 2026 23:53:35 -0800 [thread overview]
Message-ID: <920192d01c6534b5754648e12840f73cdcfa73de.1794383544.git.chris@chrisdown.name> (raw)
In-Reply-To: <cover.1794383544.git.chris@chrisdown.name>
Most memory the previous kernel preserved stays reserved until its user
restores it through KHO, either to use it again or to free it. If
nothing does, it stays reserved for as long as the kernel runs. On a
hypervisor host that can be gigabytes, but amusingly nothing really
shows it reliably. The host simply has less memory than it should, which
is not exactly obvious.
All preserved memory is reserved in kho_preserved_memory_reserve(), and
everything restored through KHO goes through kho_restore_page(), so KHO
can count both easily. Let's add preserved_size and restored_size, in
bytes, to /sys/kernel/kexec/kho_incoming/.
For example, after a live update preserving a 64 MiB memfd:
preserved_size restored_size
before retrieval 67403776 8192
after retrieval 67403776 67395584
The 8 KiB left are the incoming KHO FDT and LUO's FLB header.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
.../ABI/testing/sysfs-kernel-kexec-kdump | 10 ++++++++
Documentation/admin-guide/mm/kho.rst | 3 +++
kernel/liveupdate/kexec_handover.c | 23 +++++++++++++++++++
3 files changed, 36 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-kernel-kexec-kdump b/Documentation/ABI/testing/sysfs-kernel-kexec-kdump
index 5636cd060cb2..2b9f9917d2d4 100644
--- a/Documentation/ABI/testing/sysfs-kernel-kexec-kdump
+++ b/Documentation/ABI/testing/sysfs-kernel-kexec-kdump
@@ -79,3 +79,13 @@ Description: read only
the walk of its preserved memory map.
"failed" The kernel rejected the handover.
User: system monitoring
+
+What: /sys/kernel/kexec/kho_incoming/preserved_size
+What: /sys/kernel/kexec/kho_incoming/restored_size
+Date: Nov 2026
+Contact: kexec@lists.infradead.org
+Description: read only
+ Bytes preserved by the previous kernel and bytes restored
+ through KHO, respectively. Both are 0 unless the incoming
+ state is "revived".
+User: system monitoring
diff --git a/Documentation/admin-guide/mm/kho.rst b/Documentation/admin-guide/mm/kho.rst
index 9d74d4ce18b5..37a62daa7622 100644
--- a/Documentation/admin-guide/mm/kho.rst
+++ b/Documentation/admin-guide/mm/kho.rst
@@ -91,6 +91,9 @@ sysfs Interfaces
``/sys/kernel/kexec/kho_incoming/state``
Status of the incoming KHO handover.
+``/sys/kernel/kexec/kho_incoming/preserved_size`` and ``restored_size``
+ Bytes preserved by the previous kernel and bytes restored through KHO.
+
See Documentation/ABI/testing/sysfs-kernel-kexec-kdump for the sysfs ABI.
debugfs Interfaces
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index dfd6fa7e4a71..fe6b66270124 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -110,6 +110,8 @@ struct kho_in {
char previous_release[__NEW_UTS_LEN + 1];
u32 kexec_count;
enum kho_incoming_state state;
+ unsigned long preserved_pages;
+ atomic_long_t restored_pages;
struct kho_debugfs dbg;
struct kho_radix_tree radix_tree;
};
@@ -552,6 +554,7 @@ static struct page *kho_restore_page(phys_addr_t phys, bool is_folio,
kho_init_pages(page, nr_pages);
adjust_managed_page_count(page, nr_pages);
+ atomic_long_add(nr_pages, &kho_in.restored_pages);
return page;
}
@@ -643,6 +646,7 @@ static int __init kho_preserved_memory_reserve(unsigned long key, void *data)
info.magic = KHO_PAGE_MAGIC;
info.order = order;
page->private = info.page_private;
+ kho_in.preserved_pages += 1UL << order;
return 0;
}
@@ -978,8 +982,26 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
}
static struct kobj_attribute state_attr = __ATTR_RO(state);
+static ssize_t preserved_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%llu\n", (u64)kho_in.preserved_pages << PAGE_SHIFT);
+}
+static struct kobj_attribute preserved_size_attr = __ATTR_RO(preserved_size);
+
+static ssize_t restored_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ u64 pages = atomic_long_read(&kho_in.restored_pages);
+
+ return sysfs_emit(buf, "%llu\n", pages << PAGE_SHIFT);
+}
+static struct kobj_attribute restored_size_attr = __ATTR_RO(restored_size);
+
static struct attribute *kho_incoming_attrs[] = {
&state_attr.attr,
+ &preserved_size_attr.attr,
+ &restored_size_attr.attr,
NULL
};
@@ -1785,6 +1807,7 @@ static void __init kho_mem_retrieve(void)
kho_in.fdt_phys = 0;
kho_in.radix_tree.root = NULL;
kho_in.state = KHO_INCOMING_FAILED;
+ kho_in.preserved_pages = 0;
}
static __init int kho_out_fdt_setup(void)
--
2.54.0
next prev parent reply other threads:[~2026-11-11 7:53 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 7:52 [PATCH 0/9] kho, liveupdate: KHO/LUO observability Chris Down
2026-11-11 7:52 ` [PATCH 1/9] kho: Reclaim the metadata page left reserved after kexec Chris Down
2026-11-11 7:53 ` [PATCH 2/9] kho: Make bootmem reservations visible to fleet monitoring Chris Down
2026-11-11 7:53 ` [PATCH 3/9] liveupdate: Make failed retrieves distinguishable from dropped files Chris Down
2026-11-11 7:53 ` [PATCH 4/9] selftests/liveupdate: Catch incorrect file accounting across kexec Chris Down
2026-11-11 7:53 ` [PATCH 5/9] selftests/kho: Catch missing or zero bootmem reports before kexec Chris Down
2026-11-11 7:53 ` [PATCH 6/9] kho: Expose rejected handovers that look like cold boots Chris Down
2026-11-11 7:53 ` Chris Down [this message]
2026-11-11 7:53 ` [PATCH 8/9] liveupdate: Expose the sequence number for consecutive live updates Chris Down
2026-11-11 7:53 ` [PATCH 9/9] selftests/liveupdate: Check handover revival, sequence and memory stats Chris Down
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=920192d01c6534b5754648e12840f73cdcfa73de.1794383544.git.chris@chrisdown.name \
--to=chris@chrisdown.name \
--cc=baoquan.he@linux.dev \
--cc=corbet@lwn.net \
--cc=graf@amazon.com \
--cc=kernel-team@meta.com \
--cc=kexec@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=pasha.tatashin@soleen.com \
--cc=pratyush@kernel.org \
--cc=rppt@kernel.org \
--cc=skhan@linuxfoundation.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®