1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (C) 1991, NeXT Computer, Inc. All Rights Reserverd. 3f08c3bdfSopenharmony_ci * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved. 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * @APPLE_LICENSE_HEADER_START@ 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * The contents of this file constitute Original Code as defined in and 8f08c3bdfSopenharmony_ci * are subject to the Apple Public Source License Version 1.1 (the 9f08c3bdfSopenharmony_ci * "License"). You may not use this file except in compliance with the 10f08c3bdfSopenharmony_ci * License. Please obtain a copy of the License at 11f08c3bdfSopenharmony_ci * http://www.apple.com/publicsource and read it before using this file. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * This Original Code and all software distributed under the License are 14f08c3bdfSopenharmony_ci * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15f08c3bdfSopenharmony_ci * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16f08c3bdfSopenharmony_ci * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17f08c3bdfSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 18f08c3bdfSopenharmony_ci * License for the specific language governing rights and limitations 19f08c3bdfSopenharmony_ci * under the License. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * @APPLE_LICENSE_HEADER_END@ 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * File: fsx.c 24f08c3bdfSopenharmony_ci * Author: Avadis Tevanian, Jr. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * File system exerciser. 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * Rewrite and enhancements 1998-2001 Conrad Minshall -- conrad@mac.com 29f08c3bdfSopenharmony_ci * 30f08c3bdfSopenharmony_ci * Various features from Joe Sokol, Pat Dirks, and Clark Warner. 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * Small changes to work under Linux -- davej@suse.de 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci * Sundry porting patches from Guy Harris 12/2001 35f08c3bdfSopenharmony_ci * $FreeBSD: src/tools/regression/fsx/fsx.c,v 1.1 2001/12/20 04:15:57 jkh Exp $ 36f08c3bdfSopenharmony_ci * 37f08c3bdfSopenharmony_ci * Add multi-file testing feature -- Zach Brown <zab@clusterfs.com> 38f08c3bdfSopenharmony_ci */ 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci#include <sys/types.h> 41f08c3bdfSopenharmony_ci#include <sys/stat.h> 42f08c3bdfSopenharmony_ci#if defined(_UWIN) || defined(__linux__) 43f08c3bdfSopenharmony_ci#include <sys/param.h> 44f08c3bdfSopenharmony_ci#include <limits.h> 45f08c3bdfSopenharmony_ci#include <time.h> 46f08c3bdfSopenharmony_ci#include <string.h> 47f08c3bdfSopenharmony_ci#include <sys/time.h> 48f08c3bdfSopenharmony_ci#endif 49f08c3bdfSopenharmony_ci#include <fcntl.h> 50f08c3bdfSopenharmony_ci#include <sys/mman.h> 51f08c3bdfSopenharmony_ci#ifndef MAP_FILE 52f08c3bdfSopenharmony_ci#define MAP_FILE 0 53f08c3bdfSopenharmony_ci#endif 54f08c3bdfSopenharmony_ci#include <limits.h> 55f08c3bdfSopenharmony_ci#include <signal.h> 56f08c3bdfSopenharmony_ci#include <stdio.h> 57f08c3bdfSopenharmony_ci#include <stdlib.h> 58f08c3bdfSopenharmony_ci#include <string.h> 59f08c3bdfSopenharmony_ci#include <unistd.h> 60f08c3bdfSopenharmony_ci#include <stdarg.h> 61f08c3bdfSopenharmony_ci#include <errno.h> 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci/* 64f08c3bdfSopenharmony_ci * A log entry is an operation and a bunch of arguments. 65f08c3bdfSopenharmony_ci */ 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_cistruct log_entry { 68f08c3bdfSopenharmony_ci int operation; 69f08c3bdfSopenharmony_ci struct timeval tv; 70f08c3bdfSopenharmony_ci int args[3]; 71f08c3bdfSopenharmony_ci}; 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci#define LOGSIZE 1000 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_cistruct log_entry oplog[LOGSIZE]; /* the log */ 76f08c3bdfSopenharmony_ciint logptr = 0; /* current position in log */ 77f08c3bdfSopenharmony_ciint logcount = 0; /* total ops */ 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci/* 80f08c3bdfSopenharmony_ci * Define operations 81f08c3bdfSopenharmony_ci */ 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci#define OP_READ 1 84f08c3bdfSopenharmony_ci#define OP_WRITE 2 85f08c3bdfSopenharmony_ci#define OP_TRUNCATE 3 86f08c3bdfSopenharmony_ci#define OP_CLOSEOPEN 4 87f08c3bdfSopenharmony_ci#define OP_MAPREAD 5 88f08c3bdfSopenharmony_ci#define OP_MAPWRITE 6 89f08c3bdfSopenharmony_ci#define OP_SKIPPED 7 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ciint page_size; 92f08c3bdfSopenharmony_ciint page_mask; 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cichar *original_buf; /* a pointer to the original data */ 95f08c3bdfSopenharmony_cichar *good_buf; /* a pointer to the correct data */ 96f08c3bdfSopenharmony_cichar *temp_buf; /* a pointer to the current data */ 97f08c3bdfSopenharmony_cichar *fname; /* name of our test file */ 98f08c3bdfSopenharmony_cichar logfile[1024]; /* name of our log file */ 99f08c3bdfSopenharmony_cichar goodfile[1024]; /* name of our test file */ 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_cioff_t file_size = 0; 102f08c3bdfSopenharmony_cioff_t biggest = 0; 103f08c3bdfSopenharmony_cichar state[256]; 104f08c3bdfSopenharmony_ciunsigned long testcalls = 0; /* calls to function "test" */ 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ciunsigned long simulatedopcount = 0; /* -b flag */ 107f08c3bdfSopenharmony_ciint closeprob = 0; /* -c flag */ 108f08c3bdfSopenharmony_ciint debug = 0; /* -d flag */ 109f08c3bdfSopenharmony_ciunsigned long debugstart = 0; /* -D flag */ 110f08c3bdfSopenharmony_ciunsigned long maxfilelen = 256 * 1024; /* -l flag */ 111f08c3bdfSopenharmony_ciint sizechecks = 1; /* -n flag disables them */ 112f08c3bdfSopenharmony_ciint maxoplen = 64 * 1024; /* -o flag */ 113f08c3bdfSopenharmony_ciint quiet = 0; /* -q flag */ 114f08c3bdfSopenharmony_ciunsigned long progressinterval = 0; /* -p flag */ 115f08c3bdfSopenharmony_ciint readbdy = 1; /* -r flag */ 116f08c3bdfSopenharmony_ciint style = 0; /* -s flag */ 117f08c3bdfSopenharmony_ciint truncbdy = 1; /* -t flag */ 118f08c3bdfSopenharmony_ciint writebdy = 1; /* -w flag */ 119f08c3bdfSopenharmony_cilong monitorstart = -1; /* -m flag */ 120f08c3bdfSopenharmony_cilong monitorend = -1; /* -m flag */ 121f08c3bdfSopenharmony_ciint lite = 0; /* -L flag */ 122f08c3bdfSopenharmony_cilong numops = -1; /* -N flag */ 123f08c3bdfSopenharmony_ciint randomoplen = 1; /* -O flag disables it */ 124f08c3bdfSopenharmony_ciint seed = 1; /* -S flag */ 125f08c3bdfSopenharmony_ciint mapped_writes = 1; /* -W flag disables */ 126f08c3bdfSopenharmony_ciint mapped_reads = 1; /* -R flag disables it */ 127f08c3bdfSopenharmony_ciint fsxgoodfd = 0; 128f08c3bdfSopenharmony_ciFILE *fsxlogf = NULL; 129f08c3bdfSopenharmony_ciint badoff = -1; 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_civoid vwarnc(int code,const char *fmt, va_list ap) 132f08c3bdfSopenharmony_ci{ 133f08c3bdfSopenharmony_ci fprintf(stderr, "fsx: "); 134f08c3bdfSopenharmony_ci if (fmt != NULL) { 135f08c3bdfSopenharmony_ci vfprintf(stderr, fmt, ap); 136f08c3bdfSopenharmony_ci fprintf(stderr, ": "); 137f08c3bdfSopenharmony_ci } 138f08c3bdfSopenharmony_ci fprintf(stderr, "%s\n", strerror(code)); 139f08c3bdfSopenharmony_ci} 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_civoid warn(const char *fmt, ...) 142f08c3bdfSopenharmony_ci{ 143f08c3bdfSopenharmony_ci va_list ap; 144f08c3bdfSopenharmony_ci va_start(ap, fmt); 145f08c3bdfSopenharmony_ci vwarnc(errno, fmt, ap); 146f08c3bdfSopenharmony_ci va_end(ap); 147f08c3bdfSopenharmony_ci} 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_civoid 150f08c3bdfSopenharmony_ci __attribute__ ((format(printf, 1, 2))) 151f08c3bdfSopenharmony_ci prt(char *fmt, ...) 152f08c3bdfSopenharmony_ci{ 153f08c3bdfSopenharmony_ci va_list args; 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci va_start(args, fmt); 156f08c3bdfSopenharmony_ci vfprintf(stdout, fmt, args); 157f08c3bdfSopenharmony_ci va_end(args); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci if (fsxlogf) { 160f08c3bdfSopenharmony_ci va_start(args, fmt); 161f08c3bdfSopenharmony_ci vfprintf(fsxlogf, fmt, args); 162f08c3bdfSopenharmony_ci va_end(args); 163f08c3bdfSopenharmony_ci } 164f08c3bdfSopenharmony_ci} 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_civoid prterr(char *prefix) 167f08c3bdfSopenharmony_ci{ 168f08c3bdfSopenharmony_ci prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno)); 169f08c3bdfSopenharmony_ci} 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_civoid log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv) 172f08c3bdfSopenharmony_ci{ 173f08c3bdfSopenharmony_ci struct log_entry *le; 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci le = &oplog[logptr]; 176f08c3bdfSopenharmony_ci le->tv = *tv; 177f08c3bdfSopenharmony_ci le->operation = operation; 178f08c3bdfSopenharmony_ci le->args[0] = arg0; 179f08c3bdfSopenharmony_ci le->args[1] = arg1; 180f08c3bdfSopenharmony_ci le->args[2] = arg2; 181f08c3bdfSopenharmony_ci logptr++; 182f08c3bdfSopenharmony_ci logcount++; 183f08c3bdfSopenharmony_ci if (logptr >= LOGSIZE) 184f08c3bdfSopenharmony_ci logptr = 0; 185f08c3bdfSopenharmony_ci} 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_civoid logdump(void) 188f08c3bdfSopenharmony_ci{ 189f08c3bdfSopenharmony_ci int i, count, down; 190f08c3bdfSopenharmony_ci struct log_entry *lp; 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci prt("LOG DUMP (%d total operations):\n", logcount); 193f08c3bdfSopenharmony_ci if (logcount < LOGSIZE) { 194f08c3bdfSopenharmony_ci i = 0; 195f08c3bdfSopenharmony_ci count = logcount; 196f08c3bdfSopenharmony_ci } else { 197f08c3bdfSopenharmony_ci i = logptr; 198f08c3bdfSopenharmony_ci count = LOGSIZE; 199f08c3bdfSopenharmony_ci } 200f08c3bdfSopenharmony_ci for (; count > 0; count--) { 201f08c3bdfSopenharmony_ci int opnum; 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci opnum = i + 1 + (logcount / LOGSIZE) * LOGSIZE; 204f08c3bdfSopenharmony_ci lp = &oplog[i]; 205f08c3bdfSopenharmony_ci prt("%d: %lu.%06lu ", opnum, lp->tv.tv_sec, lp->tv.tv_usec); 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci switch (lp->operation) { 208f08c3bdfSopenharmony_ci case OP_MAPREAD: 209f08c3bdfSopenharmony_ci prt("MAPREAD 0x%x thru 0x%x (0x%x bytes)", 210f08c3bdfSopenharmony_ci lp->args[0], lp->args[0] + lp->args[1] - 1, 211f08c3bdfSopenharmony_ci lp->args[1]); 212f08c3bdfSopenharmony_ci if (badoff >= lp->args[0] && badoff < 213f08c3bdfSopenharmony_ci lp->args[0] + lp->args[1]) 214f08c3bdfSopenharmony_ci prt("\t***RRRR***"); 215f08c3bdfSopenharmony_ci break; 216f08c3bdfSopenharmony_ci case OP_MAPWRITE: 217f08c3bdfSopenharmony_ci prt("MAPWRITE 0x%x thru 0x%x (0x%x bytes)", 218f08c3bdfSopenharmony_ci lp->args[0], lp->args[0] + lp->args[1] - 1, 219f08c3bdfSopenharmony_ci lp->args[1]); 220f08c3bdfSopenharmony_ci if (badoff >= lp->args[0] && badoff < 221f08c3bdfSopenharmony_ci lp->args[0] + lp->args[1]) 222f08c3bdfSopenharmony_ci prt("\t******WWWW"); 223f08c3bdfSopenharmony_ci break; 224f08c3bdfSopenharmony_ci case OP_READ: 225f08c3bdfSopenharmony_ci prt("READ 0x%x thru 0x%x (0x%x bytes)", 226f08c3bdfSopenharmony_ci lp->args[0], lp->args[0] + lp->args[1] - 1, 227f08c3bdfSopenharmony_ci lp->args[1]); 228f08c3bdfSopenharmony_ci if (badoff >= lp->args[0] && 229f08c3bdfSopenharmony_ci badoff < lp->args[0] + lp->args[1]) 230f08c3bdfSopenharmony_ci prt("\t***RRRR***"); 231f08c3bdfSopenharmony_ci break; 232f08c3bdfSopenharmony_ci case OP_WRITE: 233f08c3bdfSopenharmony_ci prt("WRITE 0x%x thru 0x%x (0x%x bytes)", 234f08c3bdfSopenharmony_ci lp->args[0], lp->args[0] + lp->args[1] - 1, 235f08c3bdfSopenharmony_ci lp->args[1]); 236f08c3bdfSopenharmony_ci if (lp->args[0] > lp->args[2]) 237f08c3bdfSopenharmony_ci prt(" HOLE"); 238f08c3bdfSopenharmony_ci else if (lp->args[0] + lp->args[1] > lp->args[2]) 239f08c3bdfSopenharmony_ci prt(" EXTEND"); 240f08c3bdfSopenharmony_ci if ((badoff >= lp->args[0] || badoff >= lp->args[2]) && 241f08c3bdfSopenharmony_ci badoff < lp->args[0] + lp->args[1]) 242f08c3bdfSopenharmony_ci prt("\t***WWWW"); 243f08c3bdfSopenharmony_ci break; 244f08c3bdfSopenharmony_ci case OP_TRUNCATE: 245f08c3bdfSopenharmony_ci down = lp->args[0] < lp->args[1]; 246f08c3bdfSopenharmony_ci prt("TRUNCATE %s\tfrom 0x%x to 0x%x", 247f08c3bdfSopenharmony_ci down ? "DOWN" : "UP", lp->args[1], lp->args[0]); 248f08c3bdfSopenharmony_ci if (badoff >= lp->args[!down] && 249f08c3bdfSopenharmony_ci badoff < lp->args[! !down]) 250f08c3bdfSopenharmony_ci prt("\t******WWWW"); 251f08c3bdfSopenharmony_ci break; 252f08c3bdfSopenharmony_ci case OP_CLOSEOPEN: 253f08c3bdfSopenharmony_ci prt("CLOSE/OPEN"); 254f08c3bdfSopenharmony_ci break; 255f08c3bdfSopenharmony_ci case OP_SKIPPED: 256f08c3bdfSopenharmony_ci prt("SKIPPED (no operation)"); 257f08c3bdfSopenharmony_ci break; 258f08c3bdfSopenharmony_ci default: 259f08c3bdfSopenharmony_ci prt("BOGUS LOG ENTRY (operation code = %d)!", 260f08c3bdfSopenharmony_ci lp->operation); 261f08c3bdfSopenharmony_ci } 262f08c3bdfSopenharmony_ci prt("\n"); 263f08c3bdfSopenharmony_ci i++; 264f08c3bdfSopenharmony_ci if (i == LOGSIZE) 265f08c3bdfSopenharmony_ci i = 0; 266f08c3bdfSopenharmony_ci } 267f08c3bdfSopenharmony_ci} 268f08c3bdfSopenharmony_ci 269f08c3bdfSopenharmony_civoid save_buffer(char *buffer, off_t bufferlength, int fd) 270f08c3bdfSopenharmony_ci{ 271f08c3bdfSopenharmony_ci off_t ret; 272f08c3bdfSopenharmony_ci ssize_t byteswritten; 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci if (fd <= 0 || bufferlength == 0) 275f08c3bdfSopenharmony_ci return; 276f08c3bdfSopenharmony_ci 277f08c3bdfSopenharmony_ci if (bufferlength > INT_MAX) { 278f08c3bdfSopenharmony_ci prt("fsx flaw: overflow in save_buffer\n"); 279f08c3bdfSopenharmony_ci exit(67); 280f08c3bdfSopenharmony_ci } 281f08c3bdfSopenharmony_ci if (lite) { 282f08c3bdfSopenharmony_ci off_t size_by_seek = lseek(fd, (off_t) 0, SEEK_END); 283f08c3bdfSopenharmony_ci if (size_by_seek == (off_t) - 1) 284f08c3bdfSopenharmony_ci prterr("save_buffer: lseek eof"); 285f08c3bdfSopenharmony_ci else if (bufferlength > size_by_seek) { 286f08c3bdfSopenharmony_ci warn("save_buffer: .fsxgood file too short... will " 287f08c3bdfSopenharmony_ci "save 0x%llx bytes instead of 0x%llx\n", 288f08c3bdfSopenharmony_ci (unsigned long long)size_by_seek, 289f08c3bdfSopenharmony_ci (unsigned long long)bufferlength); 290f08c3bdfSopenharmony_ci bufferlength = size_by_seek; 291f08c3bdfSopenharmony_ci } 292f08c3bdfSopenharmony_ci } 293f08c3bdfSopenharmony_ci 294f08c3bdfSopenharmony_ci ret = lseek(fd, (off_t) 0, SEEK_SET); 295f08c3bdfSopenharmony_ci if (ret == (off_t) - 1) 296f08c3bdfSopenharmony_ci prterr("save_buffer: lseek 0"); 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci byteswritten = write(fd, buffer, (size_t) bufferlength); 299f08c3bdfSopenharmony_ci if (byteswritten != bufferlength) { 300f08c3bdfSopenharmony_ci if (byteswritten == -1) 301f08c3bdfSopenharmony_ci prterr("save_buffer write"); 302f08c3bdfSopenharmony_ci else 303f08c3bdfSopenharmony_ci warn("save_buffer: short write, 0x%x bytes instead " 304f08c3bdfSopenharmony_ci "of 0x%llx\n", 305f08c3bdfSopenharmony_ci (unsigned)byteswritten, 306f08c3bdfSopenharmony_ci (unsigned long long)bufferlength); 307f08c3bdfSopenharmony_ci } 308f08c3bdfSopenharmony_ci} 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_civoid report_failure(int status) 311f08c3bdfSopenharmony_ci{ 312f08c3bdfSopenharmony_ci logdump(); 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci if (fsxgoodfd) { 315f08c3bdfSopenharmony_ci if (good_buf) { 316f08c3bdfSopenharmony_ci save_buffer(good_buf, file_size, fsxgoodfd); 317f08c3bdfSopenharmony_ci prt("Correct content saved for comparison\n"); 318f08c3bdfSopenharmony_ci prt("(maybe hexdump \"%s\" vs \"%s\")\n", 319f08c3bdfSopenharmony_ci fname, goodfile); 320f08c3bdfSopenharmony_ci } 321f08c3bdfSopenharmony_ci close(fsxgoodfd); 322f08c3bdfSopenharmony_ci } 323f08c3bdfSopenharmony_ci exit(status); 324f08c3bdfSopenharmony_ci} 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci#define short_at(cp) ((unsigned short)((*((unsigned char *)(cp)) << 8) | \ 327f08c3bdfSopenharmony_ci *(((unsigned char *)(cp)) + 1))) 328f08c3bdfSopenharmony_ci 329f08c3bdfSopenharmony_civoid check_buffers(unsigned offset, unsigned size) 330f08c3bdfSopenharmony_ci{ 331f08c3bdfSopenharmony_ci unsigned char c, t; 332f08c3bdfSopenharmony_ci unsigned i = 0; 333f08c3bdfSopenharmony_ci unsigned n = 0; 334f08c3bdfSopenharmony_ci unsigned op = 0; 335f08c3bdfSopenharmony_ci unsigned bad = 0; 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci if (memcmp(good_buf + offset, temp_buf, size) != 0) { 338f08c3bdfSopenharmony_ci prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n", 339f08c3bdfSopenharmony_ci offset, size); 340f08c3bdfSopenharmony_ci prt("OFFSET\tGOOD\tBAD\tRANGE\n"); 341f08c3bdfSopenharmony_ci while (size > 0) { 342f08c3bdfSopenharmony_ci c = good_buf[offset]; 343f08c3bdfSopenharmony_ci t = temp_buf[i]; 344f08c3bdfSopenharmony_ci if (c != t) { 345f08c3bdfSopenharmony_ci if (n == 0) { 346f08c3bdfSopenharmony_ci bad = short_at(&temp_buf[i]); 347f08c3bdfSopenharmony_ci prt("%#07x\t%#06x\t%#06x", offset, 348f08c3bdfSopenharmony_ci short_at(&good_buf[offset]), bad); 349f08c3bdfSopenharmony_ci op = temp_buf[offset & 1 ? i + 1 : i]; 350f08c3bdfSopenharmony_ci } 351f08c3bdfSopenharmony_ci n++; 352f08c3bdfSopenharmony_ci badoff = offset; 353f08c3bdfSopenharmony_ci } 354f08c3bdfSopenharmony_ci offset++; 355f08c3bdfSopenharmony_ci i++; 356f08c3bdfSopenharmony_ci size--; 357f08c3bdfSopenharmony_ci } 358f08c3bdfSopenharmony_ci if (n) { 359f08c3bdfSopenharmony_ci prt("\t%#7x\n", n); 360f08c3bdfSopenharmony_ci if (bad) 361f08c3bdfSopenharmony_ci prt("operation# (mod 256) for the bad data " 362f08c3bdfSopenharmony_ci "may be %u\n", ((unsigned)op & 0xff)); 363f08c3bdfSopenharmony_ci else 364f08c3bdfSopenharmony_ci prt("operation# (mod 256) for the bad data " 365f08c3bdfSopenharmony_ci "unknown, check HOLE and EXTEND ops\n"); 366f08c3bdfSopenharmony_ci } else 367f08c3bdfSopenharmony_ci prt("????????????????\n"); 368f08c3bdfSopenharmony_ci report_failure(110); 369f08c3bdfSopenharmony_ci } 370f08c3bdfSopenharmony_ci} 371f08c3bdfSopenharmony_ci 372f08c3bdfSopenharmony_cistruct test_file { 373f08c3bdfSopenharmony_ci char *path; 374f08c3bdfSopenharmony_ci int fd; 375f08c3bdfSopenharmony_ci} *test_files = NULL; 376f08c3bdfSopenharmony_ci 377f08c3bdfSopenharmony_ciint num_test_files = 0; 378f08c3bdfSopenharmony_cienum fd_iteration_policy { 379f08c3bdfSopenharmony_ci FD_SINGLE, 380f08c3bdfSopenharmony_ci FD_ROTATE, 381f08c3bdfSopenharmony_ci FD_RANDOM, 382f08c3bdfSopenharmony_ci}; 383f08c3bdfSopenharmony_ciint fd_policy = FD_RANDOM; 384f08c3bdfSopenharmony_ciint fd_last = 0; 385f08c3bdfSopenharmony_ci 386f08c3bdfSopenharmony_cistruct test_file *get_tf(void) 387f08c3bdfSopenharmony_ci{ 388f08c3bdfSopenharmony_ci unsigned index = 0; 389f08c3bdfSopenharmony_ci 390f08c3bdfSopenharmony_ci switch (fd_policy) { 391f08c3bdfSopenharmony_ci case FD_ROTATE: 392f08c3bdfSopenharmony_ci index = fd_last++; 393f08c3bdfSopenharmony_ci break; 394f08c3bdfSopenharmony_ci case FD_RANDOM: 395f08c3bdfSopenharmony_ci index = random(); 396f08c3bdfSopenharmony_ci break; 397f08c3bdfSopenharmony_ci case FD_SINGLE: 398f08c3bdfSopenharmony_ci index = 0; 399f08c3bdfSopenharmony_ci break; 400f08c3bdfSopenharmony_ci default: 401f08c3bdfSopenharmony_ci prt("unknown policy"); 402f08c3bdfSopenharmony_ci exit(1); 403f08c3bdfSopenharmony_ci break; 404f08c3bdfSopenharmony_ci } 405f08c3bdfSopenharmony_ci return &test_files[index % num_test_files]; 406f08c3bdfSopenharmony_ci} 407f08c3bdfSopenharmony_ci 408f08c3bdfSopenharmony_civoid assign_fd_policy(char *policy) 409f08c3bdfSopenharmony_ci{ 410f08c3bdfSopenharmony_ci if (!strcmp(policy, "random")) 411f08c3bdfSopenharmony_ci fd_policy = FD_RANDOM; 412f08c3bdfSopenharmony_ci else if (!strcmp(policy, "rotate")) 413f08c3bdfSopenharmony_ci fd_policy = FD_ROTATE; 414f08c3bdfSopenharmony_ci else { 415f08c3bdfSopenharmony_ci prt("unknown -I policy: '%s'\n", policy); 416f08c3bdfSopenharmony_ci exit(1); 417f08c3bdfSopenharmony_ci } 418f08c3bdfSopenharmony_ci} 419f08c3bdfSopenharmony_ci 420f08c3bdfSopenharmony_ciint get_fd(void) 421f08c3bdfSopenharmony_ci{ 422f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 423f08c3bdfSopenharmony_ci return tf->fd; 424f08c3bdfSopenharmony_ci} 425f08c3bdfSopenharmony_ci 426f08c3bdfSopenharmony_civoid open_test_files(char **argv, int argc) 427f08c3bdfSopenharmony_ci{ 428f08c3bdfSopenharmony_ci struct test_file *tf; 429f08c3bdfSopenharmony_ci int i; 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci num_test_files = argc; 432f08c3bdfSopenharmony_ci if (num_test_files == 1) 433f08c3bdfSopenharmony_ci fd_policy = FD_SINGLE; 434f08c3bdfSopenharmony_ci 435f08c3bdfSopenharmony_ci test_files = calloc(num_test_files, sizeof(*test_files)); 436f08c3bdfSopenharmony_ci if (test_files == NULL) { 437f08c3bdfSopenharmony_ci prterr("reallocating space for test files"); 438f08c3bdfSopenharmony_ci exit(1); 439f08c3bdfSopenharmony_ci } 440f08c3bdfSopenharmony_ci 441f08c3bdfSopenharmony_ci for (i = 0, tf = test_files; i < num_test_files; i++, tf++) { 442f08c3bdfSopenharmony_ci 443f08c3bdfSopenharmony_ci tf->path = argv[i]; 444f08c3bdfSopenharmony_ci tf->fd = open(tf->path, O_RDWR | (lite ? 0 : O_CREAT | O_TRUNC), 445f08c3bdfSopenharmony_ci 0666); 446f08c3bdfSopenharmony_ci if (tf->fd < 0) { 447f08c3bdfSopenharmony_ci prterr(tf->path); 448f08c3bdfSopenharmony_ci exit(91); 449f08c3bdfSopenharmony_ci } 450f08c3bdfSopenharmony_ci } 451f08c3bdfSopenharmony_ci 452f08c3bdfSopenharmony_ci if (quiet || fd_policy == FD_SINGLE) 453f08c3bdfSopenharmony_ci return; 454f08c3bdfSopenharmony_ci 455f08c3bdfSopenharmony_ci for (i = 0, tf = test_files; i < num_test_files; i++, tf++) 456f08c3bdfSopenharmony_ci prt("fd %d: %s\n", i, tf->path); 457f08c3bdfSopenharmony_ci} 458f08c3bdfSopenharmony_ci 459f08c3bdfSopenharmony_civoid close_test_files(void) 460f08c3bdfSopenharmony_ci{ 461f08c3bdfSopenharmony_ci int i; 462f08c3bdfSopenharmony_ci struct test_file *tf; 463f08c3bdfSopenharmony_ci 464f08c3bdfSopenharmony_ci for (i = 0, tf = test_files; i < num_test_files; i++, tf++) { 465f08c3bdfSopenharmony_ci if (close(tf->fd)) { 466f08c3bdfSopenharmony_ci prterr("close"); 467f08c3bdfSopenharmony_ci report_failure(99); 468f08c3bdfSopenharmony_ci } 469f08c3bdfSopenharmony_ci } 470f08c3bdfSopenharmony_ci} 471f08c3bdfSopenharmony_ci 472f08c3bdfSopenharmony_civoid check_size(void) 473f08c3bdfSopenharmony_ci{ 474f08c3bdfSopenharmony_ci struct stat statbuf; 475f08c3bdfSopenharmony_ci off_t size_by_seek; 476f08c3bdfSopenharmony_ci int fd = get_fd(); 477f08c3bdfSopenharmony_ci 478f08c3bdfSopenharmony_ci if (fstat(fd, &statbuf)) { 479f08c3bdfSopenharmony_ci prterr("check_size: fstat"); 480f08c3bdfSopenharmony_ci statbuf.st_size = -1; 481f08c3bdfSopenharmony_ci } 482f08c3bdfSopenharmony_ci size_by_seek = lseek(fd, (off_t) 0, SEEK_END); 483f08c3bdfSopenharmony_ci if (file_size != statbuf.st_size || file_size != size_by_seek) { 484f08c3bdfSopenharmony_ci prt("Size error: expected 0x%llx stat 0x%llx seek 0x%llx\n", 485f08c3bdfSopenharmony_ci (unsigned long long)file_size, 486f08c3bdfSopenharmony_ci (unsigned long long)statbuf.st_size, 487f08c3bdfSopenharmony_ci (unsigned long long)size_by_seek); 488f08c3bdfSopenharmony_ci report_failure(120); 489f08c3bdfSopenharmony_ci } 490f08c3bdfSopenharmony_ci} 491f08c3bdfSopenharmony_ci 492f08c3bdfSopenharmony_civoid check_trunc_hack(void) 493f08c3bdfSopenharmony_ci{ 494f08c3bdfSopenharmony_ci struct stat statbuf; 495f08c3bdfSopenharmony_ci int fd = get_fd(); 496f08c3bdfSopenharmony_ci 497f08c3bdfSopenharmony_ci ftruncate(fd, (off_t) 0); 498f08c3bdfSopenharmony_ci ftruncate(fd, (off_t) 100000); 499f08c3bdfSopenharmony_ci if (fstat(fd, &statbuf)) { 500f08c3bdfSopenharmony_ci prterr("trunc_hack: fstat"); 501f08c3bdfSopenharmony_ci statbuf.st_size = -1; 502f08c3bdfSopenharmony_ci } 503f08c3bdfSopenharmony_ci if (statbuf.st_size != (off_t) 100000) { 504f08c3bdfSopenharmony_ci prt("no extend on truncate! not posix!\n"); 505f08c3bdfSopenharmony_ci exit(130); 506f08c3bdfSopenharmony_ci } 507f08c3bdfSopenharmony_ci ftruncate(fd, 0); 508f08c3bdfSopenharmony_ci} 509f08c3bdfSopenharmony_ci 510f08c3bdfSopenharmony_cistatic char *tf_buf = NULL; 511f08c3bdfSopenharmony_cistatic int max_tf_len = 0; 512f08c3bdfSopenharmony_ci 513f08c3bdfSopenharmony_civoid alloc_tf_buf(void) 514f08c3bdfSopenharmony_ci{ 515f08c3bdfSopenharmony_ci char dummy = '\0'; 516f08c3bdfSopenharmony_ci int highest = num_test_files - 1; 517f08c3bdfSopenharmony_ci int len; 518f08c3bdfSopenharmony_ci 519f08c3bdfSopenharmony_ci len = snprintf(&dummy, 0, "%u ", highest); 520f08c3bdfSopenharmony_ci if (len < 1) { 521f08c3bdfSopenharmony_ci prterr("finding max tf_buf"); 522f08c3bdfSopenharmony_ci exit(1); 523f08c3bdfSopenharmony_ci } 524f08c3bdfSopenharmony_ci len++; 525f08c3bdfSopenharmony_ci tf_buf = malloc(len); 526f08c3bdfSopenharmony_ci if (tf_buf == NULL) { 527f08c3bdfSopenharmony_ci prterr("allocating tf_buf"); 528f08c3bdfSopenharmony_ci exit(1); 529f08c3bdfSopenharmony_ci } 530f08c3bdfSopenharmony_ci max_tf_len = snprintf(tf_buf, len, "%u ", highest); 531f08c3bdfSopenharmony_ci if (max_tf_len < 1) { 532f08c3bdfSopenharmony_ci prterr("fiding max_tv_len\n"); 533f08c3bdfSopenharmony_ci exit(1); 534f08c3bdfSopenharmony_ci } 535f08c3bdfSopenharmony_ci if (max_tf_len != len - 1) { 536f08c3bdfSopenharmony_ci warn("snprintf() gave %d instead of %d?\n", 537f08c3bdfSopenharmony_ci max_tf_len, len - 1); 538f08c3bdfSopenharmony_ci exit(1); 539f08c3bdfSopenharmony_ci } 540f08c3bdfSopenharmony_ci} 541f08c3bdfSopenharmony_ci 542f08c3bdfSopenharmony_cichar *fill_tf_buf(struct test_file *tf) 543f08c3bdfSopenharmony_ci{ 544f08c3bdfSopenharmony_ci if (tf_buf == NULL) 545f08c3bdfSopenharmony_ci alloc_tf_buf(); 546f08c3bdfSopenharmony_ci 547f08c3bdfSopenharmony_ci sprintf(tf_buf, "%lu ", (unsigned long)(tf - test_files)); 548f08c3bdfSopenharmony_ci return tf_buf; 549f08c3bdfSopenharmony_ci} 550f08c3bdfSopenharmony_ci 551f08c3bdfSopenharmony_civoid 552f08c3bdfSopenharmony_cioutput_line(struct test_file *tf, int op, unsigned offset, 553f08c3bdfSopenharmony_ci unsigned size, struct timeval *tv) 554f08c3bdfSopenharmony_ci{ 555f08c3bdfSopenharmony_ci char *tf_num = ""; 556f08c3bdfSopenharmony_ci 557f08c3bdfSopenharmony_ci char *ops[] = { 558f08c3bdfSopenharmony_ci [OP_READ] = "read", 559f08c3bdfSopenharmony_ci [OP_WRITE] = "write", 560f08c3bdfSopenharmony_ci [OP_TRUNCATE] = "trunc from", 561f08c3bdfSopenharmony_ci [OP_MAPREAD] = "mapread", 562f08c3bdfSopenharmony_ci [OP_MAPWRITE] = "mapwrite", 563f08c3bdfSopenharmony_ci }; 564f08c3bdfSopenharmony_ci 565f08c3bdfSopenharmony_ci /* W. */ 566f08c3bdfSopenharmony_ci if (!(!quiet && ((progressinterval && 567f08c3bdfSopenharmony_ci testcalls % progressinterval == 0) || 568f08c3bdfSopenharmony_ci (debug && 569f08c3bdfSopenharmony_ci (monitorstart == -1 || 570f08c3bdfSopenharmony_ci (offset + size > monitorstart && 571f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))))) 572f08c3bdfSopenharmony_ci return; 573f08c3bdfSopenharmony_ci 574f08c3bdfSopenharmony_ci if (fd_policy != FD_SINGLE) 575f08c3bdfSopenharmony_ci tf_num = fill_tf_buf(tf); 576f08c3bdfSopenharmony_ci 577f08c3bdfSopenharmony_ci prt("%06lu %lu.%06lu %.*s%-10s %#08x %s %#08x\t(0x%x bytes)\n", 578f08c3bdfSopenharmony_ci testcalls, tv->tv_sec, tv->tv_usec, max_tf_len, 579f08c3bdfSopenharmony_ci tf_num, ops[op], 580f08c3bdfSopenharmony_ci offset, op == OP_TRUNCATE ? " to " : "thru", 581f08c3bdfSopenharmony_ci offset + size - 1, size); 582f08c3bdfSopenharmony_ci} 583f08c3bdfSopenharmony_ci 584f08c3bdfSopenharmony_civoid doread(unsigned offset, unsigned size) 585f08c3bdfSopenharmony_ci{ 586f08c3bdfSopenharmony_ci struct timeval t; 587f08c3bdfSopenharmony_ci off_t ret; 588f08c3bdfSopenharmony_ci unsigned iret; 589f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 590f08c3bdfSopenharmony_ci int fd = tf->fd; 591f08c3bdfSopenharmony_ci 592f08c3bdfSopenharmony_ci offset -= offset % readbdy; 593f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 594f08c3bdfSopenharmony_ci if (size == 0) { 595f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 596f08c3bdfSopenharmony_ci prt("skipping zero size read\n"); 597f08c3bdfSopenharmony_ci log4(OP_SKIPPED, OP_READ, offset, size, &t); 598f08c3bdfSopenharmony_ci return; 599f08c3bdfSopenharmony_ci } 600f08c3bdfSopenharmony_ci if (size + offset > file_size) { 601f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 602f08c3bdfSopenharmony_ci prt("skipping seek/read past end of file\n"); 603f08c3bdfSopenharmony_ci log4(OP_SKIPPED, OP_READ, offset, size, &t); 604f08c3bdfSopenharmony_ci return; 605f08c3bdfSopenharmony_ci } 606f08c3bdfSopenharmony_ci 607f08c3bdfSopenharmony_ci log4(OP_READ, offset, size, 0, &t); 608f08c3bdfSopenharmony_ci 609f08c3bdfSopenharmony_ci if (testcalls <= simulatedopcount) 610f08c3bdfSopenharmony_ci return; 611f08c3bdfSopenharmony_ci 612f08c3bdfSopenharmony_ci output_line(tf, OP_READ, offset, size, &t); 613f08c3bdfSopenharmony_ci 614f08c3bdfSopenharmony_ci ret = lseek(fd, (off_t) offset, SEEK_SET); 615f08c3bdfSopenharmony_ci if (ret == (off_t) - 1) { 616f08c3bdfSopenharmony_ci prterr("doread: lseek"); 617f08c3bdfSopenharmony_ci report_failure(140); 618f08c3bdfSopenharmony_ci } 619f08c3bdfSopenharmony_ci iret = read(fd, temp_buf, size); 620f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 621f08c3bdfSopenharmony_ci (monitorstart == -1 || 622f08c3bdfSopenharmony_ci (offset + size > monitorstart && 623f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 624f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 625f08c3bdfSopenharmony_ci prt(" %lu.%06lu read done\n", t.tv_sec, t.tv_usec); 626f08c3bdfSopenharmony_ci } 627f08c3bdfSopenharmony_ci if (iret != size) { 628f08c3bdfSopenharmony_ci if (iret == -1) 629f08c3bdfSopenharmony_ci prterr("doread: read"); 630f08c3bdfSopenharmony_ci else 631f08c3bdfSopenharmony_ci prt("short read: 0x%x bytes instead of 0x%x\n", 632f08c3bdfSopenharmony_ci iret, size); 633f08c3bdfSopenharmony_ci report_failure(141); 634f08c3bdfSopenharmony_ci } 635f08c3bdfSopenharmony_ci check_buffers(offset, size); 636f08c3bdfSopenharmony_ci} 637f08c3bdfSopenharmony_ci 638f08c3bdfSopenharmony_civoid domapread(unsigned offset, unsigned size) 639f08c3bdfSopenharmony_ci{ 640f08c3bdfSopenharmony_ci struct timeval t; 641f08c3bdfSopenharmony_ci unsigned pg_offset; 642f08c3bdfSopenharmony_ci unsigned map_size; 643f08c3bdfSopenharmony_ci char *p; 644f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 645f08c3bdfSopenharmony_ci int fd = tf->fd; 646f08c3bdfSopenharmony_ci 647f08c3bdfSopenharmony_ci offset -= offset % readbdy; 648f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 649f08c3bdfSopenharmony_ci if (size == 0) { 650f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 651f08c3bdfSopenharmony_ci prt("skipping zero size read\n"); 652f08c3bdfSopenharmony_ci log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t); 653f08c3bdfSopenharmony_ci return; 654f08c3bdfSopenharmony_ci } 655f08c3bdfSopenharmony_ci if (size + offset > file_size) { 656f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 657f08c3bdfSopenharmony_ci prt("skipping seek/read past end of file\n"); 658f08c3bdfSopenharmony_ci log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t); 659f08c3bdfSopenharmony_ci return; 660f08c3bdfSopenharmony_ci } 661f08c3bdfSopenharmony_ci 662f08c3bdfSopenharmony_ci log4(OP_MAPREAD, offset, size, 0, &t); 663f08c3bdfSopenharmony_ci 664f08c3bdfSopenharmony_ci if (testcalls <= simulatedopcount) 665f08c3bdfSopenharmony_ci return; 666f08c3bdfSopenharmony_ci 667f08c3bdfSopenharmony_ci output_line(tf, OP_MAPREAD, offset, size, &t); 668f08c3bdfSopenharmony_ci 669f08c3bdfSopenharmony_ci pg_offset = offset & page_mask; 670f08c3bdfSopenharmony_ci map_size = pg_offset + size; 671f08c3bdfSopenharmony_ci 672f08c3bdfSopenharmony_ci if ((p = mmap(0, map_size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 673f08c3bdfSopenharmony_ci (off_t) (offset - pg_offset))) == MAP_FAILED) { 674f08c3bdfSopenharmony_ci prterr("domapread: mmap"); 675f08c3bdfSopenharmony_ci report_failure(190); 676f08c3bdfSopenharmony_ci } 677f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 678f08c3bdfSopenharmony_ci (monitorstart == -1 || 679f08c3bdfSopenharmony_ci (offset + size > monitorstart && 680f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 681f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 682f08c3bdfSopenharmony_ci prt(" %lu.%06lu mmap done\n", t.tv_sec, t.tv_usec); 683f08c3bdfSopenharmony_ci } 684f08c3bdfSopenharmony_ci memcpy(temp_buf, p + pg_offset, size); 685f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 686f08c3bdfSopenharmony_ci (monitorstart == -1 || 687f08c3bdfSopenharmony_ci (offset + size > monitorstart && 688f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 689f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 690f08c3bdfSopenharmony_ci prt(" %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec); 691f08c3bdfSopenharmony_ci } 692f08c3bdfSopenharmony_ci if (munmap(p, map_size) != 0) { 693f08c3bdfSopenharmony_ci prterr("domapread: munmap"); 694f08c3bdfSopenharmony_ci report_failure(191); 695f08c3bdfSopenharmony_ci } 696f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 697f08c3bdfSopenharmony_ci (monitorstart == -1 || 698f08c3bdfSopenharmony_ci (offset + size > monitorstart && 699f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 700f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 701f08c3bdfSopenharmony_ci prt(" %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec); 702f08c3bdfSopenharmony_ci } 703f08c3bdfSopenharmony_ci 704f08c3bdfSopenharmony_ci check_buffers(offset, size); 705f08c3bdfSopenharmony_ci} 706f08c3bdfSopenharmony_ci 707f08c3bdfSopenharmony_civoid gendata(char *original_buf, char *good_buf, unsigned offset, unsigned size) 708f08c3bdfSopenharmony_ci{ 709f08c3bdfSopenharmony_ci while (size--) { 710f08c3bdfSopenharmony_ci good_buf[offset] = testcalls % 256; 711f08c3bdfSopenharmony_ci if (offset % 2) 712f08c3bdfSopenharmony_ci good_buf[offset] += original_buf[offset]; 713f08c3bdfSopenharmony_ci offset++; 714f08c3bdfSopenharmony_ci } 715f08c3bdfSopenharmony_ci} 716f08c3bdfSopenharmony_ci 717f08c3bdfSopenharmony_civoid dowrite(unsigned offset, unsigned size) 718f08c3bdfSopenharmony_ci{ 719f08c3bdfSopenharmony_ci struct timeval t; 720f08c3bdfSopenharmony_ci off_t ret; 721f08c3bdfSopenharmony_ci unsigned iret; 722f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 723f08c3bdfSopenharmony_ci int fd = tf->fd; 724f08c3bdfSopenharmony_ci 725f08c3bdfSopenharmony_ci offset -= offset % writebdy; 726f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 727f08c3bdfSopenharmony_ci if (size == 0) { 728f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 729f08c3bdfSopenharmony_ci prt("skipping zero size write\n"); 730f08c3bdfSopenharmony_ci log4(OP_SKIPPED, OP_WRITE, offset, size, &t); 731f08c3bdfSopenharmony_ci return; 732f08c3bdfSopenharmony_ci } 733f08c3bdfSopenharmony_ci 734f08c3bdfSopenharmony_ci log4(OP_WRITE, offset, size, file_size, &t); 735f08c3bdfSopenharmony_ci 736f08c3bdfSopenharmony_ci gendata(original_buf, good_buf, offset, size); 737f08c3bdfSopenharmony_ci if (file_size < offset + size) { 738f08c3bdfSopenharmony_ci if (file_size < offset) 739f08c3bdfSopenharmony_ci memset(good_buf + file_size, '\0', offset - file_size); 740f08c3bdfSopenharmony_ci file_size = offset + size; 741f08c3bdfSopenharmony_ci if (lite) { 742f08c3bdfSopenharmony_ci warn("Lite file size bug in fsx!"); 743f08c3bdfSopenharmony_ci report_failure(149); 744f08c3bdfSopenharmony_ci } 745f08c3bdfSopenharmony_ci } 746f08c3bdfSopenharmony_ci 747f08c3bdfSopenharmony_ci if (testcalls <= simulatedopcount) 748f08c3bdfSopenharmony_ci return; 749f08c3bdfSopenharmony_ci 750f08c3bdfSopenharmony_ci output_line(tf, OP_WRITE, offset, size, &t); 751f08c3bdfSopenharmony_ci 752f08c3bdfSopenharmony_ci ret = lseek(fd, (off_t) offset, SEEK_SET); 753f08c3bdfSopenharmony_ci if (ret == (off_t) - 1) { 754f08c3bdfSopenharmony_ci prterr("dowrite: lseek"); 755f08c3bdfSopenharmony_ci report_failure(150); 756f08c3bdfSopenharmony_ci } 757f08c3bdfSopenharmony_ci iret = write(fd, good_buf + offset, size); 758f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 759f08c3bdfSopenharmony_ci (monitorstart == -1 || 760f08c3bdfSopenharmony_ci (offset + size > monitorstart && 761f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 762f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 763f08c3bdfSopenharmony_ci prt(" %lu.%06lu write done\n", t.tv_sec, t.tv_usec); 764f08c3bdfSopenharmony_ci } 765f08c3bdfSopenharmony_ci if (iret != size) { 766f08c3bdfSopenharmony_ci if (iret == -1) 767f08c3bdfSopenharmony_ci prterr("dowrite: write"); 768f08c3bdfSopenharmony_ci else 769f08c3bdfSopenharmony_ci prt("short write: 0x%x bytes instead of 0x%x\n", 770f08c3bdfSopenharmony_ci iret, size); 771f08c3bdfSopenharmony_ci report_failure(151); 772f08c3bdfSopenharmony_ci } 773f08c3bdfSopenharmony_ci} 774f08c3bdfSopenharmony_ci 775f08c3bdfSopenharmony_civoid domapwrite(unsigned offset, unsigned size) 776f08c3bdfSopenharmony_ci{ 777f08c3bdfSopenharmony_ci struct timeval t; 778f08c3bdfSopenharmony_ci unsigned pg_offset; 779f08c3bdfSopenharmony_ci unsigned map_size; 780f08c3bdfSopenharmony_ci off_t cur_filesize; 781f08c3bdfSopenharmony_ci char *p; 782f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 783f08c3bdfSopenharmony_ci int fd = tf->fd; 784f08c3bdfSopenharmony_ci 785f08c3bdfSopenharmony_ci offset -= offset % writebdy; 786f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 787f08c3bdfSopenharmony_ci if (size == 0) { 788f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 789f08c3bdfSopenharmony_ci prt("skipping zero size write\n"); 790f08c3bdfSopenharmony_ci log4(OP_SKIPPED, OP_MAPWRITE, offset, size, &t); 791f08c3bdfSopenharmony_ci return; 792f08c3bdfSopenharmony_ci } 793f08c3bdfSopenharmony_ci cur_filesize = file_size; 794f08c3bdfSopenharmony_ci 795f08c3bdfSopenharmony_ci log4(OP_MAPWRITE, offset, size, 0, &t); 796f08c3bdfSopenharmony_ci 797f08c3bdfSopenharmony_ci gendata(original_buf, good_buf, offset, size); 798f08c3bdfSopenharmony_ci if (file_size < offset + size) { 799f08c3bdfSopenharmony_ci if (file_size < offset) 800f08c3bdfSopenharmony_ci memset(good_buf + file_size, '\0', offset - file_size); 801f08c3bdfSopenharmony_ci file_size = offset + size; 802f08c3bdfSopenharmony_ci if (lite) { 803f08c3bdfSopenharmony_ci warn("Lite file size bug in fsx!"); 804f08c3bdfSopenharmony_ci report_failure(200); 805f08c3bdfSopenharmony_ci } 806f08c3bdfSopenharmony_ci } 807f08c3bdfSopenharmony_ci 808f08c3bdfSopenharmony_ci if (testcalls <= simulatedopcount) 809f08c3bdfSopenharmony_ci return; 810f08c3bdfSopenharmony_ci 811f08c3bdfSopenharmony_ci output_line(tf, OP_MAPWRITE, offset, size, &t); 812f08c3bdfSopenharmony_ci 813f08c3bdfSopenharmony_ci if (file_size > cur_filesize) { 814f08c3bdfSopenharmony_ci if (ftruncate(fd, file_size) == -1) { 815f08c3bdfSopenharmony_ci prterr("domapwrite: ftruncate"); 816f08c3bdfSopenharmony_ci exit(201); 817f08c3bdfSopenharmony_ci } 818f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 819f08c3bdfSopenharmony_ci (monitorstart == -1 || 820f08c3bdfSopenharmony_ci (offset + size > monitorstart && 821f08c3bdfSopenharmony_ci (monitorend == -1 822f08c3bdfSopenharmony_ci || offset <= monitorend))))) { 823f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 824f08c3bdfSopenharmony_ci prt(" %lu.%06lu truncate done\n", t.tv_sec, 825f08c3bdfSopenharmony_ci t.tv_usec); 826f08c3bdfSopenharmony_ci } 827f08c3bdfSopenharmony_ci } 828f08c3bdfSopenharmony_ci pg_offset = offset & page_mask; 829f08c3bdfSopenharmony_ci map_size = pg_offset + size; 830f08c3bdfSopenharmony_ci 831f08c3bdfSopenharmony_ci if ((p = 832f08c3bdfSopenharmony_ci mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, 833f08c3bdfSopenharmony_ci fd, (off_t) (offset - pg_offset))) == MAP_FAILED) { 834f08c3bdfSopenharmony_ci prterr("domapwrite: mmap"); 835f08c3bdfSopenharmony_ci report_failure(202); 836f08c3bdfSopenharmony_ci } 837f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 838f08c3bdfSopenharmony_ci (monitorstart == -1 || 839f08c3bdfSopenharmony_ci (offset + size > monitorstart && 840f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 841f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 842f08c3bdfSopenharmony_ci prt(" %lu.%06lu mmap done\n", t.tv_sec, t.tv_usec); 843f08c3bdfSopenharmony_ci } 844f08c3bdfSopenharmony_ci memcpy(p + pg_offset, good_buf + offset, size); 845f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 846f08c3bdfSopenharmony_ci (monitorstart == -1 || 847f08c3bdfSopenharmony_ci (offset + size > monitorstart && 848f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 849f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 850f08c3bdfSopenharmony_ci prt(" %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec); 851f08c3bdfSopenharmony_ci } 852f08c3bdfSopenharmony_ci if (msync(p, map_size, 0) != 0) { 853f08c3bdfSopenharmony_ci prterr("domapwrite: msync"); 854f08c3bdfSopenharmony_ci report_failure(203); 855f08c3bdfSopenharmony_ci } 856f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 857f08c3bdfSopenharmony_ci (monitorstart == -1 || 858f08c3bdfSopenharmony_ci (offset + size > monitorstart && 859f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 860f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 861f08c3bdfSopenharmony_ci prt(" %lu.%06lu msync done\n", t.tv_sec, t.tv_usec); 862f08c3bdfSopenharmony_ci } 863f08c3bdfSopenharmony_ci if (munmap(p, map_size) != 0) { 864f08c3bdfSopenharmony_ci prterr("domapwrite: munmap"); 865f08c3bdfSopenharmony_ci report_failure(204); 866f08c3bdfSopenharmony_ci } 867f08c3bdfSopenharmony_ci if (!quiet && (debug > 1 && 868f08c3bdfSopenharmony_ci (monitorstart == -1 || 869f08c3bdfSopenharmony_ci (offset + size > monitorstart && 870f08c3bdfSopenharmony_ci (monitorend == -1 || offset <= monitorend))))) { 871f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 872f08c3bdfSopenharmony_ci prt(" %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec); 873f08c3bdfSopenharmony_ci } 874f08c3bdfSopenharmony_ci} 875f08c3bdfSopenharmony_ci 876f08c3bdfSopenharmony_civoid dotruncate(unsigned size) 877f08c3bdfSopenharmony_ci{ 878f08c3bdfSopenharmony_ci struct timeval t; 879f08c3bdfSopenharmony_ci int oldsize = file_size; 880f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 881f08c3bdfSopenharmony_ci int fd = tf->fd; 882f08c3bdfSopenharmony_ci 883f08c3bdfSopenharmony_ci size -= size % truncbdy; 884f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 885f08c3bdfSopenharmony_ci if (size > biggest) { 886f08c3bdfSopenharmony_ci biggest = size; 887f08c3bdfSopenharmony_ci if (!quiet && testcalls > simulatedopcount) 888f08c3bdfSopenharmony_ci prt("truncating to largest ever: 0x%x\n", size); 889f08c3bdfSopenharmony_ci } 890f08c3bdfSopenharmony_ci 891f08c3bdfSopenharmony_ci log4(OP_TRUNCATE, size, (unsigned)file_size, 0, &t); 892f08c3bdfSopenharmony_ci 893f08c3bdfSopenharmony_ci if (size > file_size) 894f08c3bdfSopenharmony_ci memset(good_buf + file_size, '\0', size - file_size); 895f08c3bdfSopenharmony_ci file_size = size; 896f08c3bdfSopenharmony_ci 897f08c3bdfSopenharmony_ci if (testcalls <= simulatedopcount) 898f08c3bdfSopenharmony_ci return; 899f08c3bdfSopenharmony_ci 900f08c3bdfSopenharmony_ci output_line(tf, OP_TRUNCATE, oldsize, size, &t); 901f08c3bdfSopenharmony_ci 902f08c3bdfSopenharmony_ci if (ftruncate(fd, (off_t) size) == -1) { 903f08c3bdfSopenharmony_ci prt("ftruncate1: %x\n", size); 904f08c3bdfSopenharmony_ci prterr("dotruncate: ftruncate"); 905f08c3bdfSopenharmony_ci report_failure(160); 906f08c3bdfSopenharmony_ci } 907f08c3bdfSopenharmony_ci if (!quiet && debug > 1) { 908f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 909f08c3bdfSopenharmony_ci prt(" %lu.%06lu trunc done\n", t.tv_sec, t.tv_usec); 910f08c3bdfSopenharmony_ci } 911f08c3bdfSopenharmony_ci} 912f08c3bdfSopenharmony_ci 913f08c3bdfSopenharmony_civoid writefileimage(void) 914f08c3bdfSopenharmony_ci{ 915f08c3bdfSopenharmony_ci ssize_t iret; 916f08c3bdfSopenharmony_ci int fd = get_fd(); 917f08c3bdfSopenharmony_ci 918f08c3bdfSopenharmony_ci if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) - 1) { 919f08c3bdfSopenharmony_ci prterr("writefileimage: lseek"); 920f08c3bdfSopenharmony_ci report_failure(171); 921f08c3bdfSopenharmony_ci } 922f08c3bdfSopenharmony_ci iret = write(fd, good_buf, file_size); 923f08c3bdfSopenharmony_ci if ((off_t) iret != file_size) { 924f08c3bdfSopenharmony_ci if (iret == -1) 925f08c3bdfSopenharmony_ci prterr("writefileimage: write"); 926f08c3bdfSopenharmony_ci else 927f08c3bdfSopenharmony_ci prt("short write: 0x%lx bytes instead of 0x%llx\n", 928f08c3bdfSopenharmony_ci (unsigned long)iret, (unsigned long long)file_size); 929f08c3bdfSopenharmony_ci report_failure(172); 930f08c3bdfSopenharmony_ci } 931f08c3bdfSopenharmony_ci if (lite ? 0 : ftruncate(fd, file_size) == -1) { 932f08c3bdfSopenharmony_ci prt("ftruncate2: %llx\n", (unsigned long long)file_size); 933f08c3bdfSopenharmony_ci prterr("writefileimage: ftruncate"); 934f08c3bdfSopenharmony_ci report_failure(173); 935f08c3bdfSopenharmony_ci } 936f08c3bdfSopenharmony_ci} 937f08c3bdfSopenharmony_ci 938f08c3bdfSopenharmony_civoid docloseopen(void) 939f08c3bdfSopenharmony_ci{ 940f08c3bdfSopenharmony_ci struct timeval t; 941f08c3bdfSopenharmony_ci struct test_file *tf = get_tf(); 942f08c3bdfSopenharmony_ci 943f08c3bdfSopenharmony_ci if (testcalls <= simulatedopcount) 944f08c3bdfSopenharmony_ci return; 945f08c3bdfSopenharmony_ci 946f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 947f08c3bdfSopenharmony_ci log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t); 948f08c3bdfSopenharmony_ci 949f08c3bdfSopenharmony_ci if (debug) 950f08c3bdfSopenharmony_ci prt("%06lu %lu.%06lu close/open\n", testcalls, t.tv_sec, 951f08c3bdfSopenharmony_ci t.tv_usec); 952f08c3bdfSopenharmony_ci if (close(tf->fd)) { 953f08c3bdfSopenharmony_ci prterr("docloseopen: close"); 954f08c3bdfSopenharmony_ci report_failure(180); 955f08c3bdfSopenharmony_ci } 956f08c3bdfSopenharmony_ci if (!quiet && debug > 1) { 957f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 958f08c3bdfSopenharmony_ci prt(" %lu.%06lu close done\n", t.tv_sec, t.tv_usec); 959f08c3bdfSopenharmony_ci } 960f08c3bdfSopenharmony_ci tf->fd = open(tf->path, O_RDWR, 0); 961f08c3bdfSopenharmony_ci if (tf->fd < 0) { 962f08c3bdfSopenharmony_ci prterr("docloseopen: open"); 963f08c3bdfSopenharmony_ci report_failure(181); 964f08c3bdfSopenharmony_ci } 965f08c3bdfSopenharmony_ci if (!quiet && debug > 1) { 966f08c3bdfSopenharmony_ci gettimeofday(&t, NULL); 967f08c3bdfSopenharmony_ci prt(" %lu.%06lu open done\n", t.tv_sec, t.tv_usec); 968f08c3bdfSopenharmony_ci } 969f08c3bdfSopenharmony_ci} 970f08c3bdfSopenharmony_ci 971f08c3bdfSopenharmony_civoid test(void) 972f08c3bdfSopenharmony_ci{ 973f08c3bdfSopenharmony_ci unsigned long offset; 974f08c3bdfSopenharmony_ci unsigned long size = maxoplen; 975f08c3bdfSopenharmony_ci unsigned long rv = random(); 976f08c3bdfSopenharmony_ci unsigned long op = rv % (3 + !lite + mapped_writes); 977f08c3bdfSopenharmony_ci 978f08c3bdfSopenharmony_ci /* turn off the map read if necessary */ 979f08c3bdfSopenharmony_ci 980f08c3bdfSopenharmony_ci if (op == 2 && !mapped_reads) 981f08c3bdfSopenharmony_ci op = 0; 982f08c3bdfSopenharmony_ci 983f08c3bdfSopenharmony_ci if (simulatedopcount > 0 && testcalls == simulatedopcount) 984f08c3bdfSopenharmony_ci writefileimage(); 985f08c3bdfSopenharmony_ci 986f08c3bdfSopenharmony_ci testcalls++; 987f08c3bdfSopenharmony_ci 988f08c3bdfSopenharmony_ci if (debugstart > 0 && testcalls >= debugstart) 989f08c3bdfSopenharmony_ci debug = 1; 990f08c3bdfSopenharmony_ci 991f08c3bdfSopenharmony_ci if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0) 992f08c3bdfSopenharmony_ci prt("%lu...\n", testcalls); 993f08c3bdfSopenharmony_ci 994f08c3bdfSopenharmony_ci /* 995f08c3bdfSopenharmony_ci * READ: op = 0 996f08c3bdfSopenharmony_ci * WRITE: op = 1 997f08c3bdfSopenharmony_ci * MAPREAD: op = 2 998f08c3bdfSopenharmony_ci * TRUNCATE: op = 3 999f08c3bdfSopenharmony_ci * MAPWRITE: op = 3 or 4 1000f08c3bdfSopenharmony_ci */ 1001f08c3bdfSopenharmony_ci if (lite ? 0 : op == 3 && (style & 1) == 0) /* vanilla truncate? */ 1002f08c3bdfSopenharmony_ci dotruncate(random() % maxfilelen); 1003f08c3bdfSopenharmony_ci else { 1004f08c3bdfSopenharmony_ci if (randomoplen) 1005f08c3bdfSopenharmony_ci size = random() % (maxoplen + 1); 1006f08c3bdfSopenharmony_ci if (lite ? 0 : op == 3) 1007f08c3bdfSopenharmony_ci dotruncate(size); 1008f08c3bdfSopenharmony_ci else { 1009f08c3bdfSopenharmony_ci offset = random(); 1010f08c3bdfSopenharmony_ci if (op == 1 || op == (lite ? 3 : 4)) { 1011f08c3bdfSopenharmony_ci offset %= maxfilelen; 1012f08c3bdfSopenharmony_ci if (offset + size > maxfilelen) 1013f08c3bdfSopenharmony_ci size = maxfilelen - offset; 1014f08c3bdfSopenharmony_ci if (op != 1) 1015f08c3bdfSopenharmony_ci domapwrite(offset, size); 1016f08c3bdfSopenharmony_ci else 1017f08c3bdfSopenharmony_ci dowrite(offset, size); 1018f08c3bdfSopenharmony_ci } else { 1019f08c3bdfSopenharmony_ci if (file_size) 1020f08c3bdfSopenharmony_ci offset %= file_size; 1021f08c3bdfSopenharmony_ci else 1022f08c3bdfSopenharmony_ci offset = 0; 1023f08c3bdfSopenharmony_ci if (offset + size > file_size) 1024f08c3bdfSopenharmony_ci size = file_size - offset; 1025f08c3bdfSopenharmony_ci if (op != 0) 1026f08c3bdfSopenharmony_ci domapread(offset, size); 1027f08c3bdfSopenharmony_ci else 1028f08c3bdfSopenharmony_ci doread(offset, size); 1029f08c3bdfSopenharmony_ci } 1030f08c3bdfSopenharmony_ci } 1031f08c3bdfSopenharmony_ci } 1032f08c3bdfSopenharmony_ci if (sizechecks && testcalls > simulatedopcount) 1033f08c3bdfSopenharmony_ci check_size(); 1034f08c3bdfSopenharmony_ci if (closeprob && (rv >> 3) < (1 << 28) / closeprob) 1035f08c3bdfSopenharmony_ci docloseopen(); 1036f08c3bdfSopenharmony_ci} 1037f08c3bdfSopenharmony_ci 1038f08c3bdfSopenharmony_civoid cleanup(int sig) 1039f08c3bdfSopenharmony_ci{ 1040f08c3bdfSopenharmony_ci if (sig) 1041f08c3bdfSopenharmony_ci prt("signal %d\n", sig); 1042f08c3bdfSopenharmony_ci prt("testcalls = %lu\n", testcalls); 1043f08c3bdfSopenharmony_ci exit(sig); 1044f08c3bdfSopenharmony_ci} 1045f08c3bdfSopenharmony_ci 1046f08c3bdfSopenharmony_civoid usage(void) 1047f08c3bdfSopenharmony_ci{ 1048f08c3bdfSopenharmony_ci fprintf(stdout, "usage: %s", 1049f08c3bdfSopenharmony_ci "fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m " 1050f08c3bdfSopenharmony_ci "start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t " 1051f08c3bdfSopenharmony_ci "truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] " 1052f08c3bdfSopenharmony_ci "[ -I random|rotate ] fname [additional paths to fname..]\n" 1053f08c3bdfSopenharmony_ci " -b opnum: beginning operation number (default 1)\n" 1054f08c3bdfSopenharmony_ci " -c P: 1 in P chance of file close+open at each op (default infinity)\n" 1055f08c3bdfSopenharmony_ci " -d: debug output for all operations [-d -d = more debugging]\n" 1056f08c3bdfSopenharmony_ci " -l flen: the upper bound on file size (default 262144)\n" 1057f08c3bdfSopenharmony_ci " -m start:end: monitor (print debug) specified byte range (default 0:infinity)\n" 1058f08c3bdfSopenharmony_ci " -n: no verifications of file size\n" 1059f08c3bdfSopenharmony_ci " -o oplen: the upper bound on operation size (default 65536)\n" 1060f08c3bdfSopenharmony_ci " -p progressinterval: debug output at specified operation interval\n" 1061f08c3bdfSopenharmony_ci " -q: quieter operation\n" 1062f08c3bdfSopenharmony_ci " -r readbdy: 4096 would make reads page aligned (default 1)\n" 1063f08c3bdfSopenharmony_ci " -s style: 1 gives smaller truncates (default 0)\n" 1064f08c3bdfSopenharmony_ci " -t truncbdy: 4096 would make truncates page aligned (default 1)\n" 1065f08c3bdfSopenharmony_ci " -w writebdy: 4096 would make writes page aligned (default 1)\n" 1066f08c3bdfSopenharmony_ci " -D startingop: debug output starting at specified operation\n" 1067f08c3bdfSopenharmony_ci " -L: fsxLite - no file creations & no file size changes\n" 1068f08c3bdfSopenharmony_ci " -N numops: total # operations to do (default infinity)\n" 1069f08c3bdfSopenharmony_ci " -O: use oplen (see -o flag) for every op (default random)\n" 1070f08c3bdfSopenharmony_ci " -P: save .fsxlog and .fsxgood files in dirpath (default ./)\n" 1071f08c3bdfSopenharmony_ci " -S seed: for random # generator (default 1) 0 gets timestamp\n" 1072f08c3bdfSopenharmony_ci " -W: mapped write operations DISabled\n" 1073f08c3bdfSopenharmony_ci " -R: read() system calls only (mapped reads disabled)\n" 1074f08c3bdfSopenharmony_ci " -I: When multiple paths to the file are given each operation uses\n" 1075f08c3bdfSopenharmony_ci " a different path. Iterate through them in order with 'rotate'\n" 1076f08c3bdfSopenharmony_ci " or chose then at 'random'. (defaults to random)\n" 1077f08c3bdfSopenharmony_ci " fname: this filename is REQUIRED (no default)\n"); 1078f08c3bdfSopenharmony_ci exit(90); 1079f08c3bdfSopenharmony_ci} 1080f08c3bdfSopenharmony_ci 1081f08c3bdfSopenharmony_ciint getnum(char *s, char **e) 1082f08c3bdfSopenharmony_ci{ 1083f08c3bdfSopenharmony_ci int ret = -1; 1084f08c3bdfSopenharmony_ci 1085f08c3bdfSopenharmony_ci *e = NULL; 1086f08c3bdfSopenharmony_ci ret = strtol(s, e, 0); 1087f08c3bdfSopenharmony_ci if (*e) 1088f08c3bdfSopenharmony_ci switch (**e) { 1089f08c3bdfSopenharmony_ci case 'b': 1090f08c3bdfSopenharmony_ci case 'B': 1091f08c3bdfSopenharmony_ci ret *= 512; 1092f08c3bdfSopenharmony_ci *e = *e + 1; 1093f08c3bdfSopenharmony_ci break; 1094f08c3bdfSopenharmony_ci case 'k': 1095f08c3bdfSopenharmony_ci case 'K': 1096f08c3bdfSopenharmony_ci ret *= 1024; 1097f08c3bdfSopenharmony_ci *e = *e + 1; 1098f08c3bdfSopenharmony_ci break; 1099f08c3bdfSopenharmony_ci case 'm': 1100f08c3bdfSopenharmony_ci case 'M': 1101f08c3bdfSopenharmony_ci ret *= 1024 * 1024; 1102f08c3bdfSopenharmony_ci *e = *e + 1; 1103f08c3bdfSopenharmony_ci break; 1104f08c3bdfSopenharmony_ci case 'w': 1105f08c3bdfSopenharmony_ci case 'W': 1106f08c3bdfSopenharmony_ci ret *= 4; 1107f08c3bdfSopenharmony_ci *e = *e + 1; 1108f08c3bdfSopenharmony_ci break; 1109f08c3bdfSopenharmony_ci } 1110f08c3bdfSopenharmony_ci return (ret); 1111f08c3bdfSopenharmony_ci} 1112f08c3bdfSopenharmony_ci 1113f08c3bdfSopenharmony_ciint main(int argc, char **argv) 1114f08c3bdfSopenharmony_ci{ 1115f08c3bdfSopenharmony_ci int i, style, ch; 1116f08c3bdfSopenharmony_ci char *endp; 1117f08c3bdfSopenharmony_ci int dirpath = 0; 1118f08c3bdfSopenharmony_ci 1119f08c3bdfSopenharmony_ci goodfile[0] = 0; 1120f08c3bdfSopenharmony_ci logfile[0] = 0; 1121f08c3bdfSopenharmony_ci 1122f08c3bdfSopenharmony_ci page_size = getpagesize(); 1123f08c3bdfSopenharmony_ci page_mask = page_size - 1; 1124f08c3bdfSopenharmony_ci 1125f08c3bdfSopenharmony_ci setvbuf(stdout, NULL, _IOLBF, 0); /* line buffered stdout */ 1126f08c3bdfSopenharmony_ci 1127f08c3bdfSopenharmony_ci while ((ch = getopt(argc, argv, 1128f08c3bdfSopenharmony_ci "b:c:dl:m:no:p:qr:s:t:w:D:I:LN:OP:RS:W")) 1129f08c3bdfSopenharmony_ci != EOF) 1130f08c3bdfSopenharmony_ci switch (ch) { 1131f08c3bdfSopenharmony_ci case 'b': 1132f08c3bdfSopenharmony_ci simulatedopcount = getnum(optarg, &endp); 1133f08c3bdfSopenharmony_ci if (!quiet) 1134f08c3bdfSopenharmony_ci fprintf(stdout, "Will begin at operation" 1135f08c3bdfSopenharmony_ci "%ld\n", simulatedopcount); 1136f08c3bdfSopenharmony_ci if (simulatedopcount == 0) 1137f08c3bdfSopenharmony_ci usage(); 1138f08c3bdfSopenharmony_ci simulatedopcount -= 1; 1139f08c3bdfSopenharmony_ci break; 1140f08c3bdfSopenharmony_ci case 'c': 1141f08c3bdfSopenharmony_ci closeprob = getnum(optarg, &endp); 1142f08c3bdfSopenharmony_ci if (!quiet) 1143f08c3bdfSopenharmony_ci fprintf(stdout, 1144f08c3bdfSopenharmony_ci "Chance of close/open is 1 in %d\n", 1145f08c3bdfSopenharmony_ci closeprob); 1146f08c3bdfSopenharmony_ci if (closeprob <= 0) 1147f08c3bdfSopenharmony_ci usage(); 1148f08c3bdfSopenharmony_ci break; 1149f08c3bdfSopenharmony_ci case 'd': 1150f08c3bdfSopenharmony_ci debug++; 1151f08c3bdfSopenharmony_ci break; 1152f08c3bdfSopenharmony_ci case 'l': 1153f08c3bdfSopenharmony_ci maxfilelen = getnum(optarg, &endp); 1154f08c3bdfSopenharmony_ci if (maxfilelen <= 0) 1155f08c3bdfSopenharmony_ci usage(); 1156f08c3bdfSopenharmony_ci break; 1157f08c3bdfSopenharmony_ci case 'm': 1158f08c3bdfSopenharmony_ci monitorstart = getnum(optarg, &endp); 1159f08c3bdfSopenharmony_ci if (monitorstart < 0) 1160f08c3bdfSopenharmony_ci usage(); 1161f08c3bdfSopenharmony_ci if (!endp || *endp++ != ':') 1162f08c3bdfSopenharmony_ci usage(); 1163f08c3bdfSopenharmony_ci monitorend = getnum(endp, &endp); 1164f08c3bdfSopenharmony_ci if (monitorend < 0) 1165f08c3bdfSopenharmony_ci usage(); 1166f08c3bdfSopenharmony_ci if (monitorend == 0) 1167f08c3bdfSopenharmony_ci monitorend = -1; /* aka infinity */ 1168f08c3bdfSopenharmony_ci debug = 1; 1169f08c3bdfSopenharmony_ci case 'n': 1170f08c3bdfSopenharmony_ci sizechecks = 0; 1171f08c3bdfSopenharmony_ci break; 1172f08c3bdfSopenharmony_ci case 'o': 1173f08c3bdfSopenharmony_ci maxoplen = getnum(optarg, &endp); 1174f08c3bdfSopenharmony_ci if (maxoplen <= 0) 1175f08c3bdfSopenharmony_ci usage(); 1176f08c3bdfSopenharmony_ci break; 1177f08c3bdfSopenharmony_ci case 'p': 1178f08c3bdfSopenharmony_ci progressinterval = getnum(optarg, &endp); 1179f08c3bdfSopenharmony_ci if (progressinterval < 0) 1180f08c3bdfSopenharmony_ci usage(); 1181f08c3bdfSopenharmony_ci break; 1182f08c3bdfSopenharmony_ci case 'q': 1183f08c3bdfSopenharmony_ci quiet = 1; 1184f08c3bdfSopenharmony_ci break; 1185f08c3bdfSopenharmony_ci case 'r': 1186f08c3bdfSopenharmony_ci readbdy = getnum(optarg, &endp); 1187f08c3bdfSopenharmony_ci if (readbdy <= 0) 1188f08c3bdfSopenharmony_ci usage(); 1189f08c3bdfSopenharmony_ci break; 1190f08c3bdfSopenharmony_ci case 's': 1191f08c3bdfSopenharmony_ci style = getnum(optarg, &endp); 1192f08c3bdfSopenharmony_ci if (style < 0 || style > 1) 1193f08c3bdfSopenharmony_ci usage(); 1194f08c3bdfSopenharmony_ci break; 1195f08c3bdfSopenharmony_ci case 't': 1196f08c3bdfSopenharmony_ci truncbdy = getnum(optarg, &endp); 1197f08c3bdfSopenharmony_ci if (truncbdy <= 0) 1198f08c3bdfSopenharmony_ci usage(); 1199f08c3bdfSopenharmony_ci break; 1200f08c3bdfSopenharmony_ci case 'w': 1201f08c3bdfSopenharmony_ci writebdy = getnum(optarg, &endp); 1202f08c3bdfSopenharmony_ci if (writebdy <= 0) 1203f08c3bdfSopenharmony_ci usage(); 1204f08c3bdfSopenharmony_ci break; 1205f08c3bdfSopenharmony_ci case 'D': 1206f08c3bdfSopenharmony_ci debugstart = getnum(optarg, &endp); 1207f08c3bdfSopenharmony_ci if (debugstart < 1) 1208f08c3bdfSopenharmony_ci usage(); 1209f08c3bdfSopenharmony_ci break; 1210f08c3bdfSopenharmony_ci case 'I': 1211f08c3bdfSopenharmony_ci assign_fd_policy(optarg); 1212f08c3bdfSopenharmony_ci break; 1213f08c3bdfSopenharmony_ci case 'L': 1214f08c3bdfSopenharmony_ci lite = 1; 1215f08c3bdfSopenharmony_ci break; 1216f08c3bdfSopenharmony_ci case 'N': 1217f08c3bdfSopenharmony_ci numops = getnum(optarg, &endp); 1218f08c3bdfSopenharmony_ci if (numops < 0) 1219f08c3bdfSopenharmony_ci usage(); 1220f08c3bdfSopenharmony_ci break; 1221f08c3bdfSopenharmony_ci case 'O': 1222f08c3bdfSopenharmony_ci randomoplen = 0; 1223f08c3bdfSopenharmony_ci break; 1224f08c3bdfSopenharmony_ci case 'P': 1225f08c3bdfSopenharmony_ci strncpy(goodfile, optarg, sizeof(goodfile)); 1226f08c3bdfSopenharmony_ci strcat(goodfile, "/"); 1227f08c3bdfSopenharmony_ci strncpy(logfile, optarg, sizeof(logfile)); 1228f08c3bdfSopenharmony_ci strcat(logfile, "/"); 1229f08c3bdfSopenharmony_ci dirpath = 1; 1230f08c3bdfSopenharmony_ci break; 1231f08c3bdfSopenharmony_ci case 'R': 1232f08c3bdfSopenharmony_ci mapped_reads = 0; 1233f08c3bdfSopenharmony_ci break; 1234f08c3bdfSopenharmony_ci case 'S': 1235f08c3bdfSopenharmony_ci seed = getnum(optarg, &endp); 1236f08c3bdfSopenharmony_ci if (seed == 0) 1237f08c3bdfSopenharmony_ci seed = time(0) % 10000; 1238f08c3bdfSopenharmony_ci if (!quiet) 1239f08c3bdfSopenharmony_ci fprintf(stdout, "Seed set to %d\n", seed); 1240f08c3bdfSopenharmony_ci if (seed < 0) 1241f08c3bdfSopenharmony_ci usage(); 1242f08c3bdfSopenharmony_ci break; 1243f08c3bdfSopenharmony_ci case 'W': 1244f08c3bdfSopenharmony_ci mapped_writes = 0; 1245f08c3bdfSopenharmony_ci if (!quiet) 1246f08c3bdfSopenharmony_ci fprintf(stdout, "mapped writes DISABLED\n"); 1247f08c3bdfSopenharmony_ci break; 1248f08c3bdfSopenharmony_ci 1249f08c3bdfSopenharmony_ci default: 1250f08c3bdfSopenharmony_ci usage(); 1251f08c3bdfSopenharmony_ci 1252f08c3bdfSopenharmony_ci } 1253f08c3bdfSopenharmony_ci argc -= optind; 1254f08c3bdfSopenharmony_ci argv += optind; 1255f08c3bdfSopenharmony_ci if (argc < 1) 1256f08c3bdfSopenharmony_ci usage(); 1257f08c3bdfSopenharmony_ci fname = argv[0]; 1258f08c3bdfSopenharmony_ci 1259f08c3bdfSopenharmony_ci signal(SIGHUP, cleanup); 1260f08c3bdfSopenharmony_ci signal(SIGINT, cleanup); 1261f08c3bdfSopenharmony_ci signal(SIGPIPE, cleanup); 1262f08c3bdfSopenharmony_ci signal(SIGALRM, cleanup); 1263f08c3bdfSopenharmony_ci signal(SIGTERM, cleanup); 1264f08c3bdfSopenharmony_ci signal(SIGXCPU, cleanup); 1265f08c3bdfSopenharmony_ci signal(SIGXFSZ, cleanup); 1266f08c3bdfSopenharmony_ci signal(SIGVTALRM, cleanup); 1267f08c3bdfSopenharmony_ci signal(SIGUSR1, cleanup); 1268f08c3bdfSopenharmony_ci signal(SIGUSR2, cleanup); 1269f08c3bdfSopenharmony_ci 1270f08c3bdfSopenharmony_ci initstate(seed, state, 256); 1271f08c3bdfSopenharmony_ci setstate(state); 1272f08c3bdfSopenharmony_ci 1273f08c3bdfSopenharmony_ci open_test_files(argv, argc); 1274f08c3bdfSopenharmony_ci 1275f08c3bdfSopenharmony_ci strncat(goodfile, dirpath ? basename(fname) : fname, 256); 1276f08c3bdfSopenharmony_ci strcat(goodfile, ".fsxgood"); 1277f08c3bdfSopenharmony_ci fsxgoodfd = open(goodfile, O_RDWR | O_CREAT | O_TRUNC, 0666); 1278f08c3bdfSopenharmony_ci if (fsxgoodfd < 0) { 1279f08c3bdfSopenharmony_ci prterr(goodfile); 1280f08c3bdfSopenharmony_ci exit(92); 1281f08c3bdfSopenharmony_ci } 1282f08c3bdfSopenharmony_ci strncat(logfile, dirpath ? basename(fname) : fname, 256); 1283f08c3bdfSopenharmony_ci strcat(logfile, ".fsxlog"); 1284f08c3bdfSopenharmony_ci fsxlogf = fopen(logfile, "w"); 1285f08c3bdfSopenharmony_ci if (fsxlogf == NULL) { 1286f08c3bdfSopenharmony_ci prterr(logfile); 1287f08c3bdfSopenharmony_ci exit(93); 1288f08c3bdfSopenharmony_ci } 1289f08c3bdfSopenharmony_ci if (lite) { 1290f08c3bdfSopenharmony_ci off_t ret; 1291f08c3bdfSopenharmony_ci int fd = get_fd(); 1292f08c3bdfSopenharmony_ci file_size = maxfilelen = lseek(fd, (off_t) 0, SEEK_END); 1293f08c3bdfSopenharmony_ci if (file_size == (off_t) - 1) { 1294f08c3bdfSopenharmony_ci prterr(fname); 1295f08c3bdfSopenharmony_ci warn("main: lseek eof"); 1296f08c3bdfSopenharmony_ci exit(94); 1297f08c3bdfSopenharmony_ci } 1298f08c3bdfSopenharmony_ci ret = lseek(fd, (off_t) 0, SEEK_SET); 1299f08c3bdfSopenharmony_ci if (ret == (off_t) - 1) { 1300f08c3bdfSopenharmony_ci prterr(fname); 1301f08c3bdfSopenharmony_ci warn("main: lseek 0"); 1302f08c3bdfSopenharmony_ci exit(95); 1303f08c3bdfSopenharmony_ci } 1304f08c3bdfSopenharmony_ci } 1305f08c3bdfSopenharmony_ci original_buf = malloc(maxfilelen); 1306f08c3bdfSopenharmony_ci if (original_buf == NULL) 1307f08c3bdfSopenharmony_ci exit(96); 1308f08c3bdfSopenharmony_ci for (i = 0; i < maxfilelen; i++) 1309f08c3bdfSopenharmony_ci original_buf[i] = random() % 256; 1310f08c3bdfSopenharmony_ci 1311f08c3bdfSopenharmony_ci good_buf = malloc(maxfilelen); 1312f08c3bdfSopenharmony_ci if (good_buf == NULL) 1313f08c3bdfSopenharmony_ci exit(97); 1314f08c3bdfSopenharmony_ci memset(good_buf, '\0', maxfilelen); 1315f08c3bdfSopenharmony_ci 1316f08c3bdfSopenharmony_ci temp_buf = malloc(maxoplen); 1317f08c3bdfSopenharmony_ci if (temp_buf == NULL) 1318f08c3bdfSopenharmony_ci exit(99); 1319f08c3bdfSopenharmony_ci memset(temp_buf, '\0', maxoplen); 1320f08c3bdfSopenharmony_ci 1321f08c3bdfSopenharmony_ci if (lite) { /* zero entire existing file */ 1322f08c3bdfSopenharmony_ci ssize_t written; 1323f08c3bdfSopenharmony_ci int fd = get_fd(); 1324f08c3bdfSopenharmony_ci 1325f08c3bdfSopenharmony_ci written = write(fd, good_buf, (size_t) maxfilelen); 1326f08c3bdfSopenharmony_ci if (written != maxfilelen) { 1327f08c3bdfSopenharmony_ci if (written == -1) { 1328f08c3bdfSopenharmony_ci prterr(fname); 1329f08c3bdfSopenharmony_ci warn("main: error on write"); 1330f08c3bdfSopenharmony_ci } else 1331f08c3bdfSopenharmony_ci warn("main: short write, 0x%x bytes instead " 1332f08c3bdfSopenharmony_ci "of 0x%x\n", 1333f08c3bdfSopenharmony_ci (unsigned)written, maxfilelen); 1334f08c3bdfSopenharmony_ci exit(98); 1335f08c3bdfSopenharmony_ci } 1336f08c3bdfSopenharmony_ci } else 1337f08c3bdfSopenharmony_ci check_trunc_hack(); 1338f08c3bdfSopenharmony_ci 1339f08c3bdfSopenharmony_ci while (numops == -1 || numops--) 1340f08c3bdfSopenharmony_ci test(); 1341f08c3bdfSopenharmony_ci 1342f08c3bdfSopenharmony_ci close_test_files(); 1343f08c3bdfSopenharmony_ci prt("All operations completed A-OK!\n"); 1344f08c3bdfSopenharmony_ci 1345f08c3bdfSopenharmony_ci if (tf_buf) 1346f08c3bdfSopenharmony_ci free(tf_buf); 1347f08c3bdfSopenharmony_ci 1348f08c3bdfSopenharmony_ci free(original_buf); 1349f08c3bdfSopenharmony_ci free(good_buf); 1350f08c3bdfSopenharmony_ci free(temp_buf); 1351f08c3bdfSopenharmony_ci 1352f08c3bdfSopenharmony_ci return 0; 1353f08c3bdfSopenharmony_ci} 1354