1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #pragma ident "@(#)bufs.c 1.52 09/05/26 SMI" 23 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * Buffer manipulation routines. 31 */ 32 #include <sys/systeminfo.h> 33 #include <diskomizer/log.h> 34 #include "args.h" 35 #include "diskomizer64mpism.h" 36 #include "asm.h" 37 #include "bufs.h" 38 #include "shm_ops.h" 39 #include "time.h" 40 #include "signal_catch.h" 41 #include <tnf/probe.h> 42 #include "errors.h" 43 44 static uchar_t *write_bufs; 45 static bitmap_t *writemap; 46 static uchar_t *read_bufs; 47 static bitmap_t *readmap; 48 static struct shadow_hdr *shadow_headers; 49 50 static char serial_and_provider[SIZEOF_SERIAL_AND_PROVIDER + 1]; 51 52 static ulong_t writemap_size = 0; 53 static ulong_t readmap_size = 0; 54 55 static void init_data_buf(uchar_t *buf, int bufno); 56 static void init_func_buf(uchar_t *buf, int bufno); 57 static void init_func_buf_branch(struct buf *buf, int bufno); 58 static void init_func_buf_short(struct buf *buf, int bufno); 59 static void init_func_buf_long(struct buf *buf, int bufno); 60 static void set_bufhdr_a(uchar_t *buf, struct bufhdr_a hdr); 61 static void set_bufhdr(uchar_t *buf, struct bufhdr hdr); 62 static uint64_t get_hdrchksum(struct bufhdr hdr); 63 static char *init_from_file(uchar_t *buf, ullong_t len); 64 static void alloc_io_bufs(ulong_t nbufs, ulong_t buf_size, 65 ulong_t map_size, unsigned char **bufs, bitmap_t **map); 66 static uchar_t *get_buf(uchar_t *bufpool, uint_t pool_size, 67 uint_t io_len, bitmap_t map[], ulong_t maplen, ullong_t *next_off); 68 struct shadow_hdr const * get_shadow_hdr_by_off(ulong_t off); 69 static uint32_t sizeof_shadow_header(void); 70 static void protect_buf_func(uchar_t *buf); 71 static void unprotect_buf_func(uchar_t *buf); 72 73 void (*protect_buf)(uchar_t *buf) = (void (*)(uchar_t *))nop; 74 void (*unprotect_buf)(uchar_t *buf) = (void (*)(uchar_t *))nop; 75 76 77 static const char *madv_str[] = { 78 "MADV_NORMAL", 79 "MADV_RANDOM", 80 "MADV_SEQUENTIAL", 81 "MADV_WILLNEED", 82 "MADV_DONTNEED", 83 "MADV_FREE", 84 "Unknown" 85 }; 86 87 #define MADV_Unknown 7 88 #define MADV_STR(A) (madv_str[A > MADV_Unknown ? MADV_Unknown : A]) 89 90 static ulong_t 91 get_buf_off(uchar_t *buf, uchar_t *bufpool, uint_t io_len) 92 { 93 ulong_t off; 94 95 /*LINTED*/ 96 off = (buf - bufpool); 97 off = off/io_len; 98 return (off); 99 } 100 101 static void 102 return_buf(uchar_t *buf, uchar_t *bufpool, uint_t io_len, 103 bitmap_t map[], ulong_t maplen, uint_t pool_size) 104 { 105 ulong_t off; 106 107 off = get_buf_off(buf, bufpool, io_len); 108 109 if (opts.use_madvise) 110 if (madvise((caddr_t)buf, io_len, opts.madvise_return)) { 111 MADVISE_ERROR((ulong_t)buf, 112 io_len, opts.madvise_return, 113 MADV_STR(opts.madvise_return)); 114 } 115 116 TNF_PROBE_5(return_buf, "return_buf", 117 "sunw%cte%diskomizer%bufs return", 118 tnf_opaque, off, off, 119 tnf_opaque, buf_pool, bufpool, 120 tnf_opaque, buf, buf, 121 tnf_opaque, sizeof_struct_buf, sizeof (struct buf), 122 tnf_opaque, io_len, io_len); 123 assert(off < pool_size); 124 125 clear_write(map, off, maplen); 126 } 127 static uchar_t * 128 get_buf(uchar_t *bufpool, uint_t pool_size, uint_t io_len, 129 bitmap_t map[], ulong_t maplen, ullong_t *next_off) 130 { 131 ullong_t off; 132 uchar_t *buf; 133 134 off = find_next_free(map, *next_off, pool_size, maplen); 135 136 *next_off = (off + opts.nprocs + 1) % pool_size; 137 138 buf = &bufpool[off * io_len]; 139 if (opts.use_madvise) 140 if (madvise((caddr_t)buf, io_len, opts.madvise_get)) { 141 MADVISE_ERROR((ulong_t)buf, io_len, opts.madvise_get, 142 MADV_STR(opts.madvise_get)); 143 } 144 TNF_PROBE_3(get_buf, "get_buf", 145 "sunw%cte%diskomizer%bufs get", 146 tnf_opaque, off, off, 147 tnf_opaque, buf_pool, bufpool, 148 tnf_opaque, buf, buf); 149 return (buf); 150 } 151 152 const char * 153 get_buf_serial_and_provider(const uchar_t *b) 154 { 155 struct bufhdr *hdrp = (struct bufhdr *)b; 156 157 if (hdrp->start == (BUF_TYPE_A)) { 158 return (hdrp->ab.a.serial_and_provider); 159 } else if (hdrp->start == BUF_TYPE_B) { 160 return (hdrp->ab.b.serial_and_provider); 161 } else { 162 return (NULL); 163 } 164 } 165 166 167 time_t 168 get_buf_time(uchar_t *b) 169 { 170 struct bufhdr *hdrp = (struct bufhdr *)b; 171 172 if (hdrp->start == BUF_TYPE_A) { 173 return (hdrp->ab.a.time); 174 } else if (hdrp->start == BUF_TYPE_B) { 175 return (hdrp->ab.b.time); 176 } else { 177 return (-1); 178 } 179 } 180 181 pid_t 182 get_buf_did(uchar_t *b) 183 { 184 struct bufhdr *hdrp = (struct bufhdr *)b; 185 186 if (hdrp->start == BUF_TYPE_A) { 187 return (hdrp->ab.a.did); 188 } else if (hdrp->start == BUF_TYPE_B) { 189 return (hdrp->ab.b.did); 190 } else { 191 return (-1); 192 } 193 } 194 195 void 196 init_block_str(struct device *device) 197 { 198 ulong_t tmp; 199 ulong_t len = device->length; 200 ulong_t size = INDEX_TO_DIOLEN(max_disk_io_len); 201 202 /* 203 * (void) memset(device->blocks, NULL, 204 * ((len/size) + 1) * sizeof (struct blks)); 205 */ 206 for (tmp = 0; tmp < (len/size) + 1; tmp++) { 207 struct blks *block, *blocks; 208 blocks = shm_ops->attach(device->blocks->handles[tmp % 209 device->blocks->count]); 210 if (blocks == NULL) { 211 ATTACH_ERROR(device->blocks->handles[tmp % 212 device->blocks->count]); 213 exit(1); 214 } 215 block = &blocks[tmp / device->blocks->count]; 216 /* 217 * Make it look like all the buffers have already been read 218 * enough times to allow a write to go ahead. 219 */ 220 block->read_count = opts.read_minimum; 221 /* 222 * Zero out the rest of the data. 223 */ 224 block->hdrchksum = 0; 225 block->path_id = 0; 226 block->bad_hdr = 0; 227 block->ab = 0; 228 block->bad_chksum = 0; 229 block->sequence = 0; 230 231 block->r.w.last_io = NULL; 232 block->r.w.last_iolen = 0; 233 block->r.w.prev_io = NULL; 234 block->r.w.prev_iolen = 0; 235 236 block->last_returned_delta = 0; 237 (void) memset(&block->u, NULL, sizeof (block->u)); 238 block->last_requested = 0; 239 shm_ops->detach(device->blocks->handles[tmp % 240 device->blocks->count]); 241 } 242 } 243 244 /* 245 * init_aio_bufs allocates and initilises the bitmaps and the blks structures 246 * for each block on the device. 247 * 248 * The size of the bit map can be limited with the option OBSCURE_WRITEMAP_SIZE 249 * in which case some or all of the bits in the map will protect more than one 250 * blk structure. 251 */ 252 static bitmap_t * 253 init_aio_bufs(struct device *device) 254 { 255 ullong_t tmp; 256 struct shm_flags shmflags; 257 int nhandles; 258 ullong_t left; 259 ullong_t blocks_per_bucket; 260 ullong_t total_blocks; 261 262 ZERO_OBJ(shmflags); 263 264 total_blocks = device->length/INDEX_TO_DIOLEN(max_disk_io_len); 265 blocks_per_bucket = (shm_ops->max_size() / sizeof (struct blks)); 266 nhandles = (total_blocks / blocks_per_bucket); 267 /* 268 * Handle any rounding, the last bucket may not be full 269 * length. 270 */ 271 if (total_blocks % blocks_per_bucket) { 272 nhandles++; 273 } 274 275 if (opts.obscure_writemap_size == 0) { 276 tmp = total_blocks; 277 tmp = (tmp % MAP_BITS ? 1 : 0) + tmp / MAP_BITS; 278 device->writemap_size = tmp; 279 } else { 280 device->writemap_size = opts.obscure_writemap_size; 281 } 282 283 tmp = device->writemap_size; 284 /* 285 * Pad to avoid alignment issues. The bitmaps are always read 286 * in the sizeof (bitmap_t) chunks so this is needed on both 287 * SPARC and x86. 288 */ 289 tmp += (tmp % sizeof (bitmap_t)); 290 291 plog(LOG_DEBUG, "Writemap size %#llx, sizeof (bitmap_t) %#lx\n", tmp, 292 (ulong_t)sizeof (bitmap_t)); 293 294 shmflags.allow_detach = (opts.expert_allow_detach); 295 shmflags.always_detach = (opts.debug_always_detach != 0); 296 shmflags.leave_attached = 297 (opts.obscure_leave_shm_attached_after_init != 0); 298 299 if ((device->writemap_handle = 300 shm_ops->init(tmp, sizeof (bitmap_t), shmflags)) == 301 NULL) { 302 pfprintf(stderr, 303 "FATAL: Unable to create shared memory %s\n", 304 shm_ops->name(NULL)); 305 exit(1); 306 } 307 308 plog(LOG_DEBUG, "writemap_handle %#lx\n", 309 (long)device->writemap_handle); 310 311 /* 312 * struct shm_handle contains the first void * 313 * hence the subtraction of one from nhandles. 314 */ 315 device->blocks = calloc(sizeof (struct shm_handle) + 316 ((nhandles - 1) * sizeof (void *)), 1); 317 318 if (device->blocks == NULL) { 319 CALLOC_ERROR((long) (sizeof (struct shm_handle) + 320 ((nhandles - 1) * sizeof (void *))), (long)1); 321 exit(1); 322 } 323 324 device->blocks->count = nhandles; 325 /* 326 * This should not really live here. 327 */ 328 device->blocks->len = blocks_per_bucket; 329 left = total_blocks; 330 331 for (nhandles = 0; nhandles < device->blocks->count; nhandles++) { 332 int n = MIN(blocks_per_bucket, left); 333 assert(n != 0); 334 device->blocks->handles[nhandles] = shm_ops->init(n, 335 sizeof (struct blks), shmflags); 336 left -= n; 337 if (device->blocks->handles[nhandles] == NULL) { 338 SHM_INIT_ERROR(NULL, 339 (ulong_t)n * sizeof (struct blks)); 340 exit(1); 341 } 342 plog(LOG_DEBUG, "blocks handle %d %#lx len %#x\n", nhandles, 343 (ulong_t)device->blocks->handles[nhandles], n); 344 } 345 346 if (opts.obscure_mprotect_write_bufs) { 347 unprotect_buf = unprotect_buf_func; 348 protect_buf = protect_buf_func; 349 } 350 351 return (device->writemap_handle); 352 } 353 354 static long 355 getpagesz(void) 356 { 357 static long pagesize; 358 359 if (pagesize == 0) { 360 pagesize = sysconf(_SC_PAGESIZE); 361 } 362 return (pagesize); 363 } 364 365 void 366 protect_buf_func(uchar_t *b) 367 { 368 long ps = getpagesz(); 369 char *x = (char *)((((ulong_t)b)/ps)*ps); 370 long len = INDEX_TO_DIOLEN(max_disk_io_len); 371 TNF_PROBE_2(init_buf, "protect", 372 "sunw%cte%diskomizer%bufs init", 373 tnf_opaque, x, x, tnf_ulong, len, len); 374 375 len += (ulong_t)b - (ulong_t)x; 376 if (mprotect(x, len, PROT_READ) == -1) 377 pperror("mprotect(%#lx, %#lx, PROT_READ)", 378 (ulong_t)x, len); 379 } 380 381 void 382 unprotect_buf_func(uchar_t *b) 383 { 384 long ps = getpagesz(); 385 char *x = (char *)((((ulong_t)b)/ps)*ps); 386 long len = INDEX_TO_DIOLEN(max_disk_io_len); 387 388 len += (ulong_t)b - (ulong_t)x; 389 TNF_PROBE_2(init_buf, "unprotect", 390 "sunw%cte%diskomizer%bufs init", 391 tnf_opaque, x, x, tnf_ulong, len, len); 392 if (mprotect(x, len, PROT_WRITE|PROT_READ) == -1) 393 pperror("mprotect(%#lx, %#lx, PROT_WRITE|PROT_READ)", 394 (ulong_t)x, len); 395 } 396 397 uchar_t * 398 get_write_buf(void) 399 { 400 static ullong_t next_off; 401 uchar_t *buf; 402 buf = get_buf(write_bufs, opts.nwritebufs, 403 INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap, 404 writemap, writemap_size, &next_off); 405 TNF_PROBE_1(get_write_buf, "get_write_buf", 406 "sunw%cte%diskomizer%bufs get write", 407 tnf_opaque, buf, buf); 408 return (buf); 409 } 410 int 411 get_write_buf_id(uchar_t *b) 412 { 413 /*LINTED*/ 414 return ((b - write_bufs)/ 415 (INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap)); 416 } 417 void 418 return_write_buf(uchar_t *buf) 419 { 420 TNF_PROBE_1(return_write_buf, 421 "return_write_buf", "sunw%cte%diskomizer%bufs return write", 422 tnf_opaque, buf, buf); 423 return_buf(buf, write_bufs, INDEX_TO_DIOLEN(max_disk_io_len) + 424 opts.write_buffer_gap, writemap, writemap_size, 425 opts.nwritebufs); 426 } 427 static uint32_t 428 sizeof_shadow_header(void) 429 { 430 return (sizeof (struct shadow_hdr) + ( 431 opts.disk_io_sizes.weightings[(opts.disk_io_sizes.wlen - 1)] * 432 sizeof (check_t))); 433 } 434 static struct shadow_hdr * 435 alloc_shadow_headers(ulong_t count) 436 { 437 struct shadow_hdr *ptr; 438 439 ptr = (struct shadow_hdr *)alloc_mem(count, sizeof_shadow_header()); 440 return (ptr); 441 } 442 /* 443 * Initialize the buffers that we are writing from. 444 * 445 * Buffers are initialized at run time and a flag in the shadow buffer is 446 * then set to prevent them being initialized twice. The exception to this is 447 * where a data file is provided by the user, then that file is used to 448 * initialise the buffers, until there are either no more buffers or no more 449 * data in the file left to use. If the file runs out first the rest of the 450 * buffers are initialzed at run time. 451 */ 452 void 453 init_all_write_bufs(struct aio_str *aio, struct device *devices) 454 { 455 char *last_from_file = NULL; 456 int i, ndevices; 457 int all_wthreads; 458 int tmp; 459 460 all_wthreads = opts.wthreads + opts.wrthreads; 461 462 ndevices = how_many_devices(devices); 463 464 for (i = 0; i < all_wthreads; i++) { 465 struct device *tmpdev; 466 int k; 467 int j = i * ndevices; 468 time_t (*handler)(struct aio_str *aiop, ullong_t start); 469 470 if (is_readonly()) { 471 handler = handle_readonly_seq; 472 } else if (i < opts.wthreads) { 473 handler = handle_write; 474 } else { 475 handler = handle_read_then_write; 476 } 477 478 for (k = 0, tmpdev = devices; tmpdev != NULL; 479 tmpdev = tmpdev->next, k++) { 480 aio[j+k].buf = NULL; 481 aio[j+k].off = 0; 482 aio[j+k].handler = handler; 483 aio[j+k].dev = tmpdev; 484 } 485 assert(k == ndevices); 486 } 487 488 while (devices != NULL) { 489 devices->writemap_handle = 490 init_aio_bufs(devices); 491 devices = devices->next; 492 } 493 if (is_readonly()) 494 return; 495 496 tmp = ndevices*opts.nprocs*all_wthreads; 497 if (opts.nwritebufs == 0) 498 opts.nwritebufs = ndevices*opts.nprocs * all_wthreads * 499 opts.obscure_buffer_multiplier; 500 501 opts.nwritebufs = MAX(opts.nwritebufs, (tmp*11)/10); 502 /* 503 * Make sure there is a spare buffer for every process. 504 */ 505 opts.nwritebufs = MAX(opts.nwritebufs, tmp + opts.nprocs); 506 507 if (writemap_size == 0) { 508 ulong_t tmp = opts.nwritebufs; 509 510 tmp = (tmp % MAP_BITS ? 1 : 0) + tmp / MAP_BITS; 511 512 writemap_size = tmp; 513 } 514 print_number((long long)opts.nwritebufs, "write buf", "write bufs"); 515 516 alloc_io_bufs(opts.nwritebufs, 517 INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap, 518 writemap_size, &write_bufs, &writemap); 519 520 shadow_headers = alloc_shadow_headers(opts.nwritebufs); 521 522 if (opts.data_file && opts.init_from_data_file != 0) { 523 if ((last_from_file = init_from_file((uchar_t *)write_bufs, 524 opts.nwritebufs * 525 INDEX_TO_DIOLEN(max_disk_io_len))) != NULL) { 526 (void) printf( 527 "\tData buffers initialzed from file %s\n", 528 opts.data_file); 529 } 530 } 531 532 for (i = 0; i < opts.nwritebufs; i++) { 533 int j; 534 ulong_t x = i * (INDEX_TO_DIOLEN(max_disk_io_len) + 535 opts.write_buffer_gap); 536 struct bufhdr_a hdr_a; 537 struct shadow_hdr *shadow; 538 if ((char *)&write_bufs[x] >= last_from_file) 539 break; 540 541 hdr_a = get_bufhdr_a(&write_bufs[x]); 542 shadow = (struct shadow_hdr *)get_shadow_hdr_by_off(i); 543 shadow->type = hdr_a.type; 544 for (j = 0; j < opts.disk_io_sizes.wlen; j++) { 545 shadow->chksums[j] = check_bufbody(&write_bufs[x], 546 INDEX_TO_DIOLEN(j)); 547 } 548 if (shadow->chksums[max_disk_io_len] != hdr_a.chksum) { 549 shadow->type.BUF_BAD_CHKSUM = 1; 550 if ((char *)&write_bufs[x] < last_from_file) 551 shadow_headers[i].type.BUF_READ_ONLY = 1; 552 shadow_headers->type.BUF_BAD_CHKSUM = 1; 553 } 554 shadow->type.BUF_READY = 1; 555 shadow->type.BUF_READ_ONLY = 1; 556 } 557 } 558 ulong_t 559 u_long_chksum(ulong_t x) 560 { 561 union { 562 ulong_t l; 563 uchar_t c[sizeof (ulong_t)]; 564 } u; 565 int i; 566 ulong_t cksum; 567 568 u.l = x; 569 570 for (i = cksum = 0; i < sizeof (ulong_t); i++) 571 cksum += u.c[i]; 572 return (cksum); 573 } 574 575 ulong_t 576 u_int32_chksum(uint32_t x) 577 { 578 union { 579 uint32_t l; 580 uchar_t c[sizeof (uint32_t)]; 581 } u; 582 int i; 583 ulong_t cksum; 584 585 u.l = x; 586 587 for (i = cksum = 0; i < sizeof (uint32_t); i++) 588 cksum += u.c[i]; 589 return (cksum); 590 } 591 ulong_t 592 u_short_chksum(ushort16_t x) 593 { 594 union { 595 ushort16_t l; 596 uchar_t c[sizeof (ushort16_t)]; 597 } u; 598 int i; 599 ulong_t cksum; 600 601 u.l = x; 602 603 for (i = cksum = 0; i < sizeof (ushort16_t); i++) 604 cksum += u.c[i]; 605 return (cksum); 606 } 607 void 608 init_data_buf(uchar_t *buf, int bufno) 609 { 610 int i; 611 int size = (INDEX_TO_DIOLEN(max_disk_io_len) - 612 sizeof (struct bufhdr)); 613 uchar_t *data = get_buf_data(buf); 614 615 616 for (i = 0; i < size; i++) { 617 *(data + i) = init_uchar_func(bufno, i); 618 } 619 } 620 621 /*ARGSUSED*/ 622 void 623 init_func_buf_branch(struct buf *buf, int bufno) 624 { 625 uint32_t *start; 626 uint32_t *last; 627 uint32_t *ptr; 628 uint32_t jump_size; 629 630 #ifdef __sparcv9 631 union { 632 pid_t (*func)(pid_t); 633 pid_t pid_t; 634 uint32_t thirty_two[2]; 635 } tmp; 636 #elif __i386 || __amd64 637 varlen t_inst; /* Some Intel assembler >32 bits */ 638 #endif 639 640 do { 641 jump_size = 0x1FFFF & 642 (lrand48() % (INDEX_TO_DIOLEN(max_disk_io_len) / 643 (2 * sizeof (uint32_t)))); 644 } while (jump_size < 4); 645 646 start = &buf->data.i[0]; 647 648 649 plog(LOG_DEBUG, "initializing a branch function %#lx buffer %#lx\n", 650 getpgid, (ulong_t)start); 651 652 last = (uint32_t *)(start + 653 ((INDEX_TO_DIOLEN(max_disk_io_len) - SIZEOF_BUFHDR)/ 654 sizeof (uint32_t))); 655 656 ptr = start; 657 /* 658 * SPARC 659 * 660 * The assembler that is written stores all but the bottom 10 661 * bits of getpgid in %l1 and all but the bottom 10 bits of 662 * pgrp in %l0. Then in the loop we jump to %l1 plus the bottom 10 663 * bits of getpgid and in the delay slot %lo gets added to the bottom 664 * 10 bits of pgrp and the result stored in %o0. 665 * 666 * Intel 667 * 668 * The assembler written pushes pgrp onto the stack, moves the address 669 * of getpgid into the %eax register. In the loop we call the function 670 * whose address is in %eax (getpgid). 671 * 672 */ 673 #ifdef __sparcv9 674 /* 675 * The V9 assembler that is created should look something like this. 676 * the upper bits are nearly always zero but at the momment I don't 677 * check for that. 678 * 679 * save %sp, -0x100, %sp 680 * sethi %hi(getpgid.upperbits), %o1 681 * add %o1, %lo(getpgid.upperbits), %o1 682 * sllx %o1, 32, %l1 683 * sethi %hi(getpgid.lowerbits), %o2 684 * add %o2, %l1, %l1 685 * sethi %hi(pgrp), %l0 ! pgrp is a 32 bit quantity. 686 * 687 */ 688 *ptr++ = save_asm(sp, sp, 1, -0x100); 689 tmp.func = getpgid; 690 if (getpgid(pgrp) == (pid_t)-1) 691 pperror("getpgpid(%d)\n", pgrp); 692 tmp.func(pgrp); 693 assert(tmp.func == &getpgid); 694 /* sethi %hi(tmp), %o1 */ 695 *ptr++ = sethi_asm(hi(tmp.thirty_two[0]), o1); 696 *ptr++ = add_asm(o1, o1, 1, lo(tmp.thirty_two[0])); 697 *ptr++ = sllx_asm(l1, o1, 32); 698 *ptr++ = sethi_asm(hi(tmp.thirty_two[1]), o2); 699 *ptr++ = add_asm(l1, o2, 0, l1); 700 701 *ptr++ = sethi_asm(hi((ulong_t)pgrp), l0); 702 #elif __sparc && !__sparcv9 703 *ptr++ = save_asm(sp, sp, 1, -0x70); 704 /* sethi %hi(getpgid), %o1 */ 705 *ptr++ = sethi_asm(hi((ulong_t)pgrp), l0); 706 *ptr++ = sethi_asm(hi((ulong_t)getpgid), l1); 707 #elif __i386 || __amd64 708 *ptr++ = save_asm(); 709 #else 710 #error "No assembler defined for this processor" 711 #endif 712 713 for (; ptr < (last - (jump_size + 8)); ptr += jump_size) { 714 int i; 715 #ifdef __sparc 716 /* sethi %hi(pgrp), %o0 */ 717 /* jmpl %o1 + %lo(getpgid), %o7 */ 718 *ptr++ = jmpl_asm(o7, l1, 1, lo((ulong_t)getpgid)); 719 /* add %o0, %lo(pgrp), %o0 */ 720 *ptr++ = add_asm(o0, l0, 1, lo(pgrp)); 721 *ptr = ba_asm(1, jump_size); 722 for (i = 0; i < (jump_size - 1); i++) { 723 *(ptr + 1 + i) = lrand48(); 724 } 725 726 } 727 *ptr++ = ret_asm(); /* ret */ 728 *ptr++ = restore_asm(g0, g0, 1, g0); /* restore */ 729 #elif defined(__i386) || defined(__amd64) 730 #if defined(__amd64) 731 /* move pgrp into %edi */ 732 t_inst = mov32_asm((uint32_t)pgrp, edi); 733 *ptr++ = t_inst.thirtytwo[0]; 734 *ptr++ = t_inst.thirtytwo[1]; 735 /* Move the address of the pointer to the function into %rdx */ 736 t_inst = movl_asm((uint64_t)&getpgid, rdx); 737 *ptr++ = t_inst.thirtytwo[0]; 738 *ptr++ = t_inst.thirtytwo[1]; 739 *ptr++ = t_inst.thirtytwo[2]; 740 *ptr++ = call_asm(); 741 #elif defined(__i386) 742 /* push pgrp onto the stack */ 743 t_inst = pushl_asm((uint32_t)pgrp); 744 *ptr++ = t_inst.thirtytwo[0]; 745 *ptr++ = t_inst.thirtytwo[1]; 746 t_inst = movl_asm((uint32_t)getpgid, eax); 747 *ptr++ = t_inst.thirtytwo[0]; 748 *ptr++ = t_inst.thirtytwo[1]; 749 *ptr++ = call_asm(); 750 *ptr++ = add_asm((uchar_t)4, esp); 751 #else 752 #error "Unknown architecture!" 753 #endif 754 755 t_inst = jmp_asm((jump_size - 1) * sizeof (uint32_t)); 756 *ptr++ = t_inst.thirtytwo[0]; 757 *ptr = t_inst.thirtytwo[1]; 758 759 for (i = 0; i < (jump_size - 1); i++) { 760 *(ptr + 1 + i) = lrand48(); 761 } 762 } 763 *ptr++ = ret_asm(); 764 #endif 765 while (ptr < last) { 766 *ptr++ = nop_asm(); 767 } 768 } 769 770 void 771 init_func_buf_short(struct buf *buf, int bufno) 772 { 773 uint32_t *start; 774 uint32_t *last; 775 uint32_t *ptr; 776 777 plog(LOG_DEBUG, "initializing a function buffer\n"); 778 start = &buf->data.i[0]; 779 780 last = (uint32_t *)(start + 781 ((INDEX_TO_DIOLEN(max_disk_io_len) - SIZEOF_BUFHDR) / 782 sizeof (uint32_t))); 783 784 /* 785 * SPARC: 786 * 787 * We fill the main part of the code with the assembler: 788 * 789 * bn,a 0x2080000a 790 * ZZZZ 791 * 792 * Intel: 793 * 794 * The equivalent to the SPARC operation is: 795 * 796 * nop 797 * nop 798 * jmp .+4 0x04eb9090 799 * ZZZZ 800 * 801 * The random 32 bits along with Intel's non-aligned instructions 802 * means this routine generates some fairly horrible assembler at 803 * first sight. The secret is to follow the jumps themselves even 804 * if they do appear to jump into the middle of other instructions 805 * and not worry about the code that isn't executed. 806 * 807 * General: 808 * 809 * Where ZZZZ is random and will be skipped of over by the 810 * annulled branch. 811 */ 812 813 #if __i386 || __amd64 814 ptr = (uint32_t *)start; 815 *ptr++ = save_asm(); 816 for (; ptr < (last - 2); ptr += 2) { 817 *ptr = 0x04eb9090; 818 #elif __sparc 819 for (ptr = (uint32_t *)(start); ptr < (last - 2); ptr += 2) { 820 *(ptr) = bn_asm(1, 2); /* SPARC branch never annuled */ 821 #else 822 #error "No assembler defined for this processor" 823 #endif 824 if (ptr == (uint32_t *)(start)) 825 *(ptr + 1) = bufno; 826 else 827 *(ptr + 1) = lrand48(); 828 829 } 830 #ifdef __sparc 831 *ptr++ = retl_asm(); /* sparc retl */ 832 #else 833 *ptr++ = ret_asm(); /* Hence the need for save_asm() */ 834 #endif 835 while (ptr < last) { 836 #ifdef __sparc 837 *(ptr++) = nop_asm(); /* SPARC nop */ 838 #else 839 *(ptr++) = NOPWORD; 840 #endif 841 } 842 } 843 void 844 init_func_buf_long(struct buf *buf, int bufno) 845 { 846 uint32_t *start; 847 uint32_t *last; 848 uint32_t *ptr; 849 #if defined(__i386) || defined(__amd64) 850 varlen t_inst; 851 #endif 852 uint32_t jump_size = 0x1FFFF & 853 (lrand48() % (INDEX_TO_DIOLEN(max_disk_io_len) / 854 sizeof (uint32_t))); 855 856 if (jump_size < 2) { 857 init_func_buf_short(buf, bufno); 858 return; 859 } 860 861 plog(LOG_DEBUG, 862 "initializing a long function buffer with jump_size %d\n", 863 jump_size); 864 start = &buf->data.i[0]; 865 866 last = start + 867 ((INDEX_TO_DIOLEN(max_disk_io_len) - SIZEOF_BUFHDR) / 868 sizeof (uint32_t)); 869 870 /* 871 * We fill the main part of the code with the assembler: 872 * 873 * SPARC 874 * 875 * ba,a jump_size 876 * now jump_size - 1 random numbers... 877 * 878 * Intel 879 * 880 * jmpl jump_size 881 * now jump_size - 1 random numbers... 882 * 883 * Where ZZZZ is random and will be skipped over by the 884 * annuled branch never. This is just to get the chksums of 885 * executable sections to be different. 886 */ 887 888 #if defined(__i386) || defined(__amd64) 889 ptr = ((uint32_t *)start); 890 *ptr++ = save_asm(); 891 892 for (; ptr < (last - (jump_size + 2)); ptr += jump_size) { 893 int i; 894 895 #if defined(__amd64) 896 t_inst = jmp_asm((jump_size - 1) * sizeof (uint32_t)); 897 *ptr++ = t_inst.thirtytwo[0]; 898 *ptr = t_inst.thirtytwo[1]; 899 #else 900 t_inst = jmp_asm((jump_size - 1) * sizeof (uint32_t)); 901 *ptr++ = t_inst.thirtytwo[0]; 902 *ptr = t_inst.thirtytwo[1]; 903 #endif 904 #elif defined(SPARC) 905 for (ptr = start; ptr < (last - (jump_size + 2)); 906 ptr += jump_size) { 907 int i; 908 909 /* 0x30800000 | jump_size; SPARC ba,a jump_size */ 910 *ptr = ba_asm(1, jump_size); 911 #else 912 #error "unknown pocesseor type" 913 #endif 914 915 for (i = 0; i < (jump_size - 1); i++) { 916 if (i == 0) 917 *(ptr + 1 + i) = bufno; 918 else 919 *(ptr + 1 + i) = lrand48(); 920 } 921 } 922 #ifdef __sparc 923 *ptr++ = retl_asm(); /* sparc retl */ 924 #else /* Intel */ 925 *ptr++ = ret_asm(); /* Again, hence the save_asm() earlier */ 926 #endif 927 while (ptr < last) { 928 #ifdef __sparc 929 *(ptr++) = nop_asm(); /* SPARC nop */ 930 #else /* Intel */ 931 *(ptr++) = NOPWORD; 932 #endif 933 } 934 } 935 void 936 init_func_buf(uchar_t *cbuf, int bufno) 937 { 938 struct buf *buf; 939 /* 940 * The under lying routines that init function buffers require 941 * correct alignment so if the buffer passed in is not alligned 942 * allocate a correctly aligned one and pass that to the other 943 * routines. memcpy all that data into the original buf. 944 */ 945 if (((ulong_t)cbuf % sizeof (uint64_t)) != 0) { 946 buf = (struct buf *)my_calloc(1, 947 INDEX_TO_DIOLEN(max_disk_io_len)); 948 if (buf == NULL) { 949 pfprintf(stderr, 950 "unable to allocate temporary buffer\n"); 951 exit(1); 952 } 953 } else { 954 /*LINTED Alignment*/ 955 buf = (struct buf *)cbuf; 956 } 957 958 if ((lrand48() % 2) == 1) 959 init_func_buf_long(buf, bufno); 960 else 961 init_func_buf_branch(buf, bufno); 962 963 if (((ulong_t)cbuf % sizeof (uint64_t)) != 0) { 964 (void) memcpy(cbuf, (void *)buf, 965 INDEX_TO_DIOLEN(max_disk_io_len)); 966 free(buf); 967 } 968 } 969 970 struct bufhdr_a 971 conv_bufhdr(struct bufhdr *in) 972 { 973 struct bufhdr_a hdr; 974 ZERO_OBJ(hdr); 975 switch (in->start) { 976 case BUF_TYPE_A: 977 hdr = in->ab.a; 978 break; 979 case BUF_TYPE_B: 980 hdr.devid = in->ab.b.devid; 981 hdr.off = in->ab.b.off; 982 hdr.hdrchksum = in->ab.b.hdrchksum; 983 hdr.len = in->ab.b.len; 984 hdr.type = in->ab.b.type; 985 hdr.chksum = in->ab.b.chksum; 986 hdr.did = in->ab.b.did; 987 hdr.time = in->ab.b.time; 988 memcpy(hdr.serial_and_provider, 989 in->ab.b.serial_and_provider, 990 sizeof (hdr.serial_and_provider)); 991 break; 992 default: 993 hdr.type.BUF_BAD_HDR = 1; 994 break; 995 } 996 return (hdr); 997 } 998 void 999 toggle_bufhdr(uchar_t *buf) 1000 { 1001 struct bufhdr newhdr, hdr; 1002 (void) memset(&newhdr, NULL, sizeof (struct bufhdr)); 1003 hdr = get_bufhdr(buf); 1004 1005 switch (hdr.start) { 1006 case BUF_TYPE_A: 1007 newhdr.ab.b.time = hdr.ab.a.time; 1008 newhdr.ab.b.did = hdr.ab.a.did; 1009 newhdr.ab.b.chksum = hdr.ab.a.chksum; 1010 newhdr.ab.b.off = hdr.ab.a.off; 1011 newhdr.ab.b.type = hdr.ab.a.type; 1012 newhdr.ab.b.hdrchksum = hdr.ab.a.hdrchksum; 1013 newhdr.ab.b.len = hdr.ab.a.len; 1014 newhdr.ab.b.devid = hdr.ab.a.devid; 1015 memcpy(newhdr.ab.b.serial_and_provider, 1016 hdr.ab.a.serial_and_provider, 1017 sizeof (hdr.ab.a.serial_and_provider)); 1018 newhdr.start = newhdr.end = BUF_TYPE_B; 1019 break; 1020 case BUF_TYPE_B: 1021 newhdr.ab.a.chksum = hdr.ab.b.chksum; 1022 newhdr.ab.a.len = hdr.ab.b.len; 1023 newhdr.ab.a.off = hdr.ab.b.off; 1024 newhdr.ab.a.type = hdr.ab.b.type; 1025 newhdr.ab.a.hdrchksum = hdr.ab.b.hdrchksum; 1026 newhdr.ab.a.devid = hdr.ab.b.devid; 1027 newhdr.ab.a.did = hdr.ab.b.did; 1028 newhdr.ab.a.time = hdr.ab.b.time; 1029 memcpy(newhdr.ab.a.serial_and_provider, 1030 hdr.ab.b.serial_and_provider, 1031 sizeof (hdr.ab.b.serial_and_provider)); 1032 newhdr.start = newhdr.end = BUF_TYPE_A; 1033 break; 1034 } 1035 set_bufhdr(buf, newhdr); 1036 } 1037 1038 struct shadow_hdr const * 1039 get_shadow_hdr_by_off(ulong_t off) 1040 { 1041 char *ptr; 1042 1043 ptr = (char *)shadow_headers + (sizeof_shadow_header() * off); 1044 /*LINTED Alignment*/ 1045 return ((struct shadow_hdr *)ptr); 1046 } 1047 1048 struct shadow_hdr const * 1049 get_shadow_hdr(uchar_t *buf) 1050 { 1051 ulong_t off; 1052 1053 off = get_buf_off(buf, write_bufs, INDEX_TO_DIOLEN(max_disk_io_len)); 1054 1055 return (get_shadow_hdr_by_off(off)); 1056 } 1057 1058 struct bufhdr 1059 get_bufhdr(uchar_t *buf) 1060 { 1061 struct bufhdr hdr; 1062 (void) memcpy(&hdr, (char *)buf, sizeof (struct bufhdr)); 1063 return (hdr); 1064 } 1065 1066 struct bufhdr_a 1067 get_bufhdr_a(uchar_t *buf) 1068 { 1069 struct bufhdr_a hdr_a; 1070 struct bufhdr hdr; 1071 1072 hdr = get_bufhdr(buf); 1073 hdr_a = conv_bufhdr(&hdr); 1074 if (hdr_a.type.BUF_BAD_HDR) 1075 pfprintf(stderr, "Unknown buf type: buf %#lx type %#llx\n", 1076 (ulong_t)buf, (long long)hdr.start); 1077 return (hdr_a); 1078 } 1079 1080 void 1081 set_bufhdr(uchar_t *buf, struct bufhdr hdr) 1082 { 1083 (void) memcpy(buf, (char *)&hdr, sizeof (struct bufhdr)); 1084 assert(*buf == 0xAA || *buf == 0x55); 1085 } 1086 1087 struct bufhdr 1088 set_hdr_a(struct bufhdr bufhdr, const struct bufhdr_a hdr) 1089 { 1090 ZERO_OBJ(bufhdr.ab); 1091 switch (bufhdr.start) { 1092 case BUF_TYPE_A: 1093 bufhdr.ab.a = hdr; 1094 break; 1095 case BUF_TYPE_B: 1096 get_serial_and_provider( 1097 bufhdr.ab.b.serial_and_provider, 1098 SIZEOF_SERIAL_AND_PROVIDER); 1099 bufhdr.ab.b.chksum = hdr.chksum; 1100 bufhdr.ab.b.off = hdr.off; 1101 bufhdr.ab.b.len = hdr.len; 1102 bufhdr.ab.b.devid = hdr.devid; 1103 bufhdr.ab.b.hdrchksum = hdr.hdrchksum; 1104 bufhdr.ab.b.type = hdr.type; 1105 bufhdr.ab.b.time = hdr.time; 1106 bufhdr.ab.b.did = hdr.did; 1107 break; 1108 default: 1109 pfprintf(stderr, 1110 "Unknown buf type: buf type %#llx " 1111 "setting to A\n", (long long)bufhdr.start); 1112 bufhdr.ab.a = hdr; 1113 bufhdr.start = bufhdr.end = BUF_TYPE_A; 1114 break; 1115 } 1116 return (bufhdr); 1117 } 1118 static void 1119 set_bufhdr_a(uchar_t *buf, struct bufhdr_a hdr_a) 1120 { 1121 struct bufhdr hdr = get_bufhdr(buf); 1122 set_bufhdr(buf, set_hdr_a(hdr, hdr_a)); 1123 } 1124 static uint64_t 1125 get_hdrchksum(struct bufhdr hdr) 1126 { 1127 struct bufhdr_a hdr_a; 1128 ZERO_OBJ(hdr_a); 1129 hdr_a = conv_bufhdr(&hdr); 1130 return (hdr_a.hdrchksum); 1131 } 1132 ushort16_t 1133 get_bufhdr_hdrchksum(uchar_t *buf) 1134 { 1135 return (get_hdrchksum(get_bufhdr(buf))); 1136 } 1137 ushort16_t 1138 set_hdrchksum(struct bufhdr *hdr) 1139 { 1140 struct bufhdr_a hdr_a; 1141 ushort16_t newchksum; 1142 ZERO_OBJ(hdr_a); 1143 hdr_a = conv_bufhdr(hdr); 1144 newchksum = check_hdr(hdr, hdr_a.hdrchksum); 1145 hdr_a.hdrchksum = newchksum; 1146 *hdr = set_hdr_a(*hdr, hdr_a); 1147 return (newchksum); 1148 } 1149 static uint_t 1150 check_delay() 1151 { 1152 uint_t delay_len; 1153 uint_t i; 1154 1155 if (opts.max_mem_delay == 0) 1156 return (0); 1157 for (i = delay_len = ((uint_t)lrand48() % opts.max_mem_delay); 1158 i > 0; i--) 1159 /* LINTED */ 1160 ; 1161 return (delay_len); 1162 } 1163 1164 ushort16_t 1165 set_buf_hdrchksum(uchar_t *buf) 1166 { 1167 struct bufhdr_a hdr_a; 1168 struct bufhdr hdr; 1169 uint_t delay_len; 1170 1171 hdr = get_bufhdr(buf); 1172 hdr_a = conv_bufhdr(&hdr); 1173 1174 hdr_a.hdrchksum = check_hdr(&hdr, hdr_a.hdrchksum); 1175 1176 set_bufhdr_a(buf, hdr_a); 1177 delay_len = check_delay(); 1178 if (hdr_a.hdrchksum != get_bufhdr_hdrchksum(buf)) { 1179 pfprintf(stderr, "buf %#lx bad header checksum read back " 1180 "from memory after delay %d\n", (ulong_t)buf, 1181 delay_len); 1182 } 1183 return (hdr_a.hdrchksum); 1184 } 1185 void 1186 set_bufhdr_all(uchar_t *buf, check_t chksum, uint32_t len, 1187 struct device_id devid, 1188 ullong_t off, 1189 buf_data_type type, 1190 char sequence, 1191 time_t now) 1192 { 1193 struct bufhdr_a hdr; 1194 ZERO_OBJ(hdr); 1195 hdr = get_bufhdr_a(buf); 1196 hdr.chksum = chksum; 1197 hdr.len = len; 1198 hdr.devid = devid; 1199 hdr.off = off; 1200 hdr.time = now; 1201 hdr.did = master_pid(); 1202 get_serial_and_provider(hdr.serial_and_provider, 1203 SIZEOF_SERIAL_AND_PROVIDER); 1204 hdr.type = type; 1205 hdr.type.sequence = sequence; 1206 hdr.type.padding = 0; /* not used */ 1207 set_bufhdr_a(buf, hdr); 1208 } 1209 void 1210 init_buf(uchar_t *buf) 1211 { 1212 int x; 1213 struct bufhdr hdr; 1214 void *sig; 1215 int bufno = get_write_buf_id(buf); 1216 time_t now; 1217 1218 now = time(NULL); 1219 1220 x = lrand48(); 1221 1222 x = x >> 10; 1223 1224 plog(LOG_DEBUG, "initalizing data buf %#lx\n", (ulong_t)buf); 1225 sig = expect_signal(SIGBUS, "memset", buf, 1226 INDEX_TO_DIOLEN(max_disk_io_len) + opts.write_buffer_gap); 1227 unprotect_buf(buf); 1228 (void) memset((char *)buf, NULL, SIZEOF_BUFHDR); 1229 ZERO_OBJ(hdr); 1230 if (1 == opts.obscure_execute && x % 2) { 1231 init_func_buf(buf, bufno); 1232 hdr.start = hdr.end = BUF_TYPE_B; 1233 hdr.ab.b.chksum = 0; 1234 hdr.ab.b.len = 0; 1235 hdr.ab.b.type.BUF_EXECUTABLE = 1; 1236 hdr.ab.b.time = now; 1237 hdr.ab.b.did = master_pid(); 1238 get_serial_and_provider(hdr.ab.b.serial_and_provider, 1239 SIZEOF_SERIAL_AND_PROVIDER); 1240 } else { 1241 init_data_buf(buf, bufno); 1242 hdr.start = hdr.end = BUF_TYPE_A; 1243 hdr.ab.a.chksum = 0; 1244 hdr.ab.a.len = 0; 1245 hdr.ab.a.type.BUF_EXECUTABLE = 0; 1246 hdr.ab.a.time = now; 1247 hdr.ab.a.did = master_pid(); 1248 get_serial_and_provider(hdr.ab.a.serial_and_provider, 1249 SIZEOF_SERIAL_AND_PROVIDER); 1250 } 1251 (void) set_hdrchksum(&hdr); 1252 set_bufhdr(buf, hdr); 1253 protect_buf(buf); 1254 1255 TNF_PROBE_1(init_buf, "init_buf", "sunw%cte%diskomizer%bufs init", 1256 tnf_opaque, buf, buf); 1257 cancel_expected_signal(SIGBUS, sig); 1258 } 1259 ushort16_t 1260 check_hdr(struct bufhdr *hdr, ushort16_t hdrchksum) 1261 { 1262 uchar_t *x; 1263 ushort16_t total; 1264 char i; 1265 1266 x = (uchar_t *)hdr; 1267 1268 for (i = total = 0; i < SIZEOF_BUFHDR; i++) { 1269 total += x[i]; 1270 } 1271 total -= u_short_chksum(hdrchksum); 1272 1273 return (total); 1274 } 1275 1276 ushort16_t 1277 check_bufhdr(uchar_t *buf, ushort16_t hdrchksum) 1278 { 1279 struct bufhdr hdr = get_bufhdr(buf); 1280 return (check_hdr(&hdr, hdrchksum)); 1281 } 1282 1283 check_t 1284 check_bufbody(uchar_t *buf, ulong_t size) 1285 { 1286 return (check_sum(buf + SIZEOF_BUFHDR, size - SIZEOF_BUFHDR)); 1287 } 1288 1289 check_t 1290 check_aiobuf(struct aio_str *aiop) 1291 { 1292 return (check_buf(aiop->buf, opts.disk_io_sizes.vals[aiop->iolen], 1293 &aiop->error)); 1294 } 1295 1296 check_t 1297 check_buf(uchar_t *buf, int len, struct error *error) 1298 { 1299 struct bufhdr_a hdr_a; 1300 check_t total; 1301 ushort16_t hdrchksum; 1302 struct bufhdr hdr; 1303 1304 hdr = get_bufhdr(buf); 1305 hdr_a = conv_bufhdr(&hdr); 1306 1307 total = check_bufbody(buf, hdr_a.len); 1308 hdrchksum = check_hdr(&hdr, hdr_a.hdrchksum); 1309 1310 if (hdr_a.len != len) { 1311 error->desc.LENGTH_MISMATCH = 1; 1312 error->len = hdr_a.len; 1313 } 1314 if (hdr_a.hdrchksum != hdrchksum) { 1315 dfprintf(stderr, "buf %#lx bad header checksum " 1316 "is %x should be %x\n", (ulong_t)buf, 1317 hdr_a.hdrchksum, hdrchksum); 1318 1319 error->desc.HEADER_CHECKSUM_ERR = 1; 1320 error->bad_checksum = hdrchksum; 1321 return (0); 1322 } 1323 1324 if (hdr_a.chksum != total) { 1325 TNF_PROBE_4(check_buf, "check_buf", 1326 "sunw%cte%diskomizer%bufs check", 1327 tnf_opaque, hdrchksum, hdrchksum, 1328 tnf_opaque, total, total, 1329 tnf_opaque, hdr_a.chksum, hdr_a.chksum, 1330 tnf_opaque, buf, buf); 1331 1332 error->desc.BODY_CHECKSUM_ERR = 1; 1333 error->bad_checksum = total; 1334 1335 if (opts.fix_bad_checksums) { 1336 hdr_a.chksum = total; 1337 set_bufhdr_a(buf, hdr_a); 1338 if (is_executable(buf)) { 1339 dfprintf(stderr, 1340 "buf %#lx bad func checksum %#x != " 1341 "%#llx - fixed\n", (ulong_t)buf, total, 1342 (long long)hdr_a.chksum); 1343 } else { 1344 dfprintf(stderr, 1345 "buf %#lx bad data checksum %#llx != " 1346 "%#llx - fixed\n", (ulong_t)buf, total, 1347 (long long)hdr_a.chksum); 1348 } 1349 } else { 1350 if (is_executable(buf)) { 1351 dfprintf(stderr, 1352 "buf %#lx bad func checksum %#llx != " 1353 "%#llx\n", (ulong_t)buf, total, 1354 (long long)hdr_a.chksum); 1355 } else { 1356 dfprintf(stderr, 1357 "buf %#lx bad data checksum %#llx != " 1358 "%#llx\n", (ulong_t)buf, total, 1359 (long long)hdr_a.chksum); 1360 } 1361 } 1362 } 1363 return (total); 1364 } 1365 void 1366 save_data_bufs(void) 1367 { 1368 FILE *save_file; 1369 uchar_t *buf = write_bufs; 1370 ullong_t blksize = INDEX_TO_DIOLEN(max_disk_io_len) + 1371 opts.write_buffer_gap; 1372 ullong_t len = blksize * opts.nwritebufs; 1373 uint64_t i; 1374 uchar_t *new; 1375 char *path_buf; 1376 time_t now; 1377 if (opts.data_file == NULL || opts.save_data == 0) { 1378 return; 1379 } 1380 1381 path_buf = alloca(strlen(opts.data_file) + 32); 1382 1383 (void) sprintf(path_buf, "%s/data_file", opts.data_file); 1384 1385 (void) mkdir(opts.data_file, 0777); 1386 1387 if ((save_file = fopen(path_buf, "w")) == NULL) { 1388 FOPEN_ERROR(path_buf, "w"); 1389 return; 1390 } 1391 1392 now = time(NULL); 1393 (void) fprintf(save_file, "#\n# diskomizer %s\n# Updated %s#\n", 1394 VERSION, ctime(&now)); 1395 1396 /*LINTED*/ 1397 new = buf; 1398 for (i = 0; i < len/sizeof (uint64_t); i++, new += sizeof (uint64_t)) { 1399 (void) fprintf(save_file, 1400 "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", 1401 *new, *(new+1), *(new+2), *(new+3), 1402 *(new+4), *(new+5), *(new+6), *(new+7)); 1403 if (((ulong_t)new % blksize) == 0) 1404 (void) fprintf(save_file, " # New Block\n"); 1405 else 1406 (void) fprintf(save_file, "\n"); 1407 } 1408 1409 now = time(NULL); 1410 (void) fprintf(save_file, "#\n# diskomizer %s\n# Updated %s#\n", 1411 VERSION, ctime(&now)); 1412 (void) fflush(save_file); 1413 if (fsync(fileno(save_file)) == -1) { 1414 FSYNC_ERROR(fileno(save_file), path_buf); 1415 } 1416 (void) fclose(save_file); 1417 1418 (void) sprintf(path_buf, "%s/option_file", opts.data_file); 1419 if ((save_file = fopen(path_buf, "w")) == NULL) { 1420 FOPEN_ERROR(path_buf, "w"); 1421 return; 1422 } 1423 1424 (void) fprintf(save_file, "# Diskimizer %s\n", VERSION); 1425 (void) print_options(save_file); 1426 1427 (void) fflush(save_file); 1428 if (fsync(fileno(save_file)) == -1) { 1429 FSYNC_ERROR(fileno(save_file), path_buf); 1430 } 1431 (void) fclose(save_file); 1432 } 1433 /* 1434 * This needs rethinking. 1435 */ 1436 static char * 1437 init_from_file(uchar_t *buf, ullong_t len) 1438 { 1439 char *data_file; 1440 char *tmp; 1441 uint64_t *new; 1442 uint64_t i = 0; 1443 time_t last_read = 0; 1444 size_t maping_len; 1445 char *path_buf = opts.data_file; 1446 /*LINTED*/ 1447 new = (uint64_t *)buf; 1448 1449 if ((data_file = map_file(path_buf, &last_read, 1450 &maping_len, pprintf, NULL)) == NULL) { 1451 1452 path_buf = alloca(strlen(opts.data_file) + 10); 1453 (void) sprintf(path_buf, "%s/data_file", opts.data_file); 1454 last_read = 0; 1455 1456 if ((data_file = map_file(path_buf, &last_read, 1457 &maping_len, pprintf, NULL)) == NULL) { 1458 pperror("map_file: can't read data bufs from %s", 1459 path_buf); 1460 return (NULL); 1461 } 1462 } 1463 if (*(data_file+maping_len-1) != '\n') { 1464 pprintf("Incomplete last line in data file %s\n", 1465 path_buf); 1466 (void) munmap(data_file, maping_len); 1467 return (0); 1468 } 1469 *(data_file+maping_len-1) = NULL; 1470 1471 1472 tmp = data_file; 1473 while (i < len/sizeof (uint64_t)) { 1474 char *next; 1475 uint64_t x; 1476 1477 if (*tmp == NULL) 1478 break; 1479 while (*tmp != '0') { 1480 while (*tmp != '\n') { 1481 if (*tmp == NULL) 1482 break; 1483 tmp++; 1484 } 1485 if (*tmp == NULL) 1486 break; 1487 tmp++; 1488 if (*tmp == NULL) 1489 break; 1490 } 1491 if (*tmp == NULL) 1492 break; 1493 if (*tmp == '0' && (*(tmp+1) == 'x' || *(tmp+1) == 'X')) 1494 tmp += 2; 1495 x = strtoull(tmp, &next, 16); 1496 #ifdef _BIG_ENDIAN 1497 *new = x; 1498 #elif defined(_LITTLE_ENDIAN) 1499 swab((char *)&x, (char *)new, sizeof (uint64_t)); 1500 #else 1501 1502 #error "niether _BIG_ENDIAN or _LITTLE_ENDIAN defined" 1503 1504 #endif /* BIG_ENDIAN or _LITTLE_ENDIAN */ 1505 1506 while (*next != '\n') { 1507 if (*next == NULL) 1508 break; 1509 next++; 1510 } 1511 i++; 1512 new++; 1513 if (*next == NULL) 1514 break; 1515 tmp = next + 1; 1516 } 1517 1518 (void) munmap(data_file, maping_len); 1519 return ((char *)&new[0]); 1520 } 1521 int 1522 is_write_io(struct aio_str *aiop) 1523 { 1524 return (aiop->handler == handle_write || 1525 aiop->handler == handle_write_then_read); 1526 } 1527 int 1528 is_read_io(struct aio_str *aiop) 1529 { 1530 return (!is_write_io(aiop)); 1531 } 1532 static void 1533 analyze_header(FILE *out, const struct bufhdr *good, const struct bufhdr *bad) 1534 { 1535 } 1536 /* 1537 * More macro hell. 1538 * 1539 * These 2 macros are used to print information about buffer headers. Before 1540 * calling them, define the macros DO_PRINT, DO_PRINT_BIT_FIELD, DO_PRINT_TIME 1541 * and DO_PRINT_STRING to do what you want. 1542 * 1543 */ 1544 #define PRINT_A_HDR(O) \ 1545 DO_PRINT(O, start); \ 1546 DO_PRINT_STRING(O, ab.a.serial_and_provider); \ 1547 DO_PRINT(O, ab.a.devid.ino); \ 1548 DO_PRINT(O, ab.a.devid.dev); \ 1549 DO_PRINT(O, ab.a.hdrchksum); \ 1550 DO_PRINT_BIT_FIELD(O, ab.a.type); \ 1551 DO_PRINT(O, ab.a.chksum); \ 1552 DO_PRINT(O, ab.a.did); \ 1553 DO_PRINT(O, ab.a.len); \ 1554 DO_PRINT(O, ab.a.off); \ 1555 DO_PRINT_TIME(O, ab.a.time); \ 1556 DO_PRINT(O, end) 1557 #define PRINT_B_HDR(O) \ 1558 DO_PRINT(O, start); \ 1559 DO_PRINT(O, ab.b.off); \ 1560 DO_PRINT_TIME(O, ab.b.time); \ 1561 DO_PRINT(O, ab.b.len); \ 1562 DO_PRINT(O, ab.b.did); \ 1563 DO_PRINT(O, ab.b.devid.ino); \ 1564 DO_PRINT(O, ab.b.devid.dev); \ 1565 DO_PRINT(O, ab.b.hdrchksum); \ 1566 DO_PRINT_BIT_FIELD(O, ab.b.type); \ 1567 DO_PRINT(O, ab.b.chksum); \ 1568 DO_PRINT_STRING(O, ab.b.serial_and_provider); \ 1569 DO_PRINT(O, end) 1570 void 1571 decode_header(FILE *out, uchar_t *good, uchar_t *bad) 1572 { 1573 struct bufhdr bufhdr, bhdr; 1574 (void) memcpy(&bufhdr, good, sizeof (struct bufhdr)); 1575 (void) memcpy(&bhdr, bad, sizeof (struct bufhdr)); 1576 (void) fprintf(out, "%29s %18s %18s\n", gettext("Decoding header"), 1577 gettext("Good"), gettext("Bad")); 1578 #define DO_PRINT(O, A) (void) fprintf(O, "hdr.%-25s %#18llx %#18llx\n", #A, \ 1579 (long long)bufhdr.A, (long long)bhdr.A) 1580 1581 #define DO_PRINT_STRING(O, A) (void) fprintf(O, "hdr.%-25s \"%.*s\"\n" \ 1582 "%-48s \"%.*s\"\n", #A, (int)sizeof (bufhdr.A), bufhdr.A, " ", \ 1583 (int)sizeof (bhdr.A), bhdr.A) 1584 1585 #define DO_PRINT_TIME(O, A) {\ 1586 char *x = alloc_time_str(bufhdr.A);\ 1587 \ 1588 if (x != NULL) {\ 1589 fprintf(O, "hdr.%-25s \"%s\"\n", #A, x); \ 1590 free(x);\ 1591 if ((x = alloc_time_str(bhdr.A)) != NULL) {\ 1592 fprintf(O, "%-48s \"%s\"\n", " ", x);\ 1593 free(x);\ 1594 }\ 1595 }\ 1596 } 1597 1598 #define DO_PRINT_BIT_FIELD(O, A) \ 1599 DO_PRINT(O, A.BUF_EXECUTABLE); \ 1600 DO_PRINT(O, A.BUF_BAD_HDR); \ 1601 DO_PRINT(O, A.BUF_BAD_CHKSUM); \ 1602 DO_PRINT(O, A.BUF_READ_ONLY); \ 1603 DO_PRINT(O, A.BUF_READY); \ 1604 DO_PRINT(O, A.sequence) 1605 /* 1606 * If both headers are of the same type and both have good check sums then 1607 * only decode the header as the claim to be. 1608 */ 1609 if (bhdr.start != BUF_TYPE_B || bufhdr.start != BUF_TYPE_B || 1610 check_hdr(&bhdr, bhdr.ab.b.hdrchksum) != bhdr.ab.b.hdrchksum || 1611 check_hdr(&bufhdr, bufhdr.ab.b.hdrchksum) != 1612 bufhdr.ab.b.hdrchksum) { 1613 PRINT_A_HDR(out); 1614 } 1615 if (bhdr.start != BUF_TYPE_A || bufhdr.start != BUF_TYPE_A || 1616 check_hdr(&bhdr, bhdr.ab.a.hdrchksum) != bhdr.ab.a.hdrchksum || 1617 check_hdr(&bufhdr, bufhdr.ab.a.hdrchksum) != 1618 bufhdr.ab.a.hdrchksum) { 1619 PRINT_B_HDR(out); 1620 } 1621 #undef DO_PRINT 1622 #undef DO_PRINT_TIME 1623 #undef DO_PRINT_BIT_FIELD 1624 #undef DO_PRINT_STRING 1625 } 1626 void 1627 print_bufhdr_offsets(FILE *out) 1628 { 1629 #define bufhdr (*((struct bufhdr *)0)) 1630 static const char heading[] = "Element Offset" 1631 " Size\n"; 1632 static const char fmt[] = "bufhdr.%-14s 0x%2.2lx (0t%3.3ld) " 1633 "sizeof (bufhdr.%-14s) 0x%2.2x (0t%2.2d)\n"; 1634 static const char fmt2[] = "bufhdr.%s\n%-21s 0x%2.2lx (0t%3.3ld) " 1635 "sizeof (bufhdr.%-14.14s) 0x%2.2x (0t%2.2d)\n"; 1636 1637 #define DO_PRINT(O, A) \ 1638 if (strlen(#A) > 14) { \ 1639 (void) fprintf(O, fmt2, #A, " ", \ 1640 ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), \ 1641 ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), #A, \ 1642 sizeof (bufhdr.A), sizeof (bufhdr.A)); \ 1643 } else { \ 1644 (void) fprintf(O, \ 1645 fmt, #A, ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), \ 1646 ((ulong_t)&bufhdr.A) - ((ulong_t)&bufhdr), #A, \ 1647 sizeof (bufhdr.A), sizeof (bufhdr.A)); \ 1648 } 1649 #define DO_PRINT_STRING(O, A) DO_PRINT(O, A) 1650 #define DO_PRINT_TIME(O, A) DO_PRINT(O, A) 1651 #define DO_PRINT_BIT_FIELD(A, B) DO_PRINT(A, B) 1652 1653 (void) fprintf(out, 1654 "Type A buffer header start and end value = %#llx:\n", 1655 (unsigned long long)BUF_TYPE_A); 1656 (void) fprintf(out, heading); 1657 PRINT_A_HDR(out); 1658 (void) fprintf(out, 1659 "Type B buffer header start and end value = %#llx:\n", 1660 (unsigned long long)BUF_TYPE_B); 1661 (void) fprintf(out, heading); 1662 PRINT_B_HDR(out); 1663 #undef bufhdr 1664 } 1665 uchar_t * 1666 get_read_buf(void) 1667 { 1668 static ullong_t next_off; 1669 uchar_t *buf; 1670 buf = get_buf(read_bufs, opts.nreadbufs, 1671 INDEX_TO_DIOLEN(max_disk_io_len), 1672 readmap, readmap_size, &next_off); 1673 TNF_PROBE_1(get_read_buf, "get_read_buf", 1674 "sunw%cte%diskomizer%bufs get read", 1675 tnf_opaque, buf, buf); 1676 return (buf); 1677 } 1678 void 1679 return_read_buf(uchar_t *buf) 1680 { 1681 TNF_PROBE_1(return_read_buf, "return_read_buf", 1682 "sunw%cte%diskomizer%bufs return read", 1683 tnf_opaque, buf, buf); 1684 return_buf(buf, read_bufs, INDEX_TO_DIOLEN(max_disk_io_len), readmap, 1685 readmap_size, opts.nreadbufs); 1686 } 1687 void 1688 init_read_bufs(struct device *devices) 1689 { 1690 int ndevices = how_many_devices(devices); 1691 int total_reads = opts.rthreads + opts.wrthreads; 1692 ulong_t tmp, tmp1; 1693 #ifndef _LP64 1694 long long q; 1695 ulong_t x; 1696 #endif 1697 assert(ndevices); 1698 assert(opts.nprocs); 1699 if (is_readonly()) { 1700 total_reads += opts.wthreads; 1701 } 1702 tmp1 = tmp = ndevices*opts.nprocs*total_reads; 1703 1704 tmp = (tmp*11)/10; 1705 1706 if (opts.nreadbufs == 0) 1707 opts.nreadbufs = tmp1 * opts.obscure_buffer_multiplier; 1708 1709 /* 1710 * Make sure that there is at least one spare block per 1711 * process. 1712 */ 1713 tmp1 += opts.nprocs; 1714 1715 tmp = MAX(tmp, tmp1); 1716 1717 opts.nreadbufs = MAX(opts.nreadbufs, tmp); 1718 1719 assert(opts.nreadbufs); 1720 tmp = opts.nreadbufs; 1721 tmp = (tmp % MAP_BITS ? 1 : 0) + tmp / MAP_BITS; 1722 1723 if (opts.obscure_readmap_size == 0) 1724 readmap_size = tmp; 1725 else 1726 readmap_size = opts.obscure_readmap_size; 1727 print_number((long long)opts.nreadbufs, "read buf", "read bufs"); 1728 1729 #ifndef _LP64 1730 q = opts.nreadbufs; 1731 q *= INDEX_TO_DIOLEN(max_disk_io_len); 1732 x = 0; 1733 x = ~x; 1734 if (q > (long long)x) { 1735 pprintf("Read buffers (%#llx) will not fit in a " 1736 "%d (%#x) bit address space\n", 1737 q, sizeof (long) * 8, sizeof (long) * 8); 1738 pprintf("nreadbufs * block_size: %#lx * %#lx = %#llx\n", 1739 opts.nreadbufs, 1740 (ulong_t)INDEX_TO_DIOLEN(max_disk_io_len), q); 1741 /* exit (1); */ 1742 } 1743 #endif 1744 1745 plog(LOG_DEBUG, "Allocating %ld * %ld\n", opts.nreadbufs, 1746 INDEX_TO_DIOLEN(max_disk_io_len) * sizeof (char)); 1747 1748 assert(opts.nreadbufs); 1749 alloc_io_bufs(opts.nreadbufs, INDEX_TO_DIOLEN(max_disk_io_len), 1750 readmap_size, &read_bufs, &readmap); 1751 print_number((long long)(readmap_size * MAP_BITS), "Bit in read map", 1752 "Bits in read map"); 1753 } 1754 uchar_t * 1755 get_buf_data(uchar_t *buf) 1756 { 1757 return (buf + SIZEOF_BUFHDR); 1758 } 1759 void 1760 alloc_io_bufs(ulong_t nbufs, ulong_t buf_size, ulong_t map_size, 1761 unsigned char **bufs, bitmap_t **map) 1762 { 1763 1764 *bufs = (uchar_t *)alloc_mem(nbufs, buf_size * sizeof (char)); 1765 *map = (bitmap_t *)alloc_mem(map_size, sizeof (bitmap_t)); 1766 } 1767 char 1768 is_executable(uchar_t *buf) 1769 { 1770 struct bufhdr_a hdr = get_bufhdr_a(buf); 1771 return (hdr.type.BUF_EXECUTABLE); 1772 } 1773 void 1774 random_string(char *str, int len) 1775 { 1776 int i; 1777 1778 for (i = 0; i < len; i++) { 1779 str[i] = (char)(0x7f & lrand48()); 1780 } 1781 } 1782 void 1783 set_serial_and_provider(void) 1784 { 1785 char serial[257]; 1786 char provider[257]; 1787 1788 ZERO_OBJ(serial_and_provider); 1789 1790 if (sysinfo(SI_HW_SERIAL, &serial[0], sizeof (serial)) == -1) { 1791 int err = errno; 1792 1793 random_string(serial, sizeof (serial)); 1794 plog(LOG_NOTICE, "Unable to determine serial number: %s. " 1795 "Using random value of %s", strerror(err), serial); 1796 } 1797 if (sysinfo(SI_HW_PROVIDER, &provider[0], sizeof (provider)) == -1) { 1798 int err = errno; 1799 random_string(provider, sizeof (provider)); 1800 plog(LOG_NOTICE, "Unable to determine hardware provider: %s. " 1801 "Using random value of %s", strerror(err), provider); 1802 } 1803 snprintf(serial_and_provider, sizeof (serial_and_provider), 1804 "%.24s%s", serial, provider); 1805 } 1806 void 1807 get_serial_and_provider(char *buf, int len) 1808 { 1809 memcpy(buf, serial_and_provider, MIN(SIZEOF_SERIAL_AND_PROVIDER, len)); 1810 } 1811 void 1812 print_serial_and_provider(FILE *out) 1813 { 1814 int i; 1815 (void) fprintf(out, 1816 "Serial and provider:\n\tASCII\n\t\t\"%s\"\n\tHex:\n\t\t\"", 1817 serial_and_provider); 1818 for (i = 0; i < SIZEOF_SERIAL_AND_PROVIDER; i++) { 1819 (void) fprintf(out, "%2.2x", serial_and_provider[i]); 1820 } 1821 (void) fprintf(out, "\"\n"); 1822 1823 } 1824 1825 int 1826 cmp_serial_and_provider(const char *buf) 1827 { 1828 return (memcmp(buf, serial_and_provider, SIZEOF_SERIAL_AND_PROVIDER)); 1829 } 1830