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