• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2013 FNST, DAN LI <li.dan@cn.fujitsu.com>
4  */
5 
6 /*
7  * Test Description:
8  *  Verify MAP_POPULATE works fine.
9  *  "For a file mapping, this causes read-ahead on the file.
10  *   Later accesses to the mapping will not be blocked by page faults"
11  *
12  * Expected Result:
13  *  mmap() with MAP_POPULATE should succeed returning the address of the
14  *  mapped region and this file has been read into RAM, so pages should
15  *  be present.
16  */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <stdint.h>
26 #include <sys/stat.h>
27 #include <sys/mman.h>
28 #include <sys/shm.h>
29 
30 #include "tst_test.h"
31 
32 #define TEMPFILE        "mmapfile"
33 #define PATHLEN         256
34 #define MMAPSIZE        (1UL<<20)
35 
36 static int fildes;
37 static char *addr;
38 
page_check(void)39 static void page_check(void)
40 {
41 	int i = 1;
42 	int flag = 0;
43 	int pm;
44 	int num_pages;
45 	long index;
46 	off_t offset;
47 	size_t page_sz;
48 	uint64_t pagemap;
49 	unsigned long vmstart;
50 
51 	vmstart = (unsigned long)addr;
52 	page_sz = getpagesize();
53 
54 	num_pages = MMAPSIZE / page_sz;
55 	index = (vmstart / page_sz) * sizeof(uint64_t);
56 
57 	pm = open("/proc/self/pagemap", O_RDONLY);
58 	if (pm == -1) {
59 		if ((errno == EPERM) && (geteuid() != 0)) {
60 			tst_res(TCONF | TERRNO,
61 				"don't have permission to open dev pagemap");
62 			return;
63 		} else {
64 			tst_brk(TFAIL | TERRNO, "pen dev pagemap failed");
65 		}
66 	}
67 
68 	offset = SAFE_LSEEK(pm, index, SEEK_SET);
69 	if (offset != index)
70 		tst_brk(TFAIL | TERRNO, "Reposition offset failed");
71 
72 	while (i <= num_pages) {
73 		SAFE_READ(1, pm, &pagemap, sizeof(uint64_t));
74 
75 		/*
76 		 * Check if the page is present.
77 		 */
78 		if (!(pagemap & (1ULL<<63))) {
79 			tst_res(TINFO, "The %dth page addressed at %lX is not "
80 				       "present", i, vmstart + i * page_sz);
81 			flag = 1;
82 		}
83 
84 		i++;
85 	}
86 
87 	close(pm);
88 
89 	if (!flag)
90 		tst_res(TINFO, "All pages are present");
91 }
92 
verify_mmap(void)93 void verify_mmap(void)
94 {
95 	unsigned int i;
96 
97 	addr = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE,
98 		    MAP_PRIVATE | MAP_POPULATE, fildes, 0);
99 
100 	if (addr == MAP_FAILED) {
101 		tst_res(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
102 		return;
103 	}
104 
105 	page_check();
106 
107 	for (i = 0; i < MMAPSIZE; i++) {
108 		if (addr[i]) {
109 			tst_res(TFAIL, "Non-zero byte at offset %i", i);
110 			goto unmap;
111 		}
112 	}
113 
114 	tst_res(TPASS, "File mapped properly");
115 
116 unmap:
117 	SAFE_MUNMAP(addr, MMAPSIZE);
118 }
119 
setup(void)120 static void setup(void)
121 {
122 	fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0766);
123 
124 	SAFE_FTRUNCATE(fildes, MMAPSIZE);
125 }
126 
cleanup(void)127 static void cleanup(void)
128 {
129 	if (fildes > 0)
130 		SAFE_CLOSE(fildes);
131 }
132 
133 static struct tst_test test = {
134 	.setup = setup,
135 	.cleanup = cleanup,
136 	.test_all = verify_mmap,
137 	.needs_tmpdir = 1,
138 	.min_kver = "2.6.25",
139 };
140