140 lines
2.7 KiB
C
140 lines
2.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2013 FNST, DAN LI <li.dan@cn.fujitsu.com>
|
|
*/
|
|
|
|
/*
|
|
* Test Description:
|
|
* Verify MAP_POPULATE works fine.
|
|
* "For a file mapping, this causes read-ahead on the file.
|
|
* Later accesses to the mapping will not be blocked by page faults"
|
|
*
|
|
* Expected Result:
|
|
* mmap() with MAP_POPULATE should succeed returning the address of the
|
|
* mapped region and this file has been read into RAM, so pages should
|
|
* be present.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <stdint.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/shm.h>
|
|
|
|
#include "tst_test.h"
|
|
|
|
#define TEMPFILE "mmapfile"
|
|
#define PATHLEN 256
|
|
#define MMAPSIZE (1UL<<20)
|
|
|
|
static int fildes;
|
|
static char *addr;
|
|
|
|
static void page_check(void)
|
|
{
|
|
int i = 1;
|
|
int flag = 0;
|
|
int pm;
|
|
int num_pages;
|
|
long index;
|
|
off_t offset;
|
|
size_t page_sz;
|
|
uint64_t pagemap;
|
|
unsigned long vmstart;
|
|
|
|
vmstart = (unsigned long)addr;
|
|
page_sz = getpagesize();
|
|
|
|
num_pages = MMAPSIZE / page_sz;
|
|
index = (vmstart / page_sz) * sizeof(uint64_t);
|
|
|
|
pm = open("/proc/self/pagemap", O_RDONLY);
|
|
if (pm == -1) {
|
|
if ((errno == EPERM) && (geteuid() != 0)) {
|
|
tst_res(TCONF | TERRNO,
|
|
"don't have permission to open dev pagemap");
|
|
return;
|
|
} else {
|
|
tst_brk(TFAIL | TERRNO, "pen dev pagemap failed");
|
|
}
|
|
}
|
|
|
|
offset = SAFE_LSEEK(pm, index, SEEK_SET);
|
|
if (offset != index)
|
|
tst_brk(TFAIL | TERRNO, "Reposition offset failed");
|
|
|
|
while (i <= num_pages) {
|
|
SAFE_READ(1, pm, &pagemap, sizeof(uint64_t));
|
|
|
|
/*
|
|
* Check if the page is present.
|
|
*/
|
|
if (!(pagemap & (1ULL<<63))) {
|
|
tst_res(TINFO, "The %dth page addressed at %lX is not "
|
|
"present", i, vmstart + i * page_sz);
|
|
flag = 1;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
close(pm);
|
|
|
|
if (!flag)
|
|
tst_res(TINFO, "All pages are present");
|
|
}
|
|
|
|
void verify_mmap(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
addr = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE,
|
|
MAP_PRIVATE | MAP_POPULATE, fildes, 0);
|
|
|
|
if (addr == MAP_FAILED) {
|
|
tst_res(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
|
|
return;
|
|
}
|
|
|
|
page_check();
|
|
|
|
for (i = 0; i < MMAPSIZE; i++) {
|
|
if (addr[i]) {
|
|
tst_res(TFAIL, "Non-zero byte at offset %i", i);
|
|
goto unmap;
|
|
}
|
|
}
|
|
|
|
tst_res(TPASS, "File mapped properly");
|
|
|
|
unmap:
|
|
SAFE_MUNMAP(addr, MMAPSIZE);
|
|
}
|
|
|
|
static void setup(void)
|
|
{
|
|
fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0766);
|
|
|
|
SAFE_FTRUNCATE(fildes, MMAPSIZE);
|
|
}
|
|
|
|
static void cleanup(void)
|
|
{
|
|
if (fildes > 0)
|
|
SAFE_CLOSE(fildes);
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.setup = setup,
|
|
.cleanup = cleanup,
|
|
.test_all = verify_mmap,
|
|
.needs_tmpdir = 1,
|
|
.min_kver = "2.6.25",
|
|
};
|