xref: /illumos-gate/usr/src/test/smbclient-tests/cmd/mkfile_mmap/mkfile_mmap.c (revision 7931524763ef94dc16989451dddd206563d03bb4)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2012 Jilin Xpd <jilinxpd@gmail.com>
14  * Copyright 2018 Nexenta Systems, Inc.
15  */
16 
17 /*
18  * Using mmap, make a file and padding it with random chars.
19  */
20 
21 #include <sys/mman.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <time.h>
31 
32 void
33 usage(void)
34 {
35 	fprintf(stderr,
36 	    "usage: mkfile_mmap -n <size>[b|k|m|g] -f <filename>\n");
37 	exit(1);
38 }
39 
40 int
41 main(int argc, char **argv)
42 {
43 	char *suffix;
44 	char *filename = NULL;
45 	char *file_addr;
46 	char *p, *q;
47 	off_t offset;
48 	size_t filesize;
49 	size_t blksize;
50 	size_t numblks;
51 	size_t cnt = 1;
52 	size_t mul = 1;
53 	size_t i;
54 	int mret = 0;
55 	int c, fid;
56 
57 	/*
58 	 * parse arguments
59 	 */
60 	while ((c = getopt(argc, argv, "n:f:")) != -1) {
61 		switch (c) {
62 		case 'n':
63 			cnt = (size_t)strtoul(optarg, &suffix, 0);
64 			if (cnt == 0)
65 				goto bad_n_arg;
66 			switch (*suffix) {
67 			case '\0':
68 			case 'b':
69 				mul = 1;
70 				break;
71 			case 'k':
72 				mul = 1024;
73 				break;
74 			case 'm':
75 				mul = (1024 * 1024);
76 				break;
77 			case 'g':
78 				mul = (1024 * 1024 * 1024);
79 				break;
80 			default:
81 			bad_n_arg:
82 				fprintf(stderr, "-n %s: invalid size\n",
83 				    optarg);
84 				return (1);
85 			}
86 			cnt = cnt * mul;
87 			break;
88 
89 		case 'f': /* target file */
90 			filename = optarg;
91 			break;
92 
93 		case ':':   /* missing optarg */
94 			fprintf(stderr,
95 			    "Option -%c requires an arg\n", optopt);
96 			usage();
97 			break;
98 		case '?':
99 			fprintf(stderr,
100 			    "Unrecognized option: -%c\n", optopt);
101 			usage();
102 			break;
103 		}
104 	}
105 
106 	/* open test file */
107 	fid = open(filename, O_RDWR | O_CREAT | O_TRUNC,
108 	    S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
109 	if (fid == -1) {
110 		fprintf(stderr, "open %s error=%d\n", filename, errno);
111 		mret = 1;
112 		goto exit3;
113 	}
114 
115 	/* extend file */
116 	filesize = cnt;
117 	if (ftruncate(fid, filesize) == -1) {
118 		fprintf(stderr, "ftrunc %s error=%d\n", filename, errno);
119 		mret = 1;
120 		goto exit2;
121 	}
122 
123 #define	K 1024
124 
125 	blksize = 64 * K * K;
126 	numblks = (filesize + blksize - 1) / blksize;
127 	for (i = 0; i < numblks && mret == 0; i++) {
128 
129 		offset = i*blksize;
130 		if (offset + blksize > filesize)
131 			blksize = filesize - offset;
132 
133 		/* map file */
134 		file_addr = mmap(NULL, blksize,
135 		    PROT_READ | PROT_WRITE, MAP_SHARED, fid, offset);
136 		if (file_addr == MAP_FAILED) {
137 			fprintf(stderr, "mmap %s error=%d\n", filename, errno);
138 			mret = 1;
139 			break;
140 		}
141 
142 	/* tag each block (to aid debug) */
143 	p = file_addr;
144 	q = file_addr + blksize - K;
145 	memset(p, ' ', K);
146 	snprintf(p, K, "\nblk=%d\n\n", i);
147 	p += K;
148 
149 		/* fill something into mapped addr */
150 	while (p < q) {
151 		memset(p, ' ', K);
152 		snprintf(p, K, "\noff=0x%x\n\n",
153 		    (i * blksize) + (p - file_addr));
154 		p += K;
155 	}
156 
157 		/* sync mapped pages to file */
158 		if (msync(file_addr, blksize, MS_SYNC) == -1) {
159 			fprintf(stderr, "msync %s error=%d\n", filename, errno);
160 			mret = 1;
161 		}
162 
163 		/* unmap file */
164 		if (munmap(file_addr, blksize) == -1) {
165 			fprintf(stderr, "unmap %s error=%d\n", filename, errno);
166 			mret = 1;
167 		}
168 	}
169 
170 	/* close file */
171 exit2:
172 	close(fid);
173 exit3:
174 	return (mret);
175 }
176