93 lines
2.1 KiB
C
93 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
|
|
* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
|
|
*/
|
|
/*
|
|
* Description:
|
|
* If one memory is already locked by mlock2() with MLOCK_ONFAULT and then
|
|
* it is locked again by mlock()(or mlock2() without MLOCK_ONFAULT), the
|
|
* VmLck field in /proc/pid/status should increase once instead of twice.
|
|
*
|
|
* This issue has been fixed in kernel:
|
|
* 'b155b4fde5bd("mm: mlock: avoid increase mm->locked_vm on mlock() when already mlock2(,MLOCK_ONFAULT)")'
|
|
*/
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <linux/mman.h>
|
|
|
|
#include "tst_test.h"
|
|
#include "lapi/syscalls.h"
|
|
#include "lapi/mlock2.h"
|
|
|
|
static unsigned long pgsz;
|
|
static char *addr;
|
|
|
|
static void verify_mlock2(void)
|
|
{
|
|
unsigned long bsize, asize1, asize2;
|
|
|
|
SAFE_FILE_LINES_SCANF("/proc/self/status", "VmLck: %lu", &bsize);
|
|
|
|
TEST(tst_syscall(__NR_mlock2, addr, pgsz, MLOCK_ONFAULT));
|
|
if (TST_RET != 0) {
|
|
if (TST_ERR == EINVAL) {
|
|
tst_res(TCONF,
|
|
"mlock2() didn't support MLOCK_ONFAULT");
|
|
} else {
|
|
tst_res(TFAIL | TTERRNO,
|
|
"mlock2(MLOCK_ONFAULT) failed");
|
|
}
|
|
return;
|
|
}
|
|
|
|
SAFE_FILE_LINES_SCANF("/proc/self/status", "VmLck: %lu", &asize1);
|
|
|
|
if ((asize1 - bsize) * 1024 != pgsz) {
|
|
tst_res(TFAIL,
|
|
"mlock2(MLOCK_ONFAULT) locked %lu size, expected %lu",
|
|
(asize1 - bsize) * 1024, pgsz);
|
|
goto end;
|
|
}
|
|
|
|
TEST(tst_syscall(__NR_mlock2, addr, pgsz, 0));
|
|
if (TST_RET != 0) {
|
|
tst_res(TFAIL | TTERRNO, "mlock2() failed");
|
|
goto end;
|
|
}
|
|
|
|
SAFE_FILE_LINES_SCANF("/proc/self/status", "VmLck: %lu", &asize2);
|
|
|
|
if (asize1 != asize2) {
|
|
tst_res(TFAIL, "Locking one memory again increased VmLck");
|
|
} else {
|
|
tst_res(TPASS,
|
|
"Locking one memory again didn't increased VmLck");
|
|
}
|
|
|
|
end:
|
|
SAFE_MUNLOCK(addr, pgsz);
|
|
}
|
|
|
|
static void setup(void)
|
|
{
|
|
pgsz = getpagesize();
|
|
addr = SAFE_MMAP(NULL, pgsz, PROT_WRITE,
|
|
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
|
}
|
|
|
|
static void cleanup(void)
|
|
{
|
|
if (addr)
|
|
SAFE_MUNMAP(addr, pgsz);
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.test_all = verify_mlock2,
|
|
.setup = setup,
|
|
.cleanup = cleanup,
|
|
.needs_root = 1,
|
|
.min_kver = "2.6.9",
|
|
};
|