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 }