blob: f4ef38bc1bd21758f15c2589c001c13394d149cd [file] [log] [blame]
DAN LId7709392013-07-01 14:10:25 +08001/*
2 * Copyright (c) 2013 FNST, DAN LI <li.dan@cn.fujitsu.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/*
20 * Test Description:
21 * Verify MAP_POPULATE works fine.
22 * "For a file mapping, this causes read-ahead on the file.
23 * Later accesses to the mapping will not be blocked by page faults"
24 *
25 * Expected Result:
26 * mmap() with MAP_POPULATE should succeed returning the address of the
27 * mapped region and this file has been read into RAM, so pages should
28 * be present.
29 */
30#include <stdio.h>
31#include <stdlib.h>
32#include <sys/types.h>
33#include <errno.h>
34#include <unistd.h>
35#include <fcntl.h>
36#include <string.h>
37#include <signal.h>
38#include <stdint.h>
39#include <sys/stat.h>
40#include <sys/mman.h>
41#include <sys/shm.h>
42
43#include "test.h"
DAN LId7709392013-07-01 14:10:25 +080044
45#define TEMPFILE "mmapfile"
46#define PATHLEN 256
47#define MMAPSIZE (1UL<<20)
48
49char *TCID = "mmap12";
50int TST_TOTAL = 1;
51
52static int fildes;
53static char *addr;
54
55static int page_check(void);
56static void setup(void);
57static void cleanup(void);
58
59int main(int argc, char *argv[])
60{
61 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020062 const char *msg;
DAN LId7709392013-07-01 14:10:25 +080063
64 msg = parse_opts(argc, argv, NULL, NULL);
65 if (msg != NULL)
66 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
67
68 setup();
69
70 for (lc = 0; TEST_LOOPING(lc); lc++) {
71 tst_count = 0;
72
73 addr = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE,
74 MAP_PRIVATE | MAP_POPULATE, fildes, 0);
75
76 if (addr == MAP_FAILED) {
77 tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
78 continue;
79 }
80
Cyril Hrubise38b9612014-06-02 17:20:57 +020081 if (page_check())
82 tst_resm(TFAIL, "Not all pages are present");
83 else
84 tst_resm(TPASS, "Functionality of mmap() "
DAN LId7709392013-07-01 14:10:25 +080085 "successful");
DAN LId7709392013-07-01 14:10:25 +080086 if (munmap(addr, MMAPSIZE) != 0)
87 tst_brkm(TFAIL | TERRNO, NULL, "munmap failed");
88 }
89
90 cleanup();
91 tst_exit();
DAN LId7709392013-07-01 14:10:25 +080092}
93
94static int page_check(void)
95{
96 int ret;
97 int i = 1;
98 int flag = 0;
99 int pm;
100 int num_pages;
101 long index;
102 off_t offset;
103 size_t page_sz;
104 uint64_t pagemap;
105 unsigned long vmstart;
106
107 vmstart = (unsigned long)addr;
108 page_sz = getpagesize();
109
110 num_pages = MMAPSIZE / page_sz;
111 index = (vmstart / page_sz) * sizeof(uint64_t);
112
113 pm = open("/proc/self/pagemap", O_RDONLY);
114 if (pm == -1)
115 tst_brkm(TFAIL | TERRNO, NULL, "Open dev pagemap failed");
116
117 offset = lseek(pm, index, SEEK_SET);
118 if (offset != index)
119 tst_brkm(TFAIL | TERRNO, NULL, "Reposition offset failed");
120
121 while (i <= num_pages) {
122 ret = read(pm, &pagemap, sizeof(uint64_t));
123 if (ret < 0)
124 tst_brkm(TFAIL | TERRNO, NULL, "Read pagemap failed");
125 /*
126 * Check if the page is present.
127 */
128 if (!(pagemap & (1ULL<<63))) {
129 tst_resm(TINFO, "The %dth page addressed at %lX is not "
130 "present", i, vmstart + i * page_sz);
131 flag = 1;
132 }
133
134 i++;
135 }
136
137 close(pm);
138
139 if (flag)
140 return 1;
141
142 return 0;
143}
144
145static void setup(void)
146{
147 tst_sig(FORK, DEF_HANDLER, cleanup);
148
149 if ((tst_kvercmp(2, 6, 25)) < 0)
150 tst_brkm(TCONF, NULL,
151 "This test can only run on kernels that are 2.6.25 and "
152 "higher");
153
154 TEST_PAUSE;
155
156 tst_tmpdir();
157
158 fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0766);
159 if (fildes < 0)
160 tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
161
162 if (ftruncate(fildes, MMAPSIZE) < 0)
163 tst_brkm(TFAIL | TERRNO, cleanup, "ftruncate file failed");
164
165}
166
167static void cleanup(void)
168{
169 close(fildes);
DAN LId7709392013-07-01 14:10:25 +0800170 tst_rmdir();
171}