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 (c) 2017 by Delphix. All rights reserved. 14 */ 15 16 #include <stdint.h> 17 #include <string.h> 18 #include "file_common.h" 19 20 /* 21 * The following sample was derived from real-world data 22 * of a production Oracle database. 23 */ 24 static const uint64_t size_distribution[] = { 25 0, 26 1499018, 27 352084, 28 1503485, 29 4206227, 30 5626657, 31 5387001, 32 3733756, 33 2233094, 34 874652, 35 238635, 36 81434, 37 33357, 38 13106, 39 2009, 40 1, 41 23660, 42 }; 43 44 45 static uint64_t distribution_n; 46 47 static uint8_t randbuf[BLOCKSZ]; 48 49 static void 50 rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset) 51 { 52 size_t nleft = nbytes; 53 ssize_t nwrite = 0; 54 55 nwrite = pwrite(fd, buf, nbytes, offset); 56 if (nwrite < 0) { 57 perror("pwrite"); 58 exit(EXIT_FAILURE); 59 } 60 61 nleft -= nwrite; 62 if (nleft != 0) { 63 (void) fprintf(stderr, "warning: pwrite: " 64 "wrote %zu out of %zu bytes\n", 65 (nbytes - nleft), nbytes); 66 } 67 } 68 69 static void 70 fillbuf(char *buf) 71 { 72 uint64_t rv = lrand48() % distribution_n; 73 uint64_t sum = 0; 74 75 uint64_t i; 76 for (i = 0; 77 i < sizeof (size_distribution) / sizeof (size_distribution[0]); 78 i++) { 79 sum += size_distribution[i]; 80 if (rv < sum) 81 break; 82 } 83 84 memcpy(buf, randbuf, BLOCKSZ); 85 if (i == 0) 86 memset(buf, 0, BLOCKSZ - 10); 87 else if (i < 16) 88 memset(buf, 0, BLOCKSZ - i * 512 + 256); 89 /*LINTED: E_BAD_PTR_CAST_ALIGN*/ 90 ((uint32_t *)buf)[0] = lrand48(); 91 } 92 93 static void 94 exit_usage(void) 95 { 96 (void) puts("usage: randwritecomp [-s] file [nwrites]"); 97 exit(EXIT_FAILURE); 98 } 99 100 static void 101 sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n) 102 { 103 for (int64_t i = 0; n == -1 || i < n; i++) { 104 fillbuf(buf); 105 106 static uint64_t j = 0; 107 if (j == 0) 108 j = lrand48() % nblocks; 109 rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ); 110 j++; 111 if (j >= nblocks) 112 j = 0; 113 } 114 } 115 116 static void 117 random_writes(int fd, char *buf, uint64_t nblocks, int64_t n) 118 { 119 for (int64_t i = 0; n == -1 || i < n; i++) { 120 fillbuf(buf); 121 rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ); 122 } 123 } 124 125 int 126 main(int argc, char *argv[]) 127 { 128 int fd, err; 129 char *filename = NULL; 130 char buf[BLOCKSZ]; 131 struct stat ss; 132 uint64_t nblocks; 133 int64_t n = -1; 134 int sequential = 0; 135 136 if (argc < 2) 137 exit_usage(); 138 139 argv++; 140 if (strcmp("-s", argv[0]) == 0) { 141 sequential = 1; 142 argv++; 143 } 144 145 if (argv[0] == NULL) 146 exit_usage(); 147 else 148 filename = argv[0]; 149 150 argv++; 151 if (argv[0] != NULL) 152 n = strtoull(argv[0], NULL, 0); 153 154 fd = open(filename, O_RDWR|O_CREAT, 0666); 155 if (fd == -1) { 156 (void) fprintf(stderr, "open(%s) failed: %s\n", filename, 157 strerror(errno)); 158 exit(EXIT_FAILURE); 159 } 160 err = fstat(fd, &ss); 161 if (err != 0) { 162 (void) fprintf(stderr, 163 "error: fstat returned error code %d\n", err); 164 exit(EXIT_FAILURE); 165 } 166 167 nblocks = ss.st_size / BLOCKSZ; 168 if (nblocks == 0) { 169 (void) fprintf(stderr, "error: " 170 "file is too small (min allowed size is %d bytes)\n", 171 BLOCKSZ); 172 exit(EXIT_FAILURE); 173 } 174 175 srand48(getpid()); 176 for (int i = 0; i < BLOCKSZ; i++) 177 randbuf[i] = lrand48(); 178 179 distribution_n = 0; 180 for (uint64_t i = 0; 181 i < sizeof (size_distribution) / sizeof (size_distribution[0]); 182 i++) { 183 distribution_n += size_distribution[i]; 184 } 185 186 if (sequential) 187 sequential_writes(fd, buf, nblocks, n); 188 else 189 random_writes(fd, buf, nblocks, n); 190 191 return (0); 192 } 193