195 lines
3.6 KiB
C
195 lines
3.6 KiB
C
|
/*
|
||
|
* This file and its contents are supplied under the terms of the
|
||
|
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||
|
* You may only use this file in accordance with the terms of version
|
||
|
* 1.0 of the CDDL.
|
||
|
*
|
||
|
* A full copy of the text of the CDDL should have accompanied this
|
||
|
* source. A copy of the CDDL is also available via the Internet at
|
||
|
* http://www.illumos.org/license/CDDL.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Copyright (c) 2017 by Delphix. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* The following is defined so the source can use
|
||
|
* lrand48() and srand48().
|
||
|
*/
|
||
|
#define __EXTENSIONS__
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
#include "../file_common.h"
|
||
|
|
||
|
/*
|
||
|
* The following sample was derived from real-world data
|
||
|
* of a production Oracle database.
|
||
|
*/
|
||
|
static uint64_t size_distribution[] = {
|
||
|
0,
|
||
|
1499018,
|
||
|
352084,
|
||
|
1503485,
|
||
|
4206227,
|
||
|
5626657,
|
||
|
5387001,
|
||
|
3733756,
|
||
|
2233094,
|
||
|
874652,
|
||
|
238635,
|
||
|
81434,
|
||
|
33357,
|
||
|
13106,
|
||
|
2009,
|
||
|
1,
|
||
|
23660,
|
||
|
};
|
||
|
|
||
|
|
||
|
static uint64_t distribution_n;
|
||
|
|
||
|
static uint8_t randbuf[BLOCKSZ];
|
||
|
|
||
|
static void
|
||
|
rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
|
||
|
{
|
||
|
size_t nleft = nbytes;
|
||
|
ssize_t nwrite = 0;
|
||
|
|
||
|
nwrite = pwrite(fd, buf, nbytes, offset);
|
||
|
if (nwrite < 0) {
|
||
|
perror("pwrite");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
nleft -= nwrite;
|
||
|
if (nleft != 0) {
|
||
|
(void) fprintf(stderr, "warning: pwrite: "
|
||
|
"wrote %zu out of %zu bytes\n",
|
||
|
(nbytes - nleft), nbytes);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
fillbuf(char *buf)
|
||
|
{
|
||
|
uint64_t rv = lrand48() % distribution_n;
|
||
|
uint64_t sum = 0;
|
||
|
|
||
|
uint64_t i;
|
||
|
for (i = 0;
|
||
|
i < sizeof (size_distribution) / sizeof (size_distribution[0]);
|
||
|
i++) {
|
||
|
sum += size_distribution[i];
|
||
|
if (rv < sum)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bcopy(randbuf, buf, BLOCKSZ);
|
||
|
if (i == 0)
|
||
|
bzero(buf, BLOCKSZ - 10);
|
||
|
else if (i < 16)
|
||
|
bzero(buf, BLOCKSZ - i * 512 + 256);
|
||
|
/*LINTED: E_BAD_PTR_CAST_ALIGN*/
|
||
|
((uint32_t *)buf)[0] = lrand48();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
exit_usage(void)
|
||
|
{
|
||
|
(void) printf("usage: ");
|
||
|
(void) printf("randwritecomp <file> [-s] [nwrites]\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
|
||
|
{
|
||
|
for (int64_t i = 0; n == -1 || i < n; i++) {
|
||
|
fillbuf(buf);
|
||
|
|
||
|
static uint64_t j = 0;
|
||
|
if (j == 0)
|
||
|
j = lrand48() % nblocks;
|
||
|
rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ);
|
||
|
j++;
|
||
|
if (j >= nblocks)
|
||
|
j = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
random_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
|
||
|
{
|
||
|
for (int64_t i = 0; n == -1 || i < n; i++) {
|
||
|
fillbuf(buf);
|
||
|
rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main(int argc, char *argv[])
|
||
|
{
|
||
|
int fd, err;
|
||
|
char *filename = NULL;
|
||
|
char buf[BLOCKSZ];
|
||
|
struct stat ss;
|
||
|
uint64_t nblocks;
|
||
|
int64_t n = -1;
|
||
|
int sequential = 0;
|
||
|
|
||
|
if (argc < 2)
|
||
|
exit_usage();
|
||
|
|
||
|
argv++;
|
||
|
if (strcmp("-s", argv[0]) == 0) {
|
||
|
sequential = 1;
|
||
|
argv++;
|
||
|
}
|
||
|
|
||
|
if (argv[0] == NULL)
|
||
|
exit_usage();
|
||
|
else
|
||
|
filename = argv[0];
|
||
|
|
||
|
argv++;
|
||
|
if (argv[0] != NULL)
|
||
|
n = strtoull(argv[0], NULL, 0);
|
||
|
|
||
|
fd = open(filename, O_RDWR|O_CREAT, 0666);
|
||
|
err = fstat(fd, &ss);
|
||
|
if (err != 0) {
|
||
|
(void) fprintf(stderr,
|
||
|
"error: fstat returned error code %d\n", err);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
nblocks = ss.st_size / BLOCKSZ;
|
||
|
if (nblocks == 0) {
|
||
|
(void) fprintf(stderr, "error: "
|
||
|
"file is too small (min allowed size is %d bytes)\n",
|
||
|
BLOCKSZ);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
srand48(getpid());
|
||
|
for (int i = 0; i < BLOCKSZ; i++)
|
||
|
randbuf[i] = lrand48();
|
||
|
|
||
|
distribution_n = 0;
|
||
|
for (uint64_t i = 0;
|
||
|
i < sizeof (size_distribution) / sizeof (size_distribution[0]);
|
||
|
i++) {
|
||
|
distribution_n += size_distribution[i];
|
||
|
}
|
||
|
|
||
|
if (sequential)
|
||
|
sequential_writes(fd, buf, nblocks, n);
|
||
|
else
|
||
|
random_writes(fd, buf, nblocks, n);
|
||
|
|
||
|
return (0);
|
||
|
}
|