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