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