1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2014-2017 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * DESCRIPTION 6f08c3bdfSopenharmony_ci * hugeshmat04 - test for hugepage leak inspection. 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * It is a regression test for shared hugepage leak, when over 1GB 9f08c3bdfSopenharmony_ci * shared memory was alocated in hugepage, the hugepage is not released 10f08c3bdfSopenharmony_ci * though process finished. 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * You need more than 2GB memory in test job 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * HISTORY 15f08c3bdfSopenharmony_ci * 05/2014 - Written by Fujistu Corp. 16f08c3bdfSopenharmony_ci * 12/2014 - Port to LTP by Li Wang. 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * RESTRICTIONS 19f08c3bdfSopenharmony_ci * test must be run at root 20f08c3bdfSopenharmony_ci */ 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_ci#include "hugetlb.h" 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_ci#define SIZE (1024 * 1024 * 1024) 25f08c3bdfSopenharmony_ci#define BOUNDARY (1024 * 1024 * 1024) 26f08c3bdfSopenharmony_ci#define BOUNDARY_MAX (3U * 1024 * 1024 * 1024) 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistatic long huge_free; 29f08c3bdfSopenharmony_cistatic long huge_free2; 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_cistatic void shared_hugepage(void); 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic void test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED) 34f08c3bdfSopenharmony_ci{ 35f08c3bdfSopenharmony_ci huge_free = SAFE_READ_MEMINFO("HugePages_Free:"); 36f08c3bdfSopenharmony_ci shared_hugepage(); 37f08c3bdfSopenharmony_ci huge_free2 = SAFE_READ_MEMINFO("HugePages_Free:"); 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci if (huge_free2 != huge_free) 40f08c3bdfSopenharmony_ci tst_brk(TFAIL, "Test failed. Hugepage leak inspection."); 41f08c3bdfSopenharmony_ci else 42f08c3bdfSopenharmony_ci tst_res(TPASS, "No regression found."); 43f08c3bdfSopenharmony_ci} 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void shared_hugepage(void) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci pid_t pid; 48f08c3bdfSopenharmony_ci int status, shmid; 49f08c3bdfSopenharmony_ci size_t size = (size_t)SIZE; 50f08c3bdfSopenharmony_ci void *buf; 51f08c3bdfSopenharmony_ci unsigned long boundary = BOUNDARY; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | IPC_CREAT | 0777); 54f08c3bdfSopenharmony_ci if (shmid < 0) 55f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmget"); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci while (boundary <= BOUNDARY_MAX 58f08c3bdfSopenharmony_ci && range_is_mapped(boundary, boundary+SIZE)) 59f08c3bdfSopenharmony_ci boundary += 128*1024*1024; 60f08c3bdfSopenharmony_ci if (boundary > BOUNDARY_MAX) 61f08c3bdfSopenharmony_ci tst_brk(TCONF, "failed to find free unmapped range"); 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci tst_res(TINFO, "attaching at 0x%lx", boundary); 64f08c3bdfSopenharmony_ci buf = shmat(shmid, (void *)boundary, SHM_RND | 0777); 65f08c3bdfSopenharmony_ci if (buf == (void *)-1) { 66f08c3bdfSopenharmony_ci shmctl(shmid, IPC_RMID, NULL); 67f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmat"); 68f08c3bdfSopenharmony_ci } 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci memset(buf, 2, size); 71f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 72f08c3bdfSopenharmony_ci if (pid == 0) 73f08c3bdfSopenharmony_ci exit(1); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci wait(&status); 76f08c3bdfSopenharmony_ci shmdt(buf); 77f08c3bdfSopenharmony_ci shmctl(shmid, IPC_RMID, NULL); 78f08c3bdfSopenharmony_ci} 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic void setup(void) 81f08c3bdfSopenharmony_ci{ 82f08c3bdfSopenharmony_ci long hpage_size, orig_hugepages; 83f08c3bdfSopenharmony_ci unsigned long new_shmmax; 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci orig_hugepages = get_sys_tune("nr_hugepages"); 86f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(PATH_SHMMAX, "%lu", &new_shmmax); 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci if (new_shmmax < SIZE) 89f08c3bdfSopenharmony_ci tst_brk(TCONF, "shmmax too low, have: %lu", new_shmmax); 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024; 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci struct tst_hugepage hp = { orig_hugepages + SIZE / hpage_size, TST_NEEDS }; 94f08c3bdfSopenharmony_ci tst_reserve_hugepages(&hp); 95f08c3bdfSopenharmony_ci} 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_cistatic struct tst_test test = { 98f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 99f08c3bdfSopenharmony_ci {"linux-git", "c5c99429fa57"}, 100f08c3bdfSopenharmony_ci {} 101f08c3bdfSopenharmony_ci }, 102f08c3bdfSopenharmony_ci .needs_root = 1, 103f08c3bdfSopenharmony_ci .forks_child = 1, 104f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 105f08c3bdfSopenharmony_ci .tcnt = 3, 106f08c3bdfSopenharmony_ci .test = test_hugeshmat, 107f08c3bdfSopenharmony_ci .min_mem_avail = 2048, 108f08c3bdfSopenharmony_ci .setup = setup, 109f08c3bdfSopenharmony_ci .hugepages = {1, TST_NEEDS}, 110f08c3bdfSopenharmony_ci .save_restore = (const struct tst_path_val[]) { 111f08c3bdfSopenharmony_ci {PATH_SHMMAX, "1073741824", TST_SR_TCONF_MISSING | TST_SR_TBROK_RO}, 112f08c3bdfSopenharmony_ci {} 113f08c3bdfSopenharmony_ci }, 114f08c3bdfSopenharmony_ci}; 115