PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/tools/diskomizer/bufs.c

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