1/*
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_LOCKED works fine.
22 *  "Lock the pages of the mapped region into memory in the manner of mlock(2)."
23 *
24 * Expected Result:
25 *  mmap() should succeed returning the address of the mapped region,
26 *  and this region should be locked into memory.
27 */
28#include <stdio.h>
29#include <sys/mman.h>
30
31#include "test.h"
32
33#define TEMPFILE        "mmapfile"
34#define MMAPSIZE        (1UL<<20)
35#define LINELEN         256
36
37char *TCID = "mmap14";
38int TST_TOTAL = 1;
39
40static char *addr;
41
42static void getvmlck(unsigned int *lock_sz);
43static void setup(void);
44static void cleanup(void);
45
46int main(int argc, char *argv[])
47{
48	int lc;
49	unsigned int sz_before;
50	unsigned int sz_after;
51	unsigned int sz_ch;
52
53	tst_parse_opts(argc, argv, NULL, NULL);
54
55	setup();
56
57	for (lc = 0; TEST_LOOPING(lc); lc++) {
58
59		tst_count = 0;
60
61		getvmlck(&sz_before);
62
63		addr = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE,
64			    MAP_PRIVATE | MAP_LOCKED | MAP_ANONYMOUS,
65			    -1, 0);
66
67		if (addr == MAP_FAILED) {
68			tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
69			continue;
70		}
71
72		getvmlck(&sz_after);
73
74		sz_ch = sz_after - sz_before;
75		if (sz_ch == MMAPSIZE / 1024) {
76			tst_resm(TPASS, "Functionality of mmap() "
77					"successful");
78		} else {
79			tst_resm(TFAIL, "Expected %luK locked, "
80					"get %uK locked",
81					MMAPSIZE / 1024, sz_ch);
82		}
83
84		if (munmap(addr, MMAPSIZE) != 0)
85			tst_brkm(TFAIL | TERRNO, NULL, "munmap failed");
86	}
87
88	cleanup();
89	tst_exit();
90}
91
92void getvmlck(unsigned int *lock_sz)
93{
94	int ret;
95	char line[LINELEN];
96	FILE *fstatus = NULL;
97
98	fstatus = fopen("/proc/self/status", "r");
99	if (fstatus == NULL)
100		tst_brkm(TFAIL | TERRNO, NULL, "Open dev status failed");
101
102	while (fgets(line, LINELEN, fstatus) != NULL)
103		if (strstr(line, "VmLck") != NULL)
104			break;
105
106	ret = sscanf(line, "%*[^0-9]%d%*[^0-9]", lock_sz);
107	if (ret != 1)
108		tst_brkm(TFAIL | TERRNO, NULL, "Get lock size failed");
109
110	fclose(fstatus);
111}
112
113static void setup(void)
114{
115	tst_require_root();
116
117	tst_sig(FORK, DEF_HANDLER, cleanup);
118
119	TEST_PAUSE;
120}
121
122static void cleanup(void)
123{
124}
125