[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <e06338f2c4aad92a6994a868483f9dcc17f84c5a.1747264138.git.ackerleytng@google.com>
Date: Wed, 14 May 2025 16:42:23 -0700
From: Ackerley Tng <ackerleytng@...gle.com>
To: kvm@...r.kernel.org, linux-mm@...ck.org, linux-kernel@...r.kernel.org,
x86@...nel.org, linux-fsdevel@...r.kernel.org
Cc: ackerleytng@...gle.com, aik@....com, ajones@...tanamicro.com,
akpm@...ux-foundation.org, amoorthy@...gle.com, anthony.yznaga@...cle.com,
anup@...infault.org, aou@...s.berkeley.edu, bfoster@...hat.com,
binbin.wu@...ux.intel.com, brauner@...nel.org, catalin.marinas@....com,
chao.p.peng@...el.com, chenhuacai@...nel.org, dave.hansen@...el.com,
david@...hat.com, dmatlack@...gle.com, dwmw@...zon.co.uk,
erdemaktas@...gle.com, fan.du@...el.com, fvdl@...gle.com, graf@...zon.com,
haibo1.xu@...el.com, hch@...radead.org, hughd@...gle.com, ira.weiny@...el.com,
isaku.yamahata@...el.com, jack@...e.cz, james.morse@....com,
jarkko@...nel.org, jgg@...pe.ca, jgowans@...zon.com, jhubbard@...dia.com,
jroedel@...e.de, jthoughton@...gle.com, jun.miao@...el.com,
kai.huang@...el.com, keirf@...gle.com, kent.overstreet@...ux.dev,
kirill.shutemov@...el.com, liam.merwick@...cle.com,
maciej.wieczor-retman@...el.com, mail@...iej.szmigiero.name, maz@...nel.org,
mic@...ikod.net, michael.roth@....com, mpe@...erman.id.au,
muchun.song@...ux.dev, nikunj@....com, nsaenz@...zon.es,
oliver.upton@...ux.dev, palmer@...belt.com, pankaj.gupta@....com,
paul.walmsley@...ive.com, pbonzini@...hat.com, pdurrant@...zon.co.uk,
peterx@...hat.com, pgonda@...gle.com, pvorel@...e.cz, qperret@...gle.com,
quic_cvanscha@...cinc.com, quic_eberman@...cinc.com,
quic_mnalajal@...cinc.com, quic_pderrin@...cinc.com, quic_pheragu@...cinc.com,
quic_svaddagi@...cinc.com, quic_tsoni@...cinc.com, richard.weiyang@...il.com,
rick.p.edgecombe@...el.com, rientjes@...gle.com, roypat@...zon.co.uk,
rppt@...nel.org, seanjc@...gle.com, shuah@...nel.org, steven.price@....com,
steven.sistare@...cle.com, suzuki.poulose@....com, tabba@...gle.com,
thomas.lendacky@....com, usama.arif@...edance.com, vannapurve@...gle.com,
vbabka@...e.cz, viro@...iv.linux.org.uk, vkuznets@...hat.com,
wei.w.wang@...el.com, will@...nel.org, willy@...radead.org,
xiaoyao.li@...el.com, yan.y.zhao@...el.com, yilun.xu@...el.com,
yuzenghui@...wei.com, zhiquan1.li@...el.com
Subject: [RFC PATCH v2 44/51] KVM: selftests: Test truncation paths of guest_memfd
When guest_memfd folios are truncated, if pages are split, they have
to be merged.
For truncations, userspace will get an error if there are unexpected
refcounts on the folios.
For truncation on closing, kernel will handle the merging even if
there are unexpected refcounts on the folios.
This patch tests the above two scenarios.
Change-Id: I0f0c619763f575605fab8b3c453858960e43ed71
Signed-off-by: Ackerley Tng <ackerleytng@...gle.com>
---
.../kvm/guest_memfd_conversions_test.c | 95 +++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/tools/testing/selftests/kvm/guest_memfd_conversions_test.c b/tools/testing/selftests/kvm/guest_memfd_conversions_test.c
index 22126454fd6b..435f91424d5f 100644
--- a/tools/testing/selftests/kvm/guest_memfd_conversions_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_conversions_test.c
@@ -4,6 +4,7 @@
*
* Copyright (c) 2024, Google LLC.
*/
+#include <linux/guestmem.h>
#include <linux/kvm.h>
#include <linux/sizes.h>
#include <stdio.h>
@@ -580,6 +581,97 @@ static void test_fault_type_independent_of_mem_attributes(size_t test_page_size)
cleanup_test(test_page_size, vm, guest_memfd, mem);
}
+static void test_truncate_shared_while_pinned(size_t test_page_size)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ int guest_memfd;
+ char *mem;
+ int ret;
+
+ vm = setup_test(test_page_size, /*init_private=*/false, &vcpu,
+ &guest_memfd, &mem);
+
+ ret = fallocate(guest_memfd, FALLOC_FL_KEEP_SIZE, 0, test_page_size);
+ TEST_ASSERT(!ret, "fallocate should have succeeded");
+
+ pin_pages(mem, test_page_size);
+
+ ret = fallocate(guest_memfd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+ 0, test_page_size);
+ if (test_page_size == PAGE_SIZE) {
+ TEST_ASSERT(!ret, "truncate should have succeeded since there is no need to merge");
+ } else {
+ TEST_ASSERT(ret, "truncate should have failed since pages are pinned");
+ TEST_ASSERT_EQ(errno, EAGAIN);
+ }
+
+ unpin_pages();
+
+ ret = fallocate(guest_memfd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+ 0, test_page_size);
+ TEST_ASSERT(!ret, "truncate should succeed now that pages are unpinned");
+
+ cleanup_test(test_page_size, vm, guest_memfd, mem);
+}
+
+static void test_truncate_private(size_t test_page_size)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ int guest_memfd;
+ char *mem;
+ int ret;
+
+ vm = setup_test(test_page_size, /*init_private=*/true, &vcpu,
+ &guest_memfd, &mem);
+
+ ret = fallocate(guest_memfd, FALLOC_FL_KEEP_SIZE, 0, test_page_size);
+ TEST_ASSERT(!ret, "fallocate should have succeeded");
+
+ ret = fallocate(guest_memfd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+ 0, test_page_size);
+ TEST_ASSERT(!ret, "truncate should have succeeded since there is no need to merge");
+
+ cleanup_test(test_page_size, vm, guest_memfd, mem);
+}
+
+static void __test_close_with_pinning(size_t test_page_size, bool init_private)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ int guest_memfd;
+ char *mem;
+ int ret;
+
+ vm = setup_test(test_page_size, init_private, &vcpu, &guest_memfd, &mem);
+
+ ret = fallocate(guest_memfd, FALLOC_FL_KEEP_SIZE, 0, test_page_size);
+ TEST_ASSERT(!ret, "fallocate should have succeeded");
+
+ if (!init_private)
+ pin_pages(mem, test_page_size);
+
+ cleanup_test(test_page_size, vm, guest_memfd, mem);
+
+ if (!init_private)
+ unpin_pages();
+
+ /*
+ * Test this with ./guest_memfd_wrap_test_check_hugetlb_reporting.sh to
+ * check that the HugeTLB page got merged and returned to HugeTLB.
+ *
+ * Sleep here to give kernel worker time to do the merge and return.
+ */
+ sleep(1);
+}
+
+static void test_close_with_pinning(size_t test_page_size)
+{
+ __test_close_with_pinning(test_page_size, true);
+ __test_close_with_pinning(test_page_size, false);
+}
+
static void test_with_size(size_t test_page_size)
{
test_sharing(test_page_size);
@@ -590,6 +682,9 @@ static void test_with_size(size_t test_page_size)
test_truncate_should_not_change_mappability(test_page_size);
test_conversions_should_fail_if_memory_has_elevated_refcount(test_page_size);
test_fault_type_independent_of_mem_attributes(test_page_size);
+ test_truncate_shared_while_pinned(test_page_size);
+ test_truncate_private(test_page_size);
+ test_close_with_pinning(test_page_size);
}
int main(int argc, char *argv[])
--
2.49.0.1045.g170613ef41-goog
Powered by blists - more mailing lists