Skip to content

Commit

Permalink
Add mincore() test for pages cached by another process
Browse files Browse the repository at this point in the history
It tests the result of mincore when memory is mapped and cached by
another process. A file is mapped in both parent and child
process.Then the mapped memory is accessed in the child process. The
results of mincore are tested in the parent process.

Closes: #460

Signed-off-by: Shwetha Subramanian. <shwetha@zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar@zilogic.com>
Acked-by: Jan Stancek <jstancek@redhat.com>
Reviewed-by: Petr Vorel <pvorel@suse.cz>
  • Loading branch information
Shwetha Subramanian authored and pevik committed Aug 3, 2020
1 parent fd66e60 commit a6c8680
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
1 change: 1 addition & 0 deletions runtest/syscalls
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,7 @@ open_tree02 open_tree02
mincore01 mincore01
mincore02 mincore02
mincore03 mincore03
mincore04 mincore04

madvise01 madvise01
madvise02 madvise02
Expand Down
1 change: 1 addition & 0 deletions testcases/kernel/syscalls/mincore/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/mincore01
/mincore02
/mincore03
/mincore04
112 changes: 112 additions & 0 deletions testcases/kernel/syscalls/mincore/mincore04.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Zilogic Systems Pvt. Ltd., 2020
* Email: code@zilogic.com
*/

/*
* mincore04
* Test shows that pages mapped in one process(parent) and
* faulted in another(child) results in mincore(in parent) reporting
* that all mapped pages are resident.
*/

#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdlib.h>
#include "tst_test.h"

#define NUM_PAGES 3

static int fd;
static int size;
static void *ptr;

static void cleanup(void)
{
if (fd > 0)
SAFE_CLOSE(fd);
if (ptr) {
SAFE_MUNLOCK(ptr, size);
SAFE_MUNMAP(ptr, size);
}
}

static void setup(void)
{
int page_size, ret;

page_size = getpagesize();
size = page_size * NUM_PAGES;
fd = SAFE_OPEN("FILE", O_CREAT | O_RDWR, 0600);
SAFE_FTRUNCATE(fd, size);

/* File pages from file creation are cleared from cache. */
SAFE_FSYNC(fd);
ret = posix_fadvise(fd, 0, size, POSIX_FADV_DONTNEED);
if (ret == -1)
tst_brk(TBROK | TERRNO, "fadvise failed");
}

static void lock_file(void)
{
SAFE_MLOCK(ptr, size);
TST_CHECKPOINT_WAKE(0);
TST_CHECKPOINT_WAIT(1);
}

static int count_pages_in_cache(void)
{
int locked_pages = 0;
int count, ret;
unsigned char vec[NUM_PAGES];

TST_CHECKPOINT_WAIT(0);

ret = mincore(ptr, size, vec);
if (ret == -1)
tst_brk(TBROK | TERRNO, "mincore failed");
for (count = 0; count < NUM_PAGES; count++) {
if (vec[count] & 1)
locked_pages++;
}

TST_CHECKPOINT_WAKE(1);
return locked_pages;
}

static void test_mincore(void)
{
int locked_pages;

ptr = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
pid_t child_pid = SAFE_FORK();

if (child_pid == 0) {
lock_file();
exit(0);
}

locked_pages = count_pages_in_cache();
tst_reap_children();

if (locked_pages == NUM_PAGES)
tst_res(TPASS, "mincore reports all %d pages locked by child process "
"are resident", locked_pages);
else
tst_res(TFAIL, "mincore reports %d pages resident but %d pages "
"locked by child process", locked_pages, NUM_PAGES);
}

static struct tst_test test = {
.setup = setup,
.cleanup = cleanup,
.forks_child = 1,
.test_all = test_mincore,
.needs_checkpoints = 1,
};

0 comments on commit a6c8680

Please sign in to comment.