Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/file/randwritecomp.c
48674 views
// SPDX-License-Identifier: CDDL-1.01/*2* This file and its contents are supplied under the terms of the3* Common Development and Distribution License ("CDDL"), version 1.0.4* You may only use this file in accordance with the terms of version5* 1.0 of the CDDL.6*7* A full copy of the text of the CDDL should have accompanied this8* source. A copy of the CDDL is also available via the Internet at9* http://www.illumos.org/license/CDDL.10*/1112/*13* Copyright (c) 2017 by Delphix. All rights reserved.14*/1516#include <stdint.h>17#include <string.h>18#include "file_common.h"1920/*21* The following sample was derived from real-world data22* of a production Oracle database.23*/24static const uint64_t size_distribution[] = {250,261499018,27352084,281503485,294206227,305626657,315387001,323733756,332233094,34874652,35238635,3681434,3733357,3813106,392009,401,4123660,42};434445static uint64_t distribution_n;4647static uint8_t randbuf[BLOCKSZ];4849static void50rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)51{52size_t nleft = nbytes;53ssize_t nwrite = 0;5455nwrite = pwrite(fd, buf, nbytes, offset);56if (nwrite < 0) {57perror("pwrite");58exit(EXIT_FAILURE);59}6061nleft -= nwrite;62if (nleft != 0) {63(void) fprintf(stderr, "warning: pwrite: "64"wrote %zu out of %zu bytes\n",65(nbytes - nleft), nbytes);66}67}6869static void70fillbuf(char *buf)71{72uint64_t rv = lrand48() % distribution_n;73uint64_t sum = 0;7475uint64_t i;76for (i = 0;77i < sizeof (size_distribution) / sizeof (size_distribution[0]);78i++) {79sum += size_distribution[i];80if (rv < sum)81break;82}8384memcpy(buf, randbuf, BLOCKSZ);85if (i == 0)86memset(buf, 0, BLOCKSZ - 10);87else if (i < 16)88memset(buf, 0, BLOCKSZ - i * 512 + 256);89/*LINTED: E_BAD_PTR_CAST_ALIGN*/90((uint32_t *)buf)[0] = lrand48();91}9293static void94exit_usage(void)95{96(void) puts("usage: randwritecomp [-s] file [nwrites]");97exit(EXIT_FAILURE);98}99100static void101sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n)102{103for (int64_t i = 0; n == -1 || i < n; i++) {104fillbuf(buf);105106static uint64_t j = 0;107if (j == 0)108j = lrand48() % nblocks;109rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ);110j++;111if (j >= nblocks)112j = 0;113}114}115116static void117random_writes(int fd, char *buf, uint64_t nblocks, int64_t n)118{119for (int64_t i = 0; n == -1 || i < n; i++) {120fillbuf(buf);121rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ);122}123}124125int126main(int argc, char *argv[])127{128int fd, err;129char *filename = NULL;130char buf[BLOCKSZ];131struct stat ss;132uint64_t nblocks;133int64_t n = -1;134int sequential = 0;135136if (argc < 2)137exit_usage();138139argv++;140if (strcmp("-s", argv[0]) == 0) {141sequential = 1;142argv++;143}144145if (argv[0] == NULL)146exit_usage();147else148filename = argv[0];149150argv++;151if (argv[0] != NULL)152n = strtoull(argv[0], NULL, 0);153154fd = open(filename, O_RDWR|O_CREAT, 0666);155if (fd == -1) {156(void) fprintf(stderr, "open(%s) failed: %s\n", filename,157strerror(errno));158exit(EXIT_FAILURE);159}160err = fstat(fd, &ss);161if (err != 0) {162(void) fprintf(stderr,163"error: fstat returned error code %d\n", err);164exit(EXIT_FAILURE);165}166167nblocks = ss.st_size / BLOCKSZ;168if (nblocks == 0) {169(void) fprintf(stderr, "error: "170"file is too small (min allowed size is %d bytes)\n",171BLOCKSZ);172exit(EXIT_FAILURE);173}174175srand48(getpid());176for (int i = 0; i < BLOCKSZ; i++)177randbuf[i] = lrand48();178179distribution_n = 0;180for (uint64_t i = 0;181i < sizeof (size_distribution) / sizeof (size_distribution[0]);182i++) {183distribution_n += size_distribution[i];184}185186if (sequential)187sequential_writes(fd, buf, nblocks, n);188else189random_writes(fd, buf, nblocks, n);190191return (0);192}193194195