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 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 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