2016-12-17 01:11:29 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
2022-03-22 22:09:47 +03:00
|
|
|
#include "file_common.h"
|
2016-12-17 01:11:29 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The following sample was derived from real-world data
|
|
|
|
* of a production Oracle database.
|
|
|
|
*/
|
2022-02-25 16:26:54 +03:00
|
|
|
static const uint64_t size_distribution[] = {
|
2016-12-17 01:11:29 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-02-25 16:26:54 +03:00
|
|
|
memcpy(buf, randbuf, BLOCKSZ);
|
2016-12-17 01:11:29 +03:00
|
|
|
if (i == 0)
|
2022-02-25 16:26:54 +03:00
|
|
|
memset(buf, 0, BLOCKSZ - 10);
|
2016-12-17 01:11:29 +03:00
|
|
|
else if (i < 16)
|
2022-02-25 16:26:54 +03:00
|
|
|
memset(buf, 0, BLOCKSZ - i * 512 + 256);
|
2016-12-17 01:11:29 +03:00
|
|
|
/*LINTED: E_BAD_PTR_CAST_ALIGN*/
|
|
|
|
((uint32_t *)buf)[0] = lrand48();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
exit_usage(void)
|
|
|
|
{
|
2022-02-25 16:26:54 +03:00
|
|
|
(void) puts("usage: randwritecomp [-s] file [nwrites]");
|
2016-12-17 01:11:29 +03:00
|
|
|
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);
|
|
|
|
}
|