1/*
2 *   Copyright (c) International Business Machines  Corp., 2004
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 * FILE NAME	: mmapfile.c
21 *
22 * PURPOSE	: This executable is invoked by the mmap test case to invoke
23 * 		  mmap() from a process different than mmap.  If mmap() is
24 * 		  invoked by the mmap process, a hang will generally occur
25 * 		  because sys_mmap obtains write access to mmap_sem, and any
26 * 		  page fault within the same process (while process is
27 * 		  responding to read/write event generated by mmap() call)
28 * 		  requires read access to the same mmap_sem.
29 *
30 * PARAMETERS	: argv[1] - name of file being memory mapped
31 * 		  argv[2] - open flags:
32 * 		  	0 - read-only
33 * 		  	1 - write-only
34 * 		  	2 - read-write
35 * 		  argv[3] - offset within file of memory mapped region
36 * 		  argv[4] - length of memory mapped region
37 * 		  argv[5] - mmap() expected pass/fail status
38 * 		  	0 - fail
39 * 		  	1 - pass
40 *
41 */
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45#include <errno.h>
46#include <unistd.h>
47#include <sys/mman.h>
48#include <fcntl.h>
49#include "dm_test.h"
50
51char DummyFile[FILENAME_MAX];
52
53int main(int argc, char **argv)
54{
55	int rc;
56	int fd;
57	int openflags;
58	int offset;
59	int length;
60	int passflag;
61	int flags;
62	void *memmap;
63
64	if (--argc != 5) {
65		printf("usage: %s filename openflags offset length passflag\n",
66		       argv[0]);
67		exit(-1);
68	}
69
70	passflag = atoi(argv[5]);
71	if ((passflag != 0) && (passflag != 1)) {
72		printf("%s error: invalid passflag %s\n", argv[0], argv[5]);
73		exit(-1);
74	}
75
76	length = atoi(argv[4]);
77	if (length < 0) {
78		printf("%s error: invalid length %s\n", argv[0], argv[4]);
79		exit(-1);
80	}
81
82	offset = atoi(argv[3]);
83	if (offset < 0) {
84		printf("%s error: invalid offset %s\n", argv[0], argv[3]);
85		exit(-1);
86	}
87	if (offset & (PAGE_SIZE - 1)) {
88		printf("%s error: unaligned offset %d\n", argv[0], offset);
89		exit(-1);
90	}
91
92	openflags = atoi(argv[2]);
93	if (openflags == O_RDONLY) {
94		flags = PROT_READ;
95	} else if (openflags == O_WRONLY) {
96		flags = PROT_WRITE;
97	} else if (openflags == O_RDWR) {
98		flags = PROT_READ | PROT_WRITE;
99	} else {
100		printf("%s error: invalid openflags %s\n", argv[0], argv[2]);
101		exit(-1);
102	}
103
104	printf("invoking open(%s, %d)\n", argv[1], openflags);
105	fd = open(argv[1], openflags);
106	if (fd == -1) {
107		printf("%s error: open failed with rc = %d (errno = %d)\n",
108		       argv[0], rc, errno);
109		exit(-1);
110	}
111
112	printf("invoking memmap(%d, %d, %s, %d)\n", length, flags, argv[1],
113	       offset);
114	memmap = mmap(NULL, length, flags, MAP_SHARED, fd, offset);
115	if (memmap == MAP_FAILED) {
116		printf("%s error: mmap failed with errno = %d\n", argv[0],
117		       errno);
118		if (passflag) {
119			close(fd);
120			exit(-1);
121		}
122	}
123
124	EVENT_DELIVERY_DELAY;
125
126	if (memmap != MAP_FAILED) {
127		printf("invoking munmap(%p, %d)\n", memmap, length);
128		munmap(memmap, length);
129	}
130
131	close(fd);
132
133	_exit(0);
134	tst_exit();
135}
136