From patchwork Sat Jan 18 23:15:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaqi Yan X-Patchwork-Id: 13944262 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]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07C95C02187 for ; Sat, 18 Jan 2025 23:16:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8A5E96B0088; Sat, 18 Jan 2025 18:16:27 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 82F6D6B0089; Sat, 18 Jan 2025 18:16:27 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 682096B008A; Sat, 18 Jan 2025 18:16:27 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 4B0496B0088 for ; Sat, 18 Jan 2025 18:16:27 -0500 (EST) Received: from smtpin14.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id F004F1403E9 for ; Sat, 18 Jan 2025 23:16:26 +0000 (UTC) X-FDA: 83022133572.14.453BE19 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) by imf20.hostedemail.com (Postfix) with ESMTP id 090B51C0009 for ; Sat, 18 Jan 2025 23:16:24 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=vq1fxSdR; spf=pass (imf20.hostedemail.com: domain of 3RzaMZwgKCCgNMEUMcERKSSKPI.GSQPMRYb-QQOZEGO.SVK@flex--jiaqiyan.bounces.google.com designates 209.85.216.74 as permitted sender) smtp.mailfrom=3RzaMZwgKCCgNMEUMcERKSSKPI.GSQPMRYb-QQOZEGO.SVK@flex--jiaqiyan.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1737242185; 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-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=YN6TmY/NDY3/qLUZOajjmh5DrDHEICthyIauzWOR8ZQ=; b=6Ot0q4C2RgwNnptZPtf91NyrPYzx2B3GjXp5/yHfDQ9DJI/u364Dopfco1O6guOBQsZS38 BbQXul1SphFNK2brOTDiiNDXk/QegYTJm/QRJf51qtlPk/J8kRKLLLcT/FYWO7KR0eutU7 CcE7j+4w4OgFCPmLv+abFqnj14a0dNI= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1737242185; a=rsa-sha256; cv=none; b=OhDUnHdaO0X3ODw/LAv5ZUqU537gHAjDeuBAACJps2s5A7/2/tb4FP7y2QGnFe4xsK0NJq Z1BDfZqfV1PmRRc7WeSwXyIYt/3n5sBydojg8agOF1jLzZ9geV5oUkxpUe+abmBCN/1g8O ElLiggo+p+UL5MSLrRMhDg97aePbJLM= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=vq1fxSdR; spf=pass (imf20.hostedemail.com: domain of 3RzaMZwgKCCgNMEUMcERKSSKPI.GSQPMRYb-QQOZEGO.SVK@flex--jiaqiyan.bounces.google.com designates 209.85.216.74 as permitted sender) smtp.mailfrom=3RzaMZwgKCCgNMEUMcERKSSKPI.GSQPMRYb-QQOZEGO.SVK@flex--jiaqiyan.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2ef775ec883so5980403a91.1 for ; Sat, 18 Jan 2025 15:16:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1737242184; x=1737846984; darn=kvack.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=YN6TmY/NDY3/qLUZOajjmh5DrDHEICthyIauzWOR8ZQ=; b=vq1fxSdRC8HKXgRM9nRNN+IlnUyRE3jQhfBriaEVjzV0bbTG/SgJxGWU/KRZpzsVUT I0c20DPbEifM7S4mwCVJiBqVQCrwrE6oCxECvFR8dVKuCGb3HjLRzI1s+i1EWbXyaxPJ 5bEglEjclIEBB/Yk2XcD3guQIM6sEh3ZWpjao+8cxiaV+uXfsfNFYFIzRAIMAizo2efa mwjihjspdLWGcXmaMb3WzszVm+EWxZv7iqiS8QW0A7vQ3J3QFLDAbYBMbMPs9DN++oYi XPwc3QByCQ5C3t4I9E0EgN/kDm4LDsJi2FCXlTmEJYnYEhwhMiE970rqdk+jg6thdWUx /FKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737242184; x=1737846984; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YN6TmY/NDY3/qLUZOajjmh5DrDHEICthyIauzWOR8ZQ=; b=b5+GLSoNhdOq06wFfYGycnrlj8iXnV5/lUM6F8FZ8Azz/O/pqHw7QA5LvhOEWLlfo9 Cc8OEvoqFJML/1lWRoBP+Qnn6bTQ11sazRDje8uYRWgIWkz+E1BhvQncudf+pDPeLn8z NiA7KLGo5tsrkTTGGz5ISug3POPstGt/XTJWrQCAJ0mIz7esx+Epl5NSnt1xe2dQHTu/ OiHBEafFX1kpwb+4T9Y9S3r6LcF2BZ/OXFYAUO2MgyYw2I0bQS82pYPRbvaYkLWPAmqv WtPQRPNE+FQZs+YTs1Hh5N6EzZ/QacxQSsWcA9G5aLQHG29a9mK3umAk6Gz/VwfNo07V c3oQ== X-Forwarded-Encrypted: i=1; AJvYcCXRBQWO8ElizT8RwyRSy/QYk6FeR1PjI5da4aLmqRfdpvryHaRaK2tSGweL117EqTbXOMT3HbiXWw==@kvack.org X-Gm-Message-State: AOJu0YzVs/Nj1oIa2u0EBODYPWnl+CU2FgELAngjQEOlEhgFKDbmbAjX OW0uBl4iE2crjOdms3Y4S4OY8ws5skAMUfQmjdtxGPPH567apsgQUU+aaepdYp76NRDjrLI4Sh2 JVz0EoG+/pw== X-Google-Smtp-Source: AGHT+IFLLkqbQaii6vgpMggmn1nuWWFx29WluNp02IqS6MEf1N7eQhiWvEopoT1MpbZfEYAZ5yHYOwd2a2T7AQ== X-Received: from pjzm19.prod.google.com ([2002:a17:90b:693:b0:2d8:8d32:2ea3]) (user=jiaqiyan job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:540b:b0:2ee:ba0c:1726 with SMTP id 98e67ed59e1d1-2f782d9a1c9mr9872038a91.34.1737242183861; Sat, 18 Jan 2025 15:16:23 -0800 (PST) Date: Sat, 18 Jan 2025 23:15:48 +0000 In-Reply-To: <20250118231549.1652825-1-jiaqiyan@google.com> Mime-Version: 1.0 References: <20250118231549.1652825-1-jiaqiyan@google.com> X-Mailer: git-send-email 2.48.0.rc2.279.g1de40edade-goog Message-ID: <20250118231549.1652825-3-jiaqiyan@google.com> Subject: [RFC PATCH v1 2/3] selftests/mm: test userspace MFR for HugeTLB 1G hugepage From: Jiaqi Yan To: nao.horiguchi@gmail.com, linmiaohe@huawei.com Cc: tony.luck@intel.com, wangkefeng.wang@huawei.com, willy@infradead.org, jane.chu@oracle.com, akpm@linux-foundation.org, osalvador@suse.de, rientjes@google.com, duenwen@google.com, jthoughton@google.com, jgg@nvidia.com, ankita@nvidia.com, peterx@redhat.com, sidhartha.kumar@oracle.com, david@redhat.com, dave.hansen@linux.intel.com, muchun.song@linux.dev, linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, Jiaqi Yan X-Rspamd-Queue-Id: 090B51C0009 X-Stat-Signature: mc4ic6wqauazykwa4s1md6d6aydgd6a4 X-Rspam-User: X-Rspamd-Server: rspam12 X-HE-Tag: 1737242184-703007 X-HE-Meta: U2FsdGVkX1+DB6WDcTGipIUwgIBA/Ys57xVD6MlbuN8/akwrSlmOkZICaT55qHemCtbN6kxEfngkwmThSrHc1UM/TJ6l/SKk1NtYZRnLj55IxmpW5asEwbDDO6hML9JtCDnkA9fYyQaASYXCA01E0gcwRumZf+MZWaNLeVbP0P6P93wf4vMWmv3BBNH7tGpM4ki000cGbyqZ1h/wzFPSWo/m+hs6bfLl4njjGJhqLJgDZ4fL4ZFiiSr8nT1CqSkkjvLjRnTinPLjK+P4ygSYcO8NIc8xJ1GbxcK3+b1kBzkXK3l334XgPwd6AIn/2JMQ6BquP4YPYbnMxcVegDrFP4XaR/EjwaH7s+AAmM3AbH1LY0XlXsF43QytNbpLxyrWw9eAlEeBNYFf/Y9+pWr7oLShPPY5ifofJPRJTrFIMtzeoDnyPJi2qOCDo26ISv4alkKq5wcYXZ1q8hy6xt8eGnEwr2viHXWvgubCJGWlvcX1/XfWnQ6ANnk9Q0ZNT55DUucn12qTDxsYUUShuDjACjjVsV/P5AziSQ5kOrAtnokM5meCw/Bf1cJw8/0AZwhYl8m+9T9KC/gdrW3s4ogrRX1uYp9pl2cCpXsA825LT9xmMVuyp96OjiM3Oy6EYcVJy9nBB5ttzOyPwBsgv4QCN78z/wvNPqixqPW5VEuNCSzVNUoFHO6l2bTM6wAQdXWbKqShnINjW8AnKW/jJWCQ6UD+SPUNN3GBYfByEaOd2CTioKG0xK6RRCEVPjal+6xm6LVQ/xot4ym5Me3OK4s/048vEgOyxXa+GakiYvKU02v1gFEOqbWv8jeIddgcG3rK0nRLa2oynz+wCHTpj6P/mgcT2cs/TLFU/KpQJiK7vZxYgUtQh0i0RvhQFMItbAX9QjvGR+oILojeN2Y9rZ5+80BoVWEl5k+W5hwkzSNFGNNSJE7xv/2gsbYbcZ+t9Ye+/NDX7Xdd7USrScSjQ9G yyQEW7Lx QAivCvWUg0tKmx8MX5e2yZ4nkSCD/e7pNpktJsSzw6PJLrt2uigTUdFQSeYGVCMaDYBjqYRB9eAu8gN2QnqI8x1Wdmz0MmPqddrzj7ryslrI3gfB1BIrItExx8Jc65WpsgIR4dTZ+4lwFJShwuwxarUXkOKmRRZssc7GeldeYmQDPtCQS9x0uIaNkqNeMo8Lu+/yFQ/doKyuYLJq+A00ta0chM/NLFlImya4/WuAMWDGFjc50EIIGIJIwB39QQWtTVSAZUodwSWs+7qLpZwc8QLRkPV+CXLLH/zoD96dIb/fUDPA0K5wtvh7W5R/KOTeuNsO62PFQlv+SteQOO05I6djoMbfsZQaGysigXxA231C95zTiUcXcg2r8rWTksy5hcwvoaK9GMyCOubmwHhho/zNc7OmFEH7SF1Wekgx9nmQ8Wo3mR+zBGv/oT+e8wa3Vyc6PqK4r8+fC641nbT4aT89BJiyrA1G0XNcDWVSqubhuUghMNmcJNguV0aYElx9CntVMcNCaD4BAZnipZK44A9pq46336pdcQ9MrmGGUMntNpOLUpGBfL5Ux+N5olh0/TtK8lrA4ZOW/QKO1aEvm9HLEiKMzx9Sb1mZ7/v17xzETX0kCGVQyH8emJaxbrZoZEPH3 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Tests the userspace memory failure recovery (MFR) policy for HugeTLB 1G hugepage case: 1. Creates a memfd backed by 1G HugeTLB and had MFD_MF_KEEP_UE_MAPPED set. 2. Allocates and maps in a 1G hugepage to the process. 3. Creates sub-threads to MADV_HWPOISON inner addresses of the hugepage. 4. Checks if the process gets correct SIGBUS for each poisoned raw page. 5. Checks if all memory are still accessible and content valid. 6. Checks if the poisoned 1G hugepage is dealt with after memfd released. Signed-off-by: Jiaqi Yan --- tools/testing/selftests/mm/.gitignore | 1 + tools/testing/selftests/mm/Makefile | 1 + tools/testing/selftests/mm/hugetlb-mfr.c | 267 +++++++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100644 tools/testing/selftests/mm/hugetlb-mfr.c diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftests/mm/.gitignore index 121000c28c105..e65a1fa43f868 100644 --- a/tools/testing/selftests/mm/.gitignore +++ b/tools/testing/selftests/mm/.gitignore @@ -5,6 +5,7 @@ hugepage-mremap hugepage-shm hugepage-vmemmap hugetlb-madvise +hugetlb-mfr hugetlb-read-hwpoison hugetlb-soft-offline khugepaged diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index 63ce39d024bb5..171a9e65ed357 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -62,6 +62,7 @@ TEST_GEN_FILES += hmm-tests TEST_GEN_FILES += hugetlb-madvise TEST_GEN_FILES += hugetlb-read-hwpoison TEST_GEN_FILES += hugetlb-soft-offline +TEST_GEN_FILES += hugetlb-mfr TEST_GEN_FILES += hugepage-mmap TEST_GEN_FILES += hugepage-mremap TEST_GEN_FILES += hugepage-shm diff --git a/tools/testing/selftests/mm/hugetlb-mfr.c b/tools/testing/selftests/mm/hugetlb-mfr.c new file mode 100644 index 0000000000000..cb20b81984f5e --- /dev/null +++ b/tools/testing/selftests/mm/hugetlb-mfr.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Tests the userspace memory failure recovery (MFR) policy for HugeTLB 1G + * hugepage case: + * 1. Creates a memfd backed by 1G HugeTLB and MFD_MF_KEEP_UE_MAPPED bit set. + * 2. Allocates and maps a 1G hugepage. + * 3. Creates sub-threads to MADV_HWPOISON inner addresses of the hugepage. + * 4. Checks if the sub-thread get correct SIGBUS for each poisoned raw page. + * 5. Checks if all memory are still accessible and content still valid. + * 6. Checks if the poisoned 1G hugepage is dealt with after memfd released. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../kselftest.h" +#include "vm_util.h" + +#define EPREFIX " !!! " +#define BYTE_LENTH_IN_1G 0x40000000 +#define HUGETLB_FILL 0xab + +static void *sigbus_addr; +static int sigbus_addr_lsb; +static bool expecting_sigbus; +static bool got_sigbus; +static bool was_mceerr; + +static int create_hugetlbfs_file(struct statfs *file_stat) +{ + int fd; + int flags = MFD_HUGETLB | MFD_HUGE_1GB | MFD_MF_KEEP_UE_MAPPED; + + fd = memfd_create("hugetlb_tmp", flags); + if (fd < 0) + ksft_exit_fail_perror("Failed to memfd_create"); + + memset(file_stat, 0, sizeof(*file_stat)); + if (fstatfs(fd, file_stat)) { + close(fd); + ksft_exit_fail_perror("Failed to fstatfs"); + } + if (file_stat->f_type != HUGETLBFS_MAGIC) { + close(fd); + ksft_exit_fail_msg("Not hugetlbfs file"); + } + + ksft_print_msg("Created hugetlb_tmp file\n"); + ksft_print_msg("hugepagesize=%#lx\n", file_stat->f_bsize); + if (file_stat->f_bsize != BYTE_LENTH_IN_1G) + ksft_exit_fail_msg("Hugepage size is not 1G"); + + return fd; +} + +/* + * SIGBUS handler for "do_hwpoison" thread that mapped and MADV_HWPOISON + */ +static void sigbus_handler(int signo, siginfo_t *info, void *context) +{ + if (!expecting_sigbus) + ksft_exit_fail_msg("unexpected sigbus with addr=%p", + info->si_addr); + + got_sigbus = true; + was_mceerr = (info->si_code == BUS_MCEERR_AO || + info->si_code == BUS_MCEERR_AR); + sigbus_addr = info->si_addr; + sigbus_addr_lsb = info->si_addr_lsb; +} + +static void *do_hwpoison(void *hwpoison_addr) +{ + int hwpoison_size = getpagesize(); + + ksft_print_msg("MADV_HWPOISON hwpoison_addr=%p, len=%d\n", + hwpoison_addr, hwpoison_size); + if (madvise(hwpoison_addr, hwpoison_size, MADV_HWPOISON) < 0) + ksft_exit_fail_perror("Failed to MADV_HWPOISON"); + + pthread_exit(NULL); +} + +static void test_hwpoison_multiple_pages(unsigned char *start_addr) +{ + pthread_t pthread; + int ret; + unsigned char *hwpoison_addr; + unsigned long offsets[] = {0x200000, 0x400000, 0x800000}; + + for (size_t i = 0; i < ARRAY_SIZE(offsets); ++i) { + sigbus_addr = (void *)0xBADBADBAD; + sigbus_addr_lsb = 0; + was_mceerr = false; + got_sigbus = false; + expecting_sigbus = true; + hwpoison_addr = start_addr + offsets[i]; + + ret = pthread_create(&pthread, NULL, &do_hwpoison, hwpoison_addr); + if (ret) + ksft_exit_fail_perror("Failed to create hwpoison thread"); + + ksft_print_msg("Created thread to hwpoison and access hwpoison_addr=%p\n", + hwpoison_addr); + + pthread_join(pthread, NULL); + + if (!got_sigbus) + ksft_test_result_fail("Didn't get a SIGBUS\n"); + if (!was_mceerr) + ksft_test_result_fail("Didn't get a BUS_MCEERR_A(R|O)\n"); + if (sigbus_addr != hwpoison_addr) + ksft_test_result_fail("Incorrect address: got=%p, expected=%p\n", + sigbus_addr, hwpoison_addr); + if (sigbus_addr_lsb != pshift()) + ksft_test_result_fail("Incorrect address LSB: got=%d, expected=%d\n", + sigbus_addr_lsb, pshift()); + + ksft_print_msg("Received expected and correct SIGBUS\n"); + } +} + +static int read_nr_hugepages(unsigned long hugepage_size, + unsigned long *nr_hugepages) +{ + char buffer[256] = {0}; + char cmd[256] = {0}; + + sprintf(cmd, "cat /sys/kernel/mm/hugepages/hugepages-%ldkB/nr_hugepages", + hugepage_size); + FILE *cmdfile = popen(cmd, "r"); + + if (cmdfile == NULL) { + ksft_perror(EPREFIX "failed to popen nr_hugepages"); + return -1; + } + + if (!fgets(buffer, sizeof(buffer), cmdfile)) { + ksft_perror(EPREFIX "failed to read nr_hugepages"); + pclose(cmdfile); + return -1; + } + + *nr_hugepages = atoll(buffer); + pclose(cmdfile); + return 0; +} + +/* + * Main thread that drives the test. + */ +static void test_main(int fd, size_t len) +{ + unsigned char *map, *iter; + struct sigaction new, old; + const unsigned long hugepagesize_kb = BYTE_LENTH_IN_1G / 1024; + unsigned long nr_hugepages_before = 0; + unsigned long nr_hugepages_after = 0; + + if (read_nr_hugepages(hugepagesize_kb, &nr_hugepages_before) != 0) { + close(fd); + ksft_exit_fail_msg("Failed to read nr_hugepages\n"); + } + ksft_print_msg("NR hugepages before MADV_HWPOISON is %ld\n", nr_hugepages_before); + + if (ftruncate(fd, len) < 0) + ksft_exit_fail_perror("Failed to ftruncate"); + + ksft_print_msg("Allocated %#lx bytes to HugeTLB file\n", len); + + map = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + ksft_exit_fail_msg("Failed to mmap"); + + ksft_print_msg("Created HugeTLB mapping: %p\n", map); + + memset(map, HUGETLB_FILL, len); + ksft_print_msg("Memset every byte to 0xab\n"); + + new.sa_sigaction = &sigbus_handler; + new.sa_flags = SA_SIGINFO; + if (sigaction(SIGBUS, &new, &old) < 0) + ksft_exit_fail_msg("Failed to setup SIGBUS handler"); + + ksft_print_msg("Setup SIGBUS handler successfully\n"); + + test_hwpoison_multiple_pages(map); + + /* + * Since MADV_HWPOISON doesn't corrupt the memory in hardware, and + * MFD_MF_KEEP_UE_MAPPED keeps the hugepage mapped, every byte should + * remain accessible and hold original data. + */ + expecting_sigbus = false; + for (iter = map; iter < map + len; ++iter) { + if (*iter != HUGETLB_FILL) { + ksft_print_msg("At addr=%p: got=%#x, expected=%#x\n", + iter, *iter, HUGETLB_FILL); + ksft_test_result_fail("Memory content corrupted\n"); + break; + } + } + ksft_print_msg("Memory content all valid\n"); + + if (read_nr_hugepages(hugepagesize_kb, &nr_hugepages_after) != 0) { + close(fd); + ksft_exit_fail_msg("Failed to read nr_hugepages\n"); + } + + /* + * After MADV_HWPOISON, hugepage should still be in HugeTLB pool. + */ + ksft_print_msg("NR hugepages after MADV_HWPOISON is %ld\n", nr_hugepages_after); + if (nr_hugepages_before != nr_hugepages_after) + ksft_test_result_fail("NR hugepages reduced by %ld after MADV_HWPOISON\n", + nr_hugepages_before - nr_hugepages_after); + + /* End of the lifetime of the created HugeTLB memfd. */ + if (ftruncate(fd, 0) < 0) + ksft_exit_fail_perror("Failed to ftruncate to 0"); + munmap(map, len); + close(fd); + + /* + * After freed by userspace, MADV_HWPOISON-ed hugepage should be + * dissolved into raw pages and removed from HugeTLB pool. + */ + if (read_nr_hugepages(hugepagesize_kb, &nr_hugepages_after) != 0) { + close(fd); + ksft_exit_fail_msg("Failed to read nr_hugepages\n"); + } + ksft_print_msg("NR hugepages after closure is %ld\n", nr_hugepages_after); + if (nr_hugepages_before != nr_hugepages_after + 1) + ksft_test_result_fail("NR hugepages is not reduced after memfd closure\n"); + + ksft_test_result_pass("All done\n"); +} + +int main(int argc, char **argv) +{ + int fd; + struct statfs file_stat; + size_t len = BYTE_LENTH_IN_1G; + + ksft_print_header(); + ksft_set_plan(1); + + fd = create_hugetlbfs_file(&file_stat); + test_main(fd, len); + + ksft_finished(); +}