/usr/src/tools/diskomizer/bufs.c
C | 1829 lines | 1448 code | 188 blank | 193 comment | 218 complexity | ba23a0d9cfe5147f3b065aeeeb08cea2 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
- /*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
- #pragma ident "%Z%%M% %I% %E% SMI"
- /*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
- /*
- * Buffer manipulation routines.
- */
- #include <sys/systeminfo.h>
- #include <diskomizer/log.h>
- #include "args.h"
- #include "diskomizer64mpism.h"
- #include "asm.h"
- #include "bufs.h"
- #include "shm_ops.h"
- #include "time.h"
- #include "signal_catch.h"
- #include <tnf/probe.h>
- #include "errors.h"
- static uchar_t *write_bufs;
- static bitmap_t *writemap;
- static uchar_t *read_bufs;
- static bitmap_t *readmap;
- static struct shadow_hdr *shadow_headers;
- static char serial_and_provider[SIZEOF_SERIAL_AND_PROVIDER + 1];
- static ulong_t writemap_size = 0;
- static ulong_t readmap_size = 0;
- static void init_data_buf(uchar_t *buf, int bufno);
- static void init_func_buf(uchar_t *buf, int bufno);
- static void init_func_buf_branch(struct buf *buf, int bufno);
- static void init_func_buf_short(struct buf *buf, int bufno);
- static void init_func_buf_long(struct buf *buf, int bufno);
- static void set_bufhdr_a(uchar_t *buf, struct bufhdr_a hdr);
- static void set_bufhdr(uchar_t *buf, struct bufhdr hdr);
- static uint64_t get_hdrchksum(struct bufhdr hdr);
- static char *init_from_file(uchar_t *buf, ullong_t len);
- static void alloc_io_bufs(ulong_t nbufs, ulong_t buf_size,
- ulong_t map_size, unsigned char **bufs, bitmap_t **map);
- static uchar_t *get_buf(uchar_t *bufpool, uint_t pool_size,
- uint_t io_len, bitmap_t map[], ulong_t maplen, ullong_t *next_off);
- struct shadow_hdr const * get_shadow_hdr_by_off(ulong_t off);
- static uint32_t sizeof_shadow_header(void);
- static void protect_buf_func(uchar_t *buf);
- static void unprotect_buf_func(uchar_t *buf);
- void (*protect_buf)(uchar_t *buf) = (void (*)(uchar_t *))nop;
- void (*unprotect_buf)(uchar_t *buf) = (void (*)(uchar_t *))nop;
- static const char *madv_str[] = {
- "MADV_NORMAL",
- "MADV_RANDOM",
- "MADV_SEQUENTIAL",
- "MADV_WILLNEED",
- "MADV_DONTNEED",
- "MADV_FREE",
- "Unknown"
- };
- #define MADV_Unknown 7
- #define MADV_STR(A) (madv_str[A > MADV_Unknown ? MADV_Unknown : A])
- static ulong_t
- get_buf_off(uchar_t *buf, uchar_t *bufpool, uint_t io_len)
- {
- ulong_t off;
- /*LINTED*/
- off = (buf - bufpool);
- off = off/io_len;
- return (off);
- }
- static void
- return_buf(uchar_t *buf, uchar_t *bufpool, uint_t io_len,
- bitmap_t map[], ulong_t maplen, uint_t pool_size)
- {
- ulong_t off;
- off = get_buf_off(buf, bufpool, io_len);
- if (opts.use_madvise)
- if (madvise((caddr_t)buf, io_len, opts.madvise_return)) {
- MADVISE_ERROR((ulong_t)buf,
- io_len, opts.madvise_return,
- MADV_STR(opts.madvise_return));
- }
- TNF_PROBE_5(return_buf, "return_buf",
- "sunw%cte%diskomizer%bufs return",
- tnf_opaque, off, off,
- tnf_opaque, buf_pool, bufpool,
- tnf_opaque, buf, buf,
- tnf_opaque, sizeof_struct_buf, sizeof (struct buf),
- tnf_opaque, io_len, io_len);
- assert(off < pool_size);
- clear_write(map, off, maplen);
- }
- static uchar_t *
- get_buf(uchar_t *bufpool, uint_t pool_size, uint_t io_len,
- bitmap_t map[], ulong_t maplen, ullong_t *next_off)
- {
- ullong_t off;
- uchar_t *buf;
- off = find_next_free(map, *next_off, pool_size, maplen);
- *next_off = (off + opts.nprocs + 1) % pool_size;
- buf = &bufpool[off * io_len];
- if (opts.use_madvise)
- if (madvise((caddr_t)buf, io_len, opts.madvise_get)) {
- MADVISE_ERROR((ulong_t)buf, io_len, opts.madvise_get,
- MADV_STR(opts.madvise_get));
- }
- TNF_PROBE_3(get_buf, "get_buf",
- "sunw%cte%diskomizer%bufs get",
- tnf_opaque, off, off,
- tnf_opaque, buf_pool, bufpool,
- tnf_opaque, buf, buf);
- return (buf);
- }
- const char *
- get_buf_serial_and_provider(const uchar_t *b)
- {
- struct bufhdr *hdrp = (struct bufhdr *)b;
- if (hdrp->start == (BUF_TYPE_A)) {
- return (hdrp->ab.a.serial_and_provider);
- } else if (hdrp->start == BUF_TYPE_B) {
- return (hdrp->ab.b.serial_and_provider);
- } else {
- return (NULL);
- }
- }
- time_t
- get_buf_time(uchar_t *b)
- {
- struct bufhdr *hdrp = (struct bufhdr *)b;
- if (hdrp->start == BUF_TYPE_A) {
- return (hdrp->ab.a.time);
- } else if (hdrp->start == BUF_TYPE_B) {
- return (hdrp->ab.b.time);
- } else {
- return (-1);
- }
- }
- pid_t
- get_buf_did(uchar_t *b)
- {
- struct bufhdr *hdrp = (struct bufhdr *)b;
- if (hdrp->start == BUF_TYPE_A) {
- return (hdrp->ab.a.did);
- } else if (hdrp->start == BUF_TYPE_B) {
- return (hdrp->ab.b.did);
- } else {
- return (-1);
- }
- }
- void
- init_block_str(struct device *device)
- {
- ulong_t tmp;
- ulong_t len = device->length;
- ulong_t size = INDEX_TO_DIOLEN(max_disk_io_len);
- /*
- * (void) memset(device->blocks, NULL,
- * ((len/size) + 1) * sizeof (struct blks));
- */
- for (tmp = 0; tmp < (len/size) + 1; tmp++) {
- struct blks *block, *blocks;
- blocks = shm_ops->attach(device->blocks->handles[tmp %
- device->blocks->count]);
- if (blocks == NULL) {
- ATTACH_ERROR(device->blocks->handles[tmp %
- device->blocks->count]);
- exit(1);
- }
- block = &blocks[tmp / device->blocks->count];
- /*
- * Make it look like all the buffers have already been read
- * enough times to allow a write to go ahead.
- */
- block->read_count = opts.read_minimum;
- /*
- * Zero out the rest of the data.
- */
- block->hdrchksum = 0;
- block->path_id = 0;
- block->bad_hdr = 0;
- block->ab = 0;
- block->bad_chksum = 0;
- block->sequence = 0;
- block->r.w.last_io = NULL;
- block->r.w.last_iolen = 0;
- block->r.w.prev_io = NULL;
- block->r.w.prev_iolen = 0;
- block->last_returned_delta = 0;
- (void) memset(&block->u, NULL, sizeof (block->u));
- block->last_requested = 0;
- shm_ops->detach(device->blocks->handles[tmp %
- device->blocks->count]);
- }
- }
- /*
- * init_aio_bufs allocates and initilises the bitmaps and the blks structures
- * for each block on the device.
- *
- * The size of the bit map can be limited with the option OBSCURE_WRITEMAP_SIZE
- * in which case some or all of the bits in the map will protect more than one
- * blk structure.
- */
- static bitmap_t *
- init_aio_bufs(struct device *device)
- {
- ullong_t tmp;
- struct shm_flags shmflags;
- int nhandles;
- ullong_t left;
- ullong_t blocks_per_bucket;
- ullong_t total_blocks;
- ZERO_OBJ(shmflags);
- total_blocks = device->length/INDEX_TO_DIOLEN(max_disk_io_len);
- blocks_per_bucket = (shm_ops->max_size() / sizeof (struct blks));
- nhandles = (total_blocks / blocks_per_bucket);
- /*
- * Handle any rounding, the last bucket may not be full
- * length.
- */
- if (total_blocks % blocks_per_bucket) {
- nhandles++;
- }
- if (opts.obscure_writemap_size == 0) {
- tmp = total_blocks;
- tmp = (tmp % MAP_BITS ? 1 : 0) + tmp / MAP_BITS;
- device->writemap_size = tmp;
- } else {
- device->writemap_size = opts.obscure_writemap_size;
- }
- tmp = device->writemap_size;
- /*
- * Pad to avoid alignment issues. The bitmaps are always read
- * in the sizeof (bitmap_t) chunks so this is needed on both
- * SPARC and x86.
- */
- tmp += (tmp % sizeof (bitmap_t));
- plog(LOG_DEBUG, "Writemap size %#llx, sizeof (bitmap_t) %#lx\n", tmp,
- (ulong_t)sizeof (bitmap_t));
- shmflags.allow_detach = (opts.expert_allow_detach);
- shmflags.always_detach = (opts.debug_always_detach != 0);
- shmflags.leave_attached =
- (opts.obscure_leave_shm_attached_after_init != 0);
- if ((device->writemap_handle =
- shm_ops->init(tmp, sizeof (bitmap_t), shmflags)) ==
- NULL) {
- pfprintf(stderr,
- "FATAL: Unable to create shared memory %s\n",
- shm_ops->name(NULL));
- exit(1);
- }
- plog(LOG_DEBUG, "writemap_handle %#lx\n",
- (long)device->writemap_handle);
- /*
- * struct shm_handle contains the first void *
- * hence the subtraction of one from nhandles.
- */
- device->blocks = calloc(sizeof (struct shm_handle) +
- ((nhandles - 1) * sizeof (void *)), 1);
- if (device->blocks == NULL) {
- CALLOC_ERROR((long) (sizeof (struct shm_handle) +
- ((nhandles - 1) * sizeof (void *))), (long)1);
- exit(1);
- }
- device->blocks->count = nhandles;
- /*
- * This should not really live here.
- */
- device->blocks->len = blocks_per_bucket;
- left = total_blocks;
- for (nhandles = 0; nhandles < device->blocks->count; nhandles++) {
- int n = MIN(blocks_per_bucket, left);
- assert(n != 0);
- device->blocks->handles[nhandles] = shm_ops->init(n,
- sizeof (struct blks), shmflags);
- left -= n;
- if (device->blocks->handles[nhandles] == NULL) {
- SHM_INIT_ERROR(NULL,
- (ulong_t)n * sizeof (struct blks));
- exit(1);
- }
- plog(LOG_DEBUG, "blocks handle %d %#lx len %#x\n", nhandles,
- (ulong_t)device->blocks->handles[nhandles], n);
- }
- if (opts.obscure_mprotect_write_bufs) {
- unprotect_buf = unprotect_buf_func;
- protect_buf = protect_buf_func;
- }
- return (device->writemap_handle);
- }
- static long
- getpagesz(void)
- {
- static long pagesize;
- if (pagesize == 0) {
- pagesize = sysconf(_SC_PAGESIZE);
- }
- return (pagesize);
- }
- void
- protect_buf_func(uchar_t *b)
- {
- long ps = getpagesz();
- char *x = (char *)((((ulong_t)b)/ps)*ps);
- long len = INDEX_TO_DIOLEN(max_disk_io_len);
- TNF_PROBE_2(init_buf, "protect",
- "sunw%cte%diskomizer%bufs init",
- tnf_opaque, x, x, tnf_ulong, len, len);
- len += (ulong_t)b - (ulong_t)x;
- if (mprotect(x, len, PROT_READ) == -1)
- pperror("mprotect(%#lx, %#lx, PROT_READ)",
- (ulong_t)x, len);
- }
- void
- unprotect_buf_func(uchar_t *b)
- {
- long ps = getpagesz();
- char *x = (char *)((((ulong_t)b)/ps)*ps);
- long len = INDEX_TO_DIOLEN(max_disk_io_len);
- len += (ulong_t)b - (ulong_t)x;
- TNF_PROBE_2(init_buf, "unprotect",
- "sunw%cte%diskomizer%bufs init",
- tnf_opaque, x, x, tnf_ulong, len, len);
- if (mprotect(x, len, PROT_WRITE|PROT_READ) == -1)
- pperror("mprotect(%#lx, %#lx, PROT_WRITE|PROT_READ)",
- (ulong_t)x, len);
- }
- uchar_t *
- get_write_buf(void)
- {
- static ullong_t next_off;
- uchar_t *buf;
- buf = get_buf(write_bufs, opts.nwritebufs,
- INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap,
- writemap, writemap_size, &next_off);
- TNF_PROBE_1(get_write_buf, "get_write_buf",
- "sunw%cte%diskomizer%bufs get write",
- tnf_opaque, buf, buf);
- return (buf);
- }
- int
- get_write_buf_id(uchar_t *b)
- {
- /*LINTED*/
- return ((b - write_bufs)/
- (INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap));
- }
- void
- return_write_buf(uchar_t *buf)
- {
- TNF_PROBE_1(return_write_buf,
- "return_write_buf", "sunw%cte%diskomizer%bufs return write",
- tnf_opaque, buf, buf);
- return_buf(buf, write_bufs, INDEX_TO_DIOLEN(max_disk_io_len) +
- opts.write_buffer_gap, writemap, writemap_size,
- opts.nwritebufs);
- }
- static uint32_t
- sizeof_shadow_header(void)
- {
- return (sizeof (struct shadow_hdr) + (
- opts.disk_io_sizes.weightings[(opts.disk_io_sizes.wlen - 1)] *
- sizeof (check_t)));
- }
- static struct shadow_hdr *
- alloc_shadow_headers(ulong_t count)
- {
- struct shadow_hdr *ptr;
- ptr = (struct shadow_hdr *)alloc_mem(count, sizeof_shadow_header());
- return (ptr);
- }
- /*
- * Initialize the buffers that we are writing from.
- *
- * Buffers are initialized at run time and a flag in the shadow buffer is
- * then set to prevent them being initialized twice. The exception to this is
- * where a data file is provided by the user, then that file is used to
- * initialise the buffers, until there are either no more buffers or no more
- * data in the file left to use. If the file runs out first the rest of the
- * buffers are initialzed at run time.
- */
- void
- init_all_write_bufs(struct aio_str *aio, struct device *devices)
- {
- char *last_from_file = NULL;
- int i, ndevices;
- int all_wthreads;
- int tmp;
- all_wthreads = opts.wthreads + opts.wrthreads;
- ndevices = how_many_devices(devices);
- for (i = 0; i < all_wthreads; i++) {
- struct device *tmpdev;
- int k;
- int j = i * ndevices;
- time_t (*handler)(struct aio_str *aiop, ullong_t start);
- if (is_readonly()) {
- handler = handle_readonly_seq;
- } else if (i < opts.wthreads) {
- handler = handle_write;
- } else {
- handler = handle_read_then_write;
- }
- for (k = 0, tmpdev = devices; tmpdev != NULL;
- tmpdev = tmpdev->next, k++) {
- aio[j+k].buf = NULL;
- aio[j+k].off = 0;
- aio[j+k].handler = handler;
- aio[j+k].dev = tmpdev;
- }
- assert(k == ndevices);
- }
- while (devices != NULL) {
- devices->writemap_handle =
- init_aio_bufs(devices);
- devices = devices->next;
- }
- if (is_readonly())
- return;
- tmp = ndevices*opts.nprocs*all_wthreads;
- if (opts.nwritebufs == 0)
- opts.nwritebufs = ndevices*opts.nprocs * all_wthreads *
- opts.obscure_buffer_multiplier;
- opts.nwritebufs = MAX(opts.nwritebufs, (tmp*11)/10);
- /*
- * Make sure there is a spare buffer for every process.
- */
- opts.nwritebufs = MAX(opts.nwritebufs, tmp + opts.nprocs);
- if (writemap_size == 0) {
- ulong_t tmp = opts.nwritebufs;
- tmp = (tmp % MAP_BITS ? 1 : 0) + tmp / MAP_BITS;
- writemap_size = tmp;
- }
- print_number((long long)opts.nwritebufs, "write buf", "write bufs");
- alloc_io_bufs(opts.nwritebufs,
- INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap,
- writemap_size, &write_bufs, &writemap);
- shadow_headers = alloc_shadow_headers(opts.nwritebufs);
- if (opts.data_file && opts.init_from_data_file != 0) {
- if ((last_from_file = init_from_file((uchar_t *)write_bufs,
- opts.nwritebufs *
- INDEX_TO_DIOLEN(max_disk_io_len))) != NULL) {
- (void) printf(
- "\tData buffers initialzed from file %s\n",
- opts.data_file);
- }
- }
- for (i = 0; i < opts.nwritebufs; i++) {
- int j;
- ulong_t x = i * (INDEX_TO_DIOLEN(max_disk_io_len) +
- opts.write_buffer_gap);
- struct bufhdr_a hdr_a;
- struct shadow_hdr *shadow;
- if ((char *)&write_bufs[x] >= last_from_file)
- break;
- hdr_a = get_bufhdr_a(&write_bufs[x]);
- shadow = (struct shadow_hdr *)get_shadow_hdr_by_off(i);
- shadow->type = hdr_a.type;
- for (j = 0; j < opts.disk_io_sizes.wlen; j++) {
- shadow->chksums[j] = check_bufbody(&write_bufs[x],
- INDEX_TO_DIOLEN(j));
- }
- if (shadow->chksums[max_disk_io_len] != hdr_a.chksum) {
- shadow->type.BUF_BAD_CHKSUM = 1;
- if ((char *)&write_bufs[x] < last_from_file)
- shadow_headers[i].type.BUF_READ_ONLY = 1;
- shadow_headers->type.BUF_BAD_CHKSUM = 1;
- }
- shadow->type.BUF_READY = 1;
- shadow->type.BUF_READ_ONLY = 1;
- }
- }
- ulong_t
- u_long_chksum(ulong_t x)
- {
- union {
- ulong_t l;
- uchar_t c[sizeof (ulong_t)];
- } u;
- int i;
- ulong_t cksum;
- u.l = x;
- for (i = cksum = 0; i < sizeof (ulong_t); i++)
- cksum += u.c[i];
- return (cksum);
- }
- ulong_t
- u_int32_chksum(uint32_t x)
- {
- union {
- uint32_t l;
- uchar_t c[sizeof (uint32_t)];
- } u;
- int i;
- ulong_t cksum;
- u.l = x;
- for (i = cksum = 0; i < sizeof (uint32_t); i++)
- cksum += u.c[i];
- return (cksum);
- }
- ulong_t
- u_short_chksum(ushort16_t x)
- {
- union {
- ushort16_t l;
- uchar_t c[sizeof (ushort16_t)];
- } u;
- int i;
- ulong_t cksum;
- u.l = x;
- for (i = cksum = 0; i < sizeof (ushort16_t); i++)
- cksum += u.c[i];
- return (cksum);
- }
- void
- init_data_buf(uchar_t *buf, int bufno)
- {
- int i;
- int size = (INDEX_TO_DIOLEN(max_disk_io_len) -
- sizeof (struct bufhdr));
- uchar_t *data = get_buf_data(buf);
- for (i = 0; i < size; i++) {
- *(data + i) = init_uchar_func(bufno, i);
- }
- }
- /*ARGSUSED*/
- void
- init_func_buf_branch(struct buf *buf, int bufno)
- {
- uint32_t *start;
- uint32_t *last;
- uint32_t *ptr;
- uint32_t jump_size;
- #ifdef __sparcv9
- union {
- pid_t (*func)(pid_t);
- pid_t pid_t;
- uint32_t thirty_two[2];
- } tmp;
- #elif __i386 || __amd64
- varlen t_inst; /* Some Intel assembler >32 bits */
- #endif
- do {
- jump_size = 0x1FFFF &
- (lrand48() % (INDEX_TO_DIOLEN(max_disk_io_len) /
- (2 * sizeof (uint32_t))));
- } while (jump_size < 4);
- start = &buf->data.i[0];
- plog(LOG_DEBUG, "initializing a branch function %#lx buffer %#lx\n",
- getpgid, (ulong_t)start);
- last = (uint32_t *)(start +
- ((INDEX_TO_DIOLEN(max_disk_io_len) - SIZEOF_BUFHDR)/
- sizeof (uint32_t)));
- ptr = start;
- /*
- * SPARC
- *
- * The assembler that is written stores all but the bottom 10
- * bits of getpgid in %l1 and all but the bottom 10 bits of
- * pgrp in %l0. Then in the loop we jump to %l1 plus the bottom 10
- * bits of getpgid and in the delay slot %lo gets added to the bottom
- * 10 bits of pgrp and the result stored in %o0.
- *
- * Intel
- *
- * The assembler written pushes pgrp onto the stack, moves the address
- * of getpgid into the %eax register. In the loop we call the function
- * whose address is in %eax (getpgid).
- *
- */
- #ifdef __sparcv9
- /*
- * The V9 assembler that is created should look something like this.
- * the upper bits are nearly always zero but at the momment I don't
- * check for that.
- *
- * save %sp, -0x100, %sp
- * sethi %hi(getpgid.upperbits), %o1
- * add %o1, %lo(getpgid.upperbits), %o1
- * sllx %o1, 32, %l1
- * sethi %hi(getpgid.lowerbits), %o2
- * add %o2, %l1, %l1
- * sethi %hi(pgrp), %l0 ! pgrp is a 32 bit quantity.
- *
- */
- *ptr++ = save_asm(sp, sp, 1, -0x100);
- tmp.func = getpgid;
- if (getpgid(pgrp) == (pid_t)-1)
- pperror("getpgpid(%d)\n", pgrp);
- tmp.func(pgrp);
- assert(tmp.func == &getpgid);
- /* sethi %hi(tmp), %o1 */
- *ptr++ = sethi_asm(hi(tmp.thirty_two[0]), o1);
- *ptr++ = add_asm(o1, o1, 1, lo(tmp.thirty_two[0]));
- *ptr++ = sllx_asm(l1, o1, 32);
- *ptr++ = sethi_asm(hi(tmp.thirty_two[1]), o2);
- *ptr++ = add_asm(l1, o2, 0, l1);
- *ptr++ = sethi_asm(hi((ulong_t)pgrp), l0);
- #elif __sparc && !__sparcv9
- *ptr++ = save_asm(sp, sp, 1, -0x70);
- /* sethi %hi(getpgid), %o1 */
- *ptr++ = sethi_asm(hi((ulong_t)pgrp), l0);
- *ptr++ = sethi_asm(hi((ulong_t)getpgid), l1);
- #elif __i386 || __amd64
- *ptr++ = save_asm();
- #else
- #error "No assembler defined for this processor"
- #endif
- for (; ptr < (last - (jump_size + 8)); ptr += jump_size) {
- int i;
- #ifdef __sparc
- /* sethi %hi(pgrp), %o0 */
- /* jmpl %o1 + %lo(getpgid), %o7 */
- *ptr++ = jmpl_asm(o7, l1, 1, lo((ulong_t)getpgid));
- /* add %o0, %lo(pgrp), %o0 */
- *ptr++ = add_asm(o0, l0, 1, lo(pgrp));
- *ptr = ba_asm(1, jump_size);
- for (i = 0; i < (jump_size - 1); i++) {
- *(ptr + 1 + i) = lrand48();
- }
- }
- *ptr++ = ret_asm(); /* ret */
- *ptr++ = restore_asm(g0, g0, 1, g0); /* restore */
- #elif defined(__i386) || defined(__amd64)
- #if defined(__amd64)
- /* move pgrp into %edi */
- t_inst = mov32_asm((uint32_t)pgrp, edi);
- *ptr++ = t_inst.thirtytwo[0];
- *ptr++ = t_inst.thirtytwo[1];
- /* Move the address of the pointer to the function into %rdx */
- t_inst = movl_asm((uint64_t)&getpgid, rdx);
- *ptr++ = t_inst.thirtytwo[0];
- *ptr++ = t_inst.thirtytwo[1];
- *ptr++ = t_inst.thirtytwo[2];
- *ptr++ = call_asm();
- #elif defined(__i386)
- /* push pgrp onto the stack */
- t_inst = pushl_asm((uint32_t)pgrp);
- *ptr++ = t_inst.thirtytwo[0];
- *ptr++ = t_inst.thirtytwo[1];
- t_inst = movl_asm((uint32_t)getpgid, eax);
- *ptr++ = t_inst.thirtytwo[0];
- *ptr++ = t_inst.thirtytwo[1];
- *ptr++ = call_asm();
- *ptr++ = add_asm((uchar_t)4, esp);
- #else
- #error "Unknown architecture!"
- #endif
- t_inst = jmp_asm((jump_size - 1) * sizeof (uint32_t));
- *ptr++ = t_inst.thirtytwo[0];
- *ptr = t_inst.thirtytwo[1];
- for (i = 0; i < (jump_size - 1); i++) {
- *(ptr + 1 + i) = lrand48();
- }
- }
- *ptr++ = ret_asm();
- #endif
- while (ptr < last) {
- *ptr++ = nop_asm();
- }
- }
- void
- init_func_buf_short(struct buf *buf, int bufno)
- {
- uint32_t *start;
- uint32_t *last;
- uint32_t *ptr;
- plog(LOG_DEBUG, "initializing a function buffer\n");
- start = &buf->data.i[0];
- last = (uint32_t *)(start +
- ((INDEX_TO_DIOLEN(max_disk_io_len) - SIZEOF_BUFHDR) /
- sizeof (uint32_t)));
- /*
- * SPARC:
- *
- * We fill the main part of the code with the assembler:
- *
- * bn,a 0x2080000a
- * ZZZZ
- *
- * Intel:
- *
- * The equivalent to the SPARC operation is:
- *
- * nop
- * nop
- * jmp .+4 0x04eb9090
- * ZZZZ
- *
- * The random 32 bits along with Intel's non-aligned instructions
- * means this routine generates some fairly horrible assembler at
- * first sight. The secret is to follow the jumps themselves even
- * if they do appear to jump into the middle of other instructions
- * and not worry about the code that isn't executed.
- *
- * General:
- *
- * Where ZZZZ is random and will be skipped of over by the
- * annulled branch.
- */
- #if __i386 || __amd64
- ptr = (uint32_t *)start;
- *ptr++ = save_asm();
- for (; ptr < (last - 2); ptr += 2) {
- *ptr = 0x04eb9090;
- #elif __sparc
- for (ptr = (uint32_t *)(start); ptr < (last - 2); ptr += 2) {
- *(ptr) = bn_asm(1, 2); /* SPARC branch never annuled */
- #else
- #error "No assembler defined for this processor"
- #endif
- if (ptr == (uint32_t *)(start))
- *(ptr + 1) = bufno;
- else
- *(ptr + 1) = lrand48();
- }
- #ifdef __sparc
- *ptr++ = retl_asm(); /* sparc retl */
- #else
- *ptr++ = ret_asm(); /* Hence the need for save_asm() */
- #endif
- while (ptr < last) {
- #ifdef __sparc
- *(ptr++) = nop_asm(); /* SPARC nop */
- #else
- *(ptr++) = NOPWORD;
- #endif
- }
- }
- void
- init_func_buf_long(struct buf *buf, int bufno)
- {
- uint32_t *start;
- uint32_t *last;
- uint32_t *ptr;
- #if defined(__i386) || defined(__amd64)
- varlen t_inst;
- #endif
- uint32_t jump_size = 0x1FFFF &
- (lrand48() % (INDEX_TO_DIOLEN(max_disk_io_len) /
- sizeof (uint32_t)));
- if (jump_size < 2) {
- init_func_buf_short(buf, bufno);
- return;
- }
- plog(LOG_DEBUG,
- "initializing a long function buffer with jump_size %d\n",
- jump_size);
- start = &buf->data.i[0];
- last = start +
- ((INDEX_TO_DIOLEN(max_disk_io_len) - SIZEOF_BUFHDR) /
- sizeof (uint32_t));
- /*
- * We fill the main part of the code with the assembler:
- *
- * SPARC
- *
- * ba,a jump_size
- * now jump_size - 1 random numbers...
- *
- * Intel
- *
- * jmpl jump_size
- * now jump_size - 1 random numbers...
- *
- * Where ZZZZ is random and will be skipped over by the
- * annuled branch never. This is just to get the chksums of
- * executable sections to be different.
- */
- #if defined(__i386) || defined(__amd64)
- ptr = ((uint32_t *)start);
- *ptr++ = save_asm();
- for (; ptr < (last - (jump_size + 2)); ptr += jump_size) {
- int i;
- #if defined(__amd64)
- t_inst = jmp_asm((jump_size - 1) * sizeof (uint32_t));
- *ptr++ = t_inst.thirtytwo[0];
- *ptr = t_inst.thirtytwo[1];
- #else
- t_inst = jmp_asm((jump_size - 1) * sizeof (uint32_t));
- *ptr++ = t_inst.thirtytwo[0];
- *ptr = t_inst.thirtytwo[1];
- #endif
- #elif defined(SPARC)
- for (ptr = start; ptr < (last - (jump_size + 2));
- ptr += jump_size) {
- int i;
- /* 0x30800000 | jump_size; SPARC ba,a jump_size */
- *ptr = ba_asm(1, jump_size);
- #else
- #error "unknown pocesseor type"
- #endif
- for (i = 0; i < (jump_size - 1); i++) {
- if (i == 0)
- *(ptr + 1 + i) = bufno;
- else
- *(ptr + 1 + i) = lrand48();
- }
- }
- #ifdef __sparc
- *ptr++ = retl_asm(); /* sparc retl */
- #else /* Intel */
- *ptr++ = ret_asm(); /* Again, hence the save_asm() earlier */
- #endif
- while (ptr < last) {
- #ifdef __sparc
- *(ptr++) = nop_asm(); /* SPARC nop */
- #else /* Intel */
- *(ptr++) = NOPWORD;
- #endif
- }
- }
- void
- init_func_buf(uchar_t *cbuf, int bufno)
- {
- struct buf *buf;
- /*
- * The under lying routines that init function buffers require
- * correct alignment so if the buffer passed in is not alligned
- * allocate a correctly aligned one and pass that to the other
- * routines. memcpy all that data into the original buf.
- */
- if (((ulong_t)cbuf % sizeof (uint64_t)) != 0) {
- buf = (struct buf *)my_calloc(1,
- INDEX_TO_DIOLEN(max_disk_io_len));
- if (buf == NULL) {
- pfprintf(stderr,
- "unable to allocate temporary buffer\n");
- exit(1);
- }
- } else {
- /*LINTED Alignment*/
- buf = (struct buf *)cbuf;
- }
- if ((lrand48() % 2) == 1)
- init_func_buf_long(buf, bufno);
- else
- init_func_buf_branch(buf, bufno);
- if (((ulong_t)cbuf % sizeof (uint64_t)) != 0) {
- (void) memcpy(cbuf, (void *)buf,
- INDEX_TO_DIOLEN(max_disk_io_len));
- free(buf);
- }
- }
- struct bufhdr_a
- conv_bufhdr(struct bufhdr *in)
- {
- struct bufhdr_a hdr;
- ZERO_OBJ(hdr);
- switch (in->start) {
- case BUF_TYPE_A:
- hdr = in->ab.a;
- break;
- case BUF_TYPE_B:
- hdr.devid = in->ab.b.devid;
- hdr.off = in->ab.b.off;
- hdr.hdrchksum = in->ab.b.hdrchksum;
- hdr.len = in->ab.b.len;
- hdr.type = in->ab.b.type;
- hdr.chksum = in->ab.b.chksum;
- hdr.did = in->ab.b.did;
- hdr.time = in->ab.b.time;
- memcpy(hdr.serial_and_provider,
- in->ab.b.serial_and_provider,
- sizeof (hdr.serial_and_provider));
- break;
- default:
- hdr.type.BUF_BAD_HDR = 1;
- break;
- }
- return (hdr);
- }
- void
- toggle_bufhdr(uchar_t *buf)
- {
- struct bufhdr newhdr, hdr;
- (void) memset(&newhdr, NULL, sizeof (struct bufhdr));
- hdr = get_bufhdr(buf);
- switch (hdr.start) {
- case BUF_TYPE_A:
- newhdr.ab.b.time = hdr.ab.a.time;
- newhdr.ab.b.did = hdr.ab.a.did;
- newhdr.ab.b.chksum = hdr.ab.a.chksum;
- newhdr.ab.b.off = hdr.ab.a.off;
- newhdr.ab.b.type = hdr.ab.a.type;
- newhdr.ab.b.hdrchksum = hdr.ab.a.hdrchksum;
- newhdr.ab.b.len = hdr.ab.a.len;
- newhdr.ab.b.devid = hdr.ab.a.devid;
- memcpy(newhdr.ab.b.serial_and_provider,
- hdr.ab.a.serial_and_provider,
- sizeof (hdr.ab.a.serial_and_provider));
- newhdr.start = newhdr.end = BUF_TYPE_B;
- break;
- case BUF_TYPE_B:
- newhdr.ab.a.chksum = hdr.ab.b.chksum;
- newhdr.ab.a.len = hdr.ab.b.len;
- newhdr.ab.a.off = hdr.ab.b.off;
- newhdr.ab.a.type = hdr.ab.b.type;
- newhdr.ab.a.hdrchksum = hdr.ab.b.hdrchksum;
- newhdr.ab.a.devid = hdr.ab.b.devid;
- newhdr.ab.a.did = hdr.ab.b.did;
- newhdr.ab.a.time = hdr.ab.b.time;
- memcpy(newhdr.ab.a.serial_and_provider,
- hdr.ab.b.serial_and_provider,
- sizeof (hdr.ab.b.serial_and_provider));
- newhdr.start = newhdr.end = BUF_TYPE_A;
- break;
- }
- set_bufhdr(buf, newhdr);
- }
- struct shadow_hdr const *
- get_shadow_hdr_by_off(ulong_t off)
- {
- char *ptr;
- ptr = (char *)shadow_headers + (sizeof_shadow_header() * off);
- /*LINTED Alignment*/
- return ((struct shadow_hdr *)ptr);
- }
- struct shadow_hdr const *
- get_shadow_hdr(uchar_t *buf)
- {
- ulong_t off;
- off = get_buf_off(buf, write_bufs, INDEX_TO_DIOLEN(max_disk_io_len));
- return (get_shadow_hdr_by_off(off));
- }
- struct bufhdr
- get_bufhdr(uchar_t *buf)
- {
- struct bufhdr hdr;
- (void) memcpy(&hdr, (char *)buf, sizeof (struct bufhdr));
- return (hdr);
- }
- struct bufhdr_a
- get_bufhdr_a(uchar_t *buf)
- {
- struct bufhdr_a hdr_a;
- struct bufhdr hdr;
- hdr = get_bufhdr(buf);
- hdr_a = conv_bufhdr(&hdr);
- if (hdr_a.type.BUF_BAD_HDR)
- pfprintf(stderr, "Unknown buf type: buf %#lx type %#llx\n",
- (ulong_t)buf, (long long)hdr.start);
- return (hdr_a);
- }
- void
- set_bufhdr(uchar_t *buf, struct bufhdr hdr)
- {
- (void) memcpy(buf, (char *)&hdr, sizeof (struct bufhdr));
- assert(*buf == 0xAA || *buf == 0x55);
- }
- struct bufhdr
- set_hdr_a(struct bufhdr bufhdr, const struct bufhdr_a hdr)
- {
- ZERO_OBJ(bufhdr.ab);
- switch (bufhdr.start) {
- case BUF_TYPE_A:
- bufhdr.ab.a = hdr;
- break;
- case BUF_TYPE_B:
- get_serial_and_provider(
- bufhdr.ab.b.serial_and_provider,
- SIZEOF_SERIAL_AND_PROVIDER);
- bufhdr.ab.b.chksum = hdr.chksum;
- bufhdr.ab.b.off = hdr.off;
- bufhdr.ab.b.len = hdr.len;
- bufhdr.ab.b.devid = hdr.devid;
- bufhdr.ab.b.hdrchksum = hdr.hdrchksum;
- bufhdr.ab.b.type = hdr.type;
- bufhdr.ab.b.time = hdr.time;
- bufhdr.ab.b.did = hdr.did;
- break;
- default:
- pfprintf(stderr,
- "Unknown buf type: buf type %#llx "
- "setting to A\n", (long long)bufhdr.start);
- bufhdr.ab.a = hdr;
- bufhdr.start = bufhdr.end = BUF_TYPE_A;
- break;
- }
- return (bufhdr);
- }
- static void
- set_bufhdr_a(uchar_t *buf, struct bufhdr_a hdr_a)
- {
- struct bufhdr hdr = get_bufhdr(buf);
- set_bufhdr(buf, set_hdr_a(hdr, hdr_a));
- }
- static uint64_t
- get_hdrchksum(struct bufhdr hdr)
- {
- struct bufhdr_a hdr_a;
- ZERO_OBJ(hdr_a);
- hdr_a = conv_bufhdr(&hdr);
- return (hdr_a.hdrchksum);
- }
- ushort16_t
- get_bufhdr_hdrchksum(uchar_t *buf)
- {
- return (get_hdrchksum(get_bufhdr(buf)));
- }
- ushort16_t
- set_hdrchksum(struct bufhdr *hdr)
- {
- struct bufhdr_a hdr_a;
- ushort16_t newchksum;
- ZERO_OBJ(hdr_a);
- hdr_a = conv_bufhdr(hdr);
- newchksum = check_hdr(hdr, hdr_a.hdrchksum);
- hdr_a.hdrchksum = newchksum;
- *hdr = set_hdr_a(*hdr, hdr_a);
- return (newchksum);
- }
- static uint_t
- check_delay()
- {
- uint_t delay_len;
- uint_t i;
- if (opts.max_mem_delay == 0)
- return (0);
- for (i = delay_len = ((uint_t)lrand48() % opts.max_mem_delay);
- i > 0; i--)
- /* LINTED */
- ;
- return (delay_len);
- }
- ushort16_t
- set_buf_hdrchksum(uchar_t *buf)
- {
- struct bufhdr_a hdr_a;
- struct bufhdr hdr;
- uint_t delay_len;
- hdr = get_bufhdr(buf);
- hdr_a = conv_bufhdr(&hdr);
- hdr_a.hdrchksum = check_hdr(&hdr, hdr_a.hdrchksum);
- set_bufhdr_a(buf, hdr_a);
- delay_len = check_delay();
- if (hdr_a.hdrchksum != get_bufhdr_hdrchksum(buf)) {
- pfprintf(stderr, "buf %#lx bad header checksum read back "
- "from memory after delay %d\n", (ulong_t)buf,
- delay_len);
- }
- return (hdr_a.hdrchksum);
- }
- void
- set_bufhdr_all(uchar_t *buf, check_t chksum, uint32_t len,
- struct device_id devid,
- ullong_t off,
- buf_data_type type,
- char sequence,
- time_t now)
- {
- struct bufhdr_a hdr;
- ZERO_OBJ(hdr);
- hdr = get_bufhdr_a(buf);
- hdr.chksum = chksum;
- hdr.len = len;
- hdr.devid = devid;
- hdr.off = off;
- hdr.time = now;
- hdr.did = master_pid();
- get_serial_and_provider(hdr.serial_and_provider,
- SIZEOF_SERIAL_AND_PROVIDER);
- hdr.type = type;
- hdr.type.sequence = sequence;
- hdr.type.padding = 0; /* not used */
- set_bufhdr_a(buf, hdr);
- }
- void
- init_buf(uchar_t *buf)
- {
- int x;
- struct bufhdr hdr;
- void *sig;
- int bufno = get_write_buf_id(buf);
- time_t now;
- now = time(NULL);
- x = lrand48();
- x = x >> 10;
- plog(LOG_DEBUG, "initalizing data buf %#lx\n", (ulong_t)buf);
- sig = expect_signal(SIGBUS, "memset", buf,
- INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap);
- unprotect_buf(buf);
- (void) memset((char *)buf, NULL, SIZEOF_BUFHDR);
- ZERO_OBJ(hdr);
- if (1 == opts.obscure_execute && x % 2) {
- init_func_buf(buf, bufno);
- hdr.start = hdr.end = BUF_TYPE_B;
- hdr.ab.b.chksum = 0;
- hdr.ab.b.len = 0;
- hdr.ab.b.type.BUF_EXECUTABLE = 1;
- hdr.ab.b.time = now;
- hdr.ab.b.did = master_pid();
- get_serial_and_provider(hdr.ab.b.serial_and_provider,
- SIZEOF_SERIAL_AND_PROVIDER);
- } else {
- init_data_buf(buf, bufno);
- hdr.start = hdr.end = BUF_TYPE_A;
- hdr.ab.a.chksum = 0;
- hdr.ab.a.len = 0;
- hdr.ab.a.type.BUF_EXECUTABLE = 0;
- hdr.ab.a.time = now;
- hdr.ab.a.did = master_pid();
- get_serial_and_provider(hdr.ab.a.serial_and_provider,
- SIZEOF_SERIAL_AND_PROVIDER);
- }
- (void) set_hdrchksum(&hdr);
- set_bufhdr(buf, hdr);
- protect_buf(buf);
- TNF_PROBE_1(init_buf, "init_buf", "sunw%cte%diskomizer%bufs init",
- tnf_opaque, buf, buf);
- cancel_expected_signal(SIGBUS, sig);
- }
- ushort16_t
- check_hdr(struct bufhdr *hdr, ushort16_t hdrchksum)
- {
- uchar_t *x;
- ushort16_t total;
- char i;
- x = (uchar_t *)hdr;
- for (i = total = 0; i < SIZEOF_BUFHDR; i++) {
- total += x[i];
- }
- total -= u_short_chksum(hdrchksum);
- return (total);
- }
- ushort16_t
- check_bufhdr(uchar_t *buf, ushort16_t hdrchksum)
- {
- struct bufhdr hdr = get_bufhdr(buf);
- return (check_hdr(&hdr, hdrchksum));
- }
- check_t
- check_bufbody(uchar_t *buf, ulong_t size)
- {
- return (check_sum(buf + SIZEOF_BUFHDR, size - SIZEOF_BUFHDR));
- }
- check_t
- check_aiobuf(struct aio_str *aiop)
- {
- return (check_buf(aiop->buf, opts.disk_io_sizes.vals[aiop->iolen],
- &aiop->error));
- }
- check_t
- check_buf(uchar_t *buf, int len, struct error *error)
- {
- struct bufhdr_a hdr_a;
- check_t total;
- ushort16_t hdrchksum;
- struct bufhdr hdr;
- hdr = get_bufhdr(buf);
- hdr_a = conv_bufhdr(&hdr);
- total = check_bufbody(buf, hdr_a.len);
- hdrchksum = check_hdr(&hdr, hdr_a.hdrchksum);
- if (hdr_a.len != len) {
- error->desc.LENGTH_MISMATCH = 1;
- error->len = hdr_a.len;
- }
- if (hdr_a.hdrchksum != hdrchksum) {
- dfprintf(stderr, "buf %#lx bad header checksum "
- "is %x should be %x\n", (ulong_t)buf,
- hdr_a.hdrchksum, hdrchksum);
- error->desc.HEADER_CHECKSUM_ERR = 1;
- error->bad_checksum = hdrchksum;
- return (0);
- }
- if (hdr_a.chksum != total) {
- TNF_PROBE_4(check_buf, "check_buf",
- "sunw%cte%diskomizer%bufs check",
- tnf_opaque, hdrchksum, hdrchksum,
- tnf_opaque, total, total,
- tnf_opaque, hdr_a.chksum, hdr_a.chksum,
- tnf_opaque, buf, buf);
- error->desc.BODY_CHECKSUM_ERR = 1;
- error->bad_checksum = total;
- if (opts.fix_bad_checksums) {
- hdr_a.chksum = total;
- set_bufhdr_a(buf, hdr_a);
- if (is_executable(buf)) {
- dfprintf(stderr,
- "buf %#lx bad func checksum %#x != "
- "%#llx - fixed\n", (ulong_t)buf, total,
- (long long)hdr_a.chksum);
- } else {
- dfprintf(stderr,
- "buf %#lx bad data checksum %#llx != "
- "%#llx - fixed\n", (ulong_t)buf, total,
- (long long)hdr_a.chksum);
- }
- } else {
- if (is_executable(buf)) {
- dfprintf(stderr,
- "buf %#lx bad func checksum %#llx != "
- "%#llx\n", (ulong_t)buf, total,
- (long long)hdr_a.chksum);
- } else {
- dfprintf(stderr,
- "buf %#lx bad data checksum %#llx != "
- "%#llx\n", (ulong_t)buf, total,
- (long long)hdr_a.chksum);
- }
- }
- }
- return (total);
- }
- void
- save_data_bufs(void)
- {
- FILE *save_file;
- uchar_t *buf = write_bufs;
- ullong_t blksize = INDEX_TO_DIOLEN(max_disk_io_len) +
- opts.write_buffer_gap;
- ullong_t len = blksize * opts.nwritebufs;
- uint64_t i;
- uchar_t *new;
- char *path_buf;
- time_t now;
- if (opts.data_file == NULL || opts.save_data == 0) {
- return;
- }
- path_buf = alloca(strlen(opts.data_file) + 32);
- (void) sprintf(path_buf, "%s/data_file", opts.data_file);
- (void) mkdir(opts.data_file, 0777);
- if ((save_file = fopen(path_buf, "w")) == NULL) {
- FOPEN_ERROR(path_buf, "w");
- return;
- }
- now = time(NULL);
- (void) fprintf(save_file, "#\n# diskomizer %s\n# Updated %s#\n",
- VERSION, ctime(&now));
- /*LINTED*/
- new = buf;
- for (i = 0; i < len/sizeof (uint64_t); i++, new += sizeof (uint64_t)) {
- (void) fprintf(save_file,
- "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
- *new, *(new+1), *(new+2), *(new+3),
- *(new+4), *(new+5), *(new+6), *(new+7));
- if (((ulong_t)new % blksize) == 0)
- (void) fprintf(save_file, " # New Block\n");
- else
- (void) fprintf(save_file, "\n");
- }
- now = time(NULL);
- (void) fprintf(save_file, "#\n# diskomizer %s\n# Updated %s#\n",
- VERSION, ctime(&now));
- (void) fflush(save_file);
- if (fsync(fileno(save_file)) == -1) {
- FSYNC_ERROR(fileno(save_file), path_buf);
- }
- (void) fclose(save_file);
- (void) sprintf(path_buf, "%s/option_file", opts.data_file);
- if ((save_file = fopen(path_buf, "w")) == NULL) {
- FOPEN_ERROR(path_buf, "w");
- return;
- }
- (void) fprintf(save_file, "# Diskimizer %s\n", VERSION);
- (void) print_options(save_file);
- (void) fflush(save_file);
- if (fsync(fileno(save_file)) == -1) {
- FSYNC_ERROR(fileno(save_file), path_buf);
- }
- (void) fclose(save_file);
- }
- /*
- * This needs rethinking.
- */
- static char *
- init_from_file(uchar_t *buf, ullong_t len)
- {
- char *data_file;
- char *tmp;
- uint64_t *new;
- uint64_t i = 0;
- time_t last_read = 0;
- size_t maping_len;
- char *path_buf = opts.data_file;
- /*LINTED*/
- new = (uint64_t *)buf;
- if ((data_file = map_file(path_buf, &last_read,
- &maping_len, pprintf, NULL)) == NULL) {
- path_buf = alloca(strlen(opts.data_file) + 10);
- (void) sprintf(path_buf, "%s/data_file", opts.data_file);
- last_read = 0;
- if ((data_file = map_file(path_buf, &last_read,
- &maping_len, pprintf, NULL)) == NULL) {
- pperror("map_file: can't read data bufs from %s",
- path_buf);
- return (NULL);
- }
- }
- if (*(data_file+maping_len-1) != '\n') {
- pprintf("Incomplete last line in data file %s\n",
- path_buf);
- (void) munmap(data_file, maping_len);
- return (0);
- }
- *(data_file+maping_len-1) = NULL;
- tmp = data_file;
- while (i < len/sizeof (uint64_t)) {
- char *next;
- uint64_t x;
- if (*tmp == NULL)
- break;
- while (*tmp != '0') {
- while (*tmp != '\n') {
- if (*tmp == NULL)
- break;
- tmp++;
- }
- if (*tmp == NULL)
- break;
- tmp++;
- if (*tmp == NULL)
- break;
- }
- if (*tmp == NULL)
- break;
- if (*tmp == '0' && (*(tmp+1) == 'x' || *(tmp+1) == 'X'))
- tmp += 2;
- x = strtoull(tmp, &next, 16);
- #ifdef _BIG_ENDIAN
- *new = x;
- #elif defined(_LITTLE_ENDIAN)
- swab((char *)&x, (char *)new, sizeof (uint64_t));
- #else
- #error "niether _BIG_ENDIAN or _LITTLE_ENDIAN defined"
- #endif /* BIG_ENDIAN or _LITTLE_ENDIAN */
- while (*next != '\n') {
- if (*next == NULL)
- break;
- next++;
- }
- i++;
- new++;
- if (*next == NULL)
- break;
- tmp = next + 1;
- }
- (void) munmap(data_file, maping_len);
- return ((char *)&new[0]);
- }
- int
- is_write_io(struct aio_str *aiop)
- {
- return (aiop->handler == handle_write ||
- aiop->handler == handle_write_then_read);
- }
- int
- is_read_io(struct aio_str *aiop)
- {
- return (!is_write_io(aiop));
- }
- static void
- analyze_header(FILE *out, const struct bufhdr *good, const struct bufhdr *bad)
- {
- }
- /*
- * More macro hell.
- *
- * These 2 macros are used to print information about buffer headers. Before
- * calling them, define the macros DO_PRINT, DO_PRINT_BIT_FIELD, DO_PRINT_TIME
- * and DO_PRINT_STRING to do what you want.
- *
- */
- #define PRINT_A_HDR(O) \
- DO_PRINT(O, start); \
- DO_PRINT_STRING(O, ab.a.serial_and_provider); \
- DO_PRINT(O, ab.a.devid.ino); \
- DO_PRINT(O, ab.a.devid.dev); \
- DO_PRINT(O, ab.a.hdrchksum); \
- DO_PRINT_BIT_FIELD(O, ab.a.type); \
- DO_PRINT(O, ab.a.chksum); \
- DO_PRINT(O, ab.a.did); \
- DO_PRINT(O, ab.a.len); \
- DO_PRINT(O, ab.a.off); \
- DO_PRINT_TIME(O, ab.a.time); \
- DO_PRINT(O, end)
- #define PRINT_B_HDR(O) \
- DO_PRINT(O, start); \
- DO_PRINT(O, ab.b.off); \
- DO_PRINT_TIME(O, ab.b.time); \
- DO_PRINT(O, ab.b.len); \
- DO_PRINT(O, ab.b.did); \
- DO_PRINT(O, ab.b.devid.ino); \
- DO_PRINT(O, ab.b.devid.dev); \
- DO_PRINT(O, ab.b.hdrchksum); \
- DO_PRINT_BIT_FIELD(O, ab.b.type); \
- DO_PRINT(O, ab.b.chksum); \
- DO_PRINT_STRING(O, ab.b.serial_and_provider); \
- DO_PRINT(O, end)
- void
- decode_header(FILE *out, uchar_t *good, uchar_t *bad)
- {
- struct bufhdr bufhdr, bhdr;
- (void) memcpy(&bufhdr, good, sizeof (struct bufhdr));
- (void) memcpy(&bhdr, bad, sizeof (struct bufhdr));
- (void) fprintf(out, "%29s %18s %18s\n", gettext("Decoding header"),
- gettext("Good"), gettext("Bad"));
- #define DO_PRINT(O, A) (void) fprintf(O, "hdr.%-25s %#18llx %#18llx\n", #A, \
- (long long)bufhdr.A, (long long)bhdr.A)
- #define DO_PRINT_STRING(O, A) (void) fprintf(O, "hdr.%-25s \"%.*s\"\n" \
- "%-48s \"%.*s\"\n", #A, (int)sizeof (bufhdr.A), bufhdr.A, " ", \
- (int)sizeof (bhdr.A), bhdr.A)
- #define DO_PRINT_TIME(O, A) {\
- char *x = alloc_time_str(bufhdr.A);\
- \
- if (x != NULL) {\
- fprintf(O, "hdr.%-25s \"%s\"\n", #A, x); \
- free(x);\
- if ((x = alloc_time_str(bhdr.A)) != NULL) {\
- fprintf(O, "%-48s \"%s\"\n", " ", x);\
- free(x);\
- }\
- }\
- }
- #define DO_PRINT_BIT_FIELD(O, A) \
- DO_PRINT(O, A.BUF_EXECUTABLE); \
- DO_PRINT(O, A.BUF_BAD_HDR); \
- DO_PRINT(O, A.BUF_BAD_CHKSUM); \
- DO_PRINT(O, A.BUF_READ_ONLY); \
- DO_PRINT(O, A.BUF_READY); \
- DO_PRINT(O, A.sequence)
- /*
- * If both headers are of the same type and both have good check sums then
- * only decode the header as the claim to be.
- */
- if (bhdr.start != BUF_TYPE_B || bufhdr.start != BUF_TYPE_B ||
- check_hdr(&bhdr, bhdr.ab.b.hdrchksum) != bhdr.ab.b.hdrchksum ||
- check_hdr(&bufhdr, bufhdr.ab.b.hdrchksum) !=
- bufhdr.ab.b.hdrchksum) {
- PRINT_A_HDR(out);
- }
- if (bhdr.start != BUF_TYPE_A || bufhdr.start != BUF_TYPE_A ||
- check_hdr(&bhdr, bhdr.ab.a.hdrchksum) != bhdr.ab.a.hdrchksum ||
- check_hdr(&bufhdr, bufhdr.ab.a.hdrchksum) !=
- bufhdr.ab.a.hdrchksum) {
- PRINT_B_HDR(out);
- }
- #undef DO_PRINT
- #undef DO_PRINT_TIME
- #undef DO_PRINT_BIT_FIELD
- #undef DO_PRINT_STRING
- }
- void
- print_bufhdr_offsets(FILE *out)
- {
- #define bufhdr (*((struct bufhdr *)0))
- static const char heading[] = "Element Offset"
- " Size\n";
- static const char fmt[] = "bufhdr.%-14s 0x%2.2lx (0t%3.3ld) "
- "sizeof (bufhdr.%-14s) 0x%2.2x (0t%2.2d)\n";
- static const char fmt2[] = "bufhdr.%s\n%-21s 0x%2.2lx (0t%3.3ld) "
- "sizeof (bufhdr.%-14.14s) 0x%2.2x (0t%2.2d)\n";
- #define DO_PRINT(O, A) \
- if (strlen(#A) > 14) { \
- (void) fprintf(O, fmt2, #A, " ", \
- ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), \
- ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), #A, \
- sizeof (bufhdr.A), sizeof (bufhdr.A)); \
- } else { \
- (void) fprintf(O, \
- fmt, #A, ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), \
- ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), #A, \
- sizeof (bufhdr.A), sizeof (bufhdr.A)); \
- }
- #define DO_PRINT_STRING(O, A) DO_PRINT(O, A)
- #define DO_PRINT_TIME(O, A) DO_PRINT(O, A)
- #define DO_PRINT_BIT_FIELD(A, B) DO_PRINT(A, B)
- (void) fprintf(out,
- "Type A buffer header start and end value = %#llx:\n",
- (unsigned long long)BUF_TYPE_A);
- (void) fprintf(out, heading);
- PRINT_A_HDR(out);
- (void) fprintf(out,
- "Type B buffer header start and end value = %#llx:\n",
- (unsigned long long)BUF_TYPE_B);
- (void) fprintf(out, heading);
- PRINT_B_HDR(out);
- #undef bufhdr
- }
- uchar_t *
- get_read_buf(void)
- {
- static ullong_t next_off;
- uchar_t *buf;
- buf = get_buf(read_bufs, opts.nreadbufs,
- INDEX_TO_DIOLEN(max_disk_io_len),
- readmap, readmap_size, &next_off);
- TNF_PROBE_1(get_read_buf, "get_read_buf",
- "sunw%cte%diskomizer%bufs get read",
- tnf_opaque, buf, buf);
- return (buf);
- }
- void
- return_read_buf(uchar_t *buf)
- {
- TNF_PROBE_1(return_read_buf, "return_read_buf",
- "sunw%cte%diskomizer%bufs return read",
- tnf_opaque, buf, buf);
- return_buf(buf, read_bufs, INDEX_TO_DIOLEN(max_disk_io_len), readmap,
- readmap_size, opts.nreadbufs);
- }
- void
- init_read_bufs(struct device *devices)
- {
- int ndevices = how_many_devices(devices);
- int total_reads = opts.rthreads + opts.wrthreads;
- ulong_t tmp, tmp1;
- #ifndef _LP64
- long long q;
- ulong_t x;
- #endif
- assert(ndevices);
- assert(opts.nprocs);
- if (is_readonly()) {
- total_reads += opts.wthreads;
- }
- tmp1 = tmp = ndevices*opts.nprocs*total_reads;
- tmp = (tmp*11)/10;
- if (opts.nreadbufs == 0)
- opts.nreadbufs = tmp1 * opts.obscure_buffer_multiplier;
- /*
- * Make sure that there is at least one spare block per
- * process.
- */
- tmp1 += opts.nprocs;
- tmp = MAX(tmp, tmp1);
- opts.nreadbufs = MAX(opts.nreadbufs, tmp);
- assert(opts.nreadbufs);
- tmp = opts.nreadbufs;
- tmp = (tmp % MAP_BITS ? 1 : 0) + tmp / MAP_BITS;
- if (opts.obscure_readmap_size == 0)
- readmap_size = tmp;
- else
- readmap_size = opts.obscure_readmap_size;
- print_number((long long)opts.nreadbufs, "read buf", "read bufs");
- #ifndef _LP64
- q = opts.nreadbufs;
- q *= INDEX_TO_DIOLEN(max_disk_io_len);
- x = 0;
- x = ~x;
- if (q > (long long)x) {
- pprintf("Read buffers (%#llx) will not fit in a "
- "%d (%#x) bit address space\n",
- q, sizeof (long) * 8, sizeof (long) * 8);
- pprintf("nreadbufs * block_size: %#lx * %#lx = %#llx\n",
- opts.nreadbufs,
- (ulong_t)INDEX_TO_DIOLEN(max_disk_io_len), q);
- /* exit (1); */
- }
- #endif
- plog(LOG_DEBUG, "Allocating %ld * %ld\n", opts.nreadbufs,
- INDEX_TO_DIOLEN(max_disk_io_len) * sizeof (char));
- assert(opts.nreadbufs);
- alloc_io_bufs(opts.nreadbufs, INDEX_TO_DIOLEN(max_disk_io_len),
- readmap_size, &read_bufs, &readmap);
- print_number((long long)(readmap_size * MAP_BITS), "Bit in read map",
- "Bits in read map");
- }
- uchar_t *
- get_buf_data(uchar_t *buf)
- {
- return (buf + SIZEOF_BUFHDR);
- }
- void
- alloc_io_bufs(ulong_t nbufs, ulong_t buf_size, ulong_t map_size,
- unsigned char **bufs, bitmap_t **map)
- {
- *bufs = (uchar_t *)alloc_mem(nbufs, buf_size * sizeof (char));
- *map = (bitmap_t *)alloc_mem(map_size, sizeof (bitmap_t));
- }
- char
- is_executable(uchar_t *buf)
- {
- struct bufhdr_a hdr = get_bufhdr_a(buf);
- return (hdr.type.BUF_EXECUTABLE);
- }
- void
- random_string(char *str, int len)
- {
- int i;
- for (i = 0; i < len; i++) {
- str[i] = (char)(0x7f & lrand48());
- }
- }
- void
- set_serial_and_provider(void)
- {
- char serial[257];
- char provider[257];
- ZERO_OBJ(serial_and_provider);
- if (sysinfo(SI_HW_SERIAL, &serial[0], sizeof (serial)) == -1) {
- int err = errno;
- random_string(serial, sizeof (serial));
- plog(LOG_NOTICE, "Unable to determine serial number: %s. "
- "Using random value of %s", strerror(err), serial);
- }
- if (sysinfo(SI_HW_PROVIDER, &provider[0], sizeof (provider)) == -1) {
- int err = errno;
- random_string(provider, sizeof (provider));
- plog(LOG_NOTICE, "Unable to determine hardware provider: %s. "
- "Using random value of %s", strerror(err), provider);
- }
- snprintf(serial_and_provider, sizeof (serial_and_provider),
- "%.24s%s", serial, provider);
- }
- void
- get_serial_and_provider(char *buf, int len)
- {
- memcpy(buf, serial_and_provider, MIN(SIZEOF_SERIAL_AND_PROVIDER, len));
- }
- void
- print_serial_and_provider(FILE *out)
- {
- int i;
- (void) fprintf(out,
- "Serial and provider:\n\tASCII\n\t\t\"%s\"\n\tHex:\n\t\t\"",
- serial_and_provider);
- for (i = 0; i < SIZEOF_SERIAL_AND_PROVIDER; i++) {
- (void) fprintf(out, "%2.2x", serial_and_provider[i]);
- }
- (void) fprintf(out, "\"\n");
- }
- int
- cmp_serial_and_provider(const char *buf)
- {
- return (memcmp(buf, serial_and_provider, SIZEOF_SERIAL_AND_PROVIDER));
- }