8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / avs / sdbc / sd_diag.c
blob706f547226f3cd2e60f747ad482f9c15f9fcb783
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* #include <version.h> SKK */
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <sys/param.h>
32 #include <sys/inttypes.h>
33 #include <stdio.h>
34 #include <strings.h>
35 #include <fcntl.h>
36 #include <sys/shm.h>
37 #include <sys/wait.h>
38 #include <unistd.h>
39 #include <nsctl.h>
41 #include <sys/nsctl/sd_cache.h>
42 #include <sys/nsctl/sd_conf.h>
44 #include <stdlib.h>
45 #include <thread.h>
46 #include <synch.h>
48 #define MAXPARTS 100 /* Max disks */
49 #define MAXBUF 65536 /* Max buffer size in long words */
50 #define DISKLIST "disk_config" /* Default config file */
51 #define DEF_SIZE 8192 /* Default buffer size */
52 #define DEF_LOOP 1000 /* Loops for test */
53 #define RAND_LOOPS DEF_LOOP /* # of random ios to do */
56 * >>>>>>>>> USER LEVEL SD CACHE DIAGNOSTICS <<<<<<<<<<
58 * Write and read data blocks w/multiple processes
59 * Starts one process for each partition specified in
60 * the config file
63 int buf1[MAXBUF];
64 int buf2[MAXBUF];
65 char name[MAXPARTS][80];
66 int pattern[MAXPARTS];
67 int bufsize = DEF_SIZE;
68 int fba_num_bufsize;
69 nsc_size_t loops = DEF_LOOP;
70 nsc_size_t r_loops = RAND_LOOPS;
71 int fsize = -1;
72 int readercount = 3;
73 int Rflag = O_EXCL;
74 char config_file[32];
76 int
77 read_parts()
79 FILE *dfile;
80 int partitions = 0;
81 int i;
83 dfile = fopen(config_file, "r");
84 if (dfile == NULL) {
85 (void) printf("cannot open file: %s\n", config_file);
86 perror("fopen");
87 exit(errno);
89 for (i = 0; i < MAXPARTS; i++) {
90 if (fscanf(dfile, "%s %x", name[i], (uint_t *)&pattern[i]) ==
91 EOF) {
92 break;
93 } else
94 if (name[i][0] == '#' || strchr(name[i], '/') == NULL) {
95 i--;
96 continue;
98 partitions++;
100 (void) fclose(dfile);
101 (void) printf("No. of partitions listed in file '%s' = %d\n\n",
102 config_file, partitions);
103 return (partitions);
106 void
107 print_usage()
109 (void) printf("Usage:\n");
110 (void) printf(
111 "sd_diag [-R] [-b <bufsize>] [-d <datasize>] [-l <loops>] [-r <readers>]\n");
112 (void) printf(
113 " [-f <disk_config_file>] <test#>\n");
114 (void) printf(" test 1 = random read/write\n");
115 (void) printf(" 2 = random read/write/verify, read after write\n");
116 (void) printf(" 3 = random read/write/verify,");
117 (void) printf(" all reads after all writes\n");
118 (void) printf(" 4 = sequential read/write\n");
119 (void) printf(" 5 = sequential write/read/verify,");
120 (void) printf(" all reads after all writes\n");
121 (void) printf(
122 " 6 = altenating top/bottom sequential read/write/verify\n");
123 (void) printf(" 7 = multiple readers/1 random writer\n");
124 (void) printf(" 8 = random writes\n");
125 (void) printf(" 9 = sequential write of known data\n");
126 (void) printf(" 10 = sequential copy of datasize disk/verify\n");
127 (void) printf(" 11 = sequential read/verify test 9 data -");
128 (void) printf(" then clear data with timestamp\n");
129 (void) printf(" 12 = sequential read/verify test 9 data -");
130 (void) printf(" no clear data\n");
131 (void) printf("\n");
132 (void) printf(" <bufsize> in bytes (minimum is 512 bytes)\n");
133 (void) printf(" <datasize> in Mbytes per disk\n");
134 (void) printf(" <loops> is count of reads/writes,\n");
135 (void) printf(" loops = 0 tests entire datasize disk");
136 (void) printf(" for sequential tests.\n");
137 (void) printf(" loops = 0 performs %d I/Os for the random "
138 "tests\n", RAND_LOOPS);
139 (void) printf(" <readers> is count of readers for test #7 (default "
140 "is 3).\n");
141 (void) printf(" [ defaults: bufsize = %d bytes, loops = %d,",
142 DEF_SIZE, DEF_LOOP);
143 (void) printf(" datasize = disksize ]\n");
144 (void) printf("\n");
145 (void) printf(" -R : do nsc_reserve(), nsc_release(0 around each "
146 "I/O\n");
149 void
150 parse_opts(int argc, char *argv[])
152 extern char *optarg;
153 int c;
155 while ((c = getopt(argc, argv, "b:d:l:r:Rf:")) != -1) {
156 switch (c) {
157 case 'f':
158 /* printf("\n%s", optarg); */
159 (void) strcpy(config_file, optarg);
160 break;
161 case 'b':
162 /* bufsize between 1*512 and 512*512 */
163 bufsize = strtol(optarg, 0, 0);
164 if (bufsize > (MAXBUF*4))
165 bufsize = MAXBUF*4;
166 else if (bufsize < FBA_SIZE(1))
167 bufsize = FBA_SIZE(1);
168 break;
169 case 'd':
170 /* convert datasize from Mb's to fba */
171 fsize = strtol(optarg, 0, 0) * FBA_NUM(1 << 20);
172 break;
173 case 'l':
174 loops = (nsc_size_t)strtoll(optarg, 0, 0);
175 break;
176 case 'r':
177 /* count of readers for test 7 */
178 readercount = strtol(optarg, 0, 0);
179 break;
180 case 'R':
181 /* do reserve, release on a per io basis */
182 Rflag = 0;
183 break;
184 case '?':
185 print_usage();
186 exit(0);
189 bufsize &= ~FBA_MASK; /* multiple of 512 bytes for SECTMODE I/O */
190 fba_num_bufsize = FBA_NUM(bufsize);
192 /* set #ios for random io tests */
193 if (loops != 0)
194 r_loops = loops;
198 nsc_size_t
199 set_part_size(char *path, nsc_fd_t *sdfd)
201 nsc_size_t filesize;
202 int rc;
204 rc = nsc_partsize(sdfd, &filesize); /* partsize in FBAs (512 bytes) */
205 if (rc < 0 || filesize == 0) {
206 (void) fprintf(stderr,
207 "set_part_size: cannot access partition size");
208 (void) fprintf(stderr, " for %s\n", path);
209 (void) nsc_close(sdfd);
210 exit(1);
213 (void) printf("Partition %s, size:%" NSC_SZFMT " blocks\n", path,
214 filesize);
216 if (fsize != -1 && fsize < filesize)
217 filesize = fsize;
218 filesize -= fba_num_bufsize;
219 if (filesize < fba_num_bufsize) {
220 (void) printf("ERROR: Max block size %" NSC_SZFMT "\n",
221 filesize);
222 (void) nsc_close(sdfd);
223 exit(0);
226 return (filesize);
230 do_sdtest1(int fd, nsc_size_t loops, nsc_size_t filesize)
232 nsc_off_t seekpos;
233 nsc_size_t i;
234 ssize_t r;
236 for (i = 0; i < loops; i++) {
237 seekpos = (
238 #ifdef NSC_MULTI_TERABYTE
239 ((nsc_off_t)rand() << 48) | ((nsc_off_t)rand() << 32) |
240 #endif
241 (rand() << 16) | rand()) % filesize;
242 r = pwrite(fd, buf1, bufsize, (off_t)(seekpos << SCTRSHFT));
243 if (r <= 0) {
244 perror("Test1: write");
245 return (1);
247 seekpos = (
248 #ifdef NSC_MULTI_TERABYTE
249 ((nsc_off_t)rand() << 48) | ((nsc_off_t)rand() << 32) |
250 #endif
251 (rand() << 16) | rand()) % filesize;
252 r = pread(fd, buf2, bufsize, (off_t)(seekpos << SCTRSHFT));
253 if (r <= 0) {
254 perror("Test1: read");
255 return (1);
258 return (0);
261 void
262 gen_data(int *buffer, int size)
264 int i;
266 size /= 4;
267 for (i = 0; i < size; i++)
268 buffer[i] = rand() << 16 | rand();
272 do_sdtest2(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
274 nsc_off_t seekpos;
275 int err = 0;
276 ssize_t r;
277 nsc_size_t i;
279 for (i = 0; i < loops; i++) {
280 seekpos = (
281 #ifdef NSC_MULTI_TERABYTE
282 ((nsc_off_t)rand() << 48) | ((nsc_off_t)rand() << 32) |
283 #endif
284 (rand() << 16) | rand()) % filesize;
285 gen_data(buf1, bufsize);
286 r = pwrite(fd, buf1, bufsize, (off_t)(seekpos << SCTRSHFT));
287 if (r <= 0) {
288 perror("Test2: write");
289 err++;
290 return (err);
292 r = pread(fd, buf2, bufsize, (off_t)(seekpos << SCTRSHFT));
293 if (r <= 0) {
294 perror("Test2: read");
295 err++;
296 return (err);
298 if (memcmp(buf1, buf2, bufsize)) {
299 (void) printf("Test2: Data corruption,"
300 " fd:%s, fpos:%" PRId64 ", len:%d\n",
301 name[h], (int64_t)(seekpos << SCTRSHFT),
302 bufsize);
303 err++;
306 return (err);
310 do_sdtest3(int fd, nsc_size_t loops, nsc_size_t filesize, int h, nsc_fd_t *sdfd)
312 nsc_off_t *seekpos;
313 int err = 0;
314 nsc_size_t i;
315 ssize_t r;
317 seekpos = malloc(loops*sizeof (nsc_off_t));
318 if (seekpos == NULL) {
319 perror("Test3: malloc");
320 (void) nsc_close(sdfd);
321 exit(errno);
323 gen_data(buf1, bufsize);
325 for (i = 0; i < loops; i++) {
326 seekpos[i] = (
327 #ifdef NSC_MULTI_TERABYTE
328 ((nsc_off_t)rand() << 48) | ((nsc_off_t)rand() << 32) |
329 #endif
330 (rand() << 16) | rand()) % filesize;
331 seekpos[i] -= seekpos[i] % fba_num_bufsize;
332 r = pwrite(fd, buf1, bufsize, (off_t)(seekpos[i] << SCTRSHFT));
333 if (r <= 0) {
334 perror("Test3: write");
335 err++;
336 goto cleanup;
339 for (i = 0; i < loops; i++) {
340 buf2[0] = '\0'; /* clear buf to make sure something is read */
341 r = pread(fd, buf2, bufsize, (off_t)(seekpos[i] << SCTRSHFT));
342 if (r <= 0) {
343 perror("Test3: read");
344 err++;
345 goto cleanup;
347 if (memcmp(buf1, buf2, bufsize)) {
348 (void) printf("Data corruption, fd:%s, fpos:%" PRId64
349 ", len:%d\n", name[h],
350 (int64_t)(seekpos[i] << SCTRSHFT), bufsize);
351 err++;
355 cleanup:
356 free(seekpos);
357 return (err);
361 do_sdtest4(int fd, nsc_size_t loops, nsc_size_t filesize)
363 ssize_t r;
364 nsc_size_t i;
367 * Do sequential reads/writes for loops number
368 * of bufsize chunks, unless loops == 0, then do
369 * entire disk.
370 * 1. sequential reads from the top down,
371 * 2. sequential writes from the top down,
372 * 3. sequential reads from the bottom up,
373 * 4. sequential writes from the bottom up.
375 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
376 loops = filesize / fba_num_bufsize; /* entire disk */
378 for (i = 0; i < loops; i++) {
379 r = pread(fd, buf2, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
380 if (r <= 0) {
381 perror("Test4: read");
382 return (1);
385 for (i = 0; i < loops; i++) {
386 r = pwrite(fd, buf1, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
387 if (r <= 0) {
388 perror("Test4: write");
389 return (1);
392 for (i = loops - 1; i + 1 > 0; i--) {
393 r = pread(fd, buf2, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
394 if (r <= 0) {
395 perror("Test4: read");
396 return (1);
399 for (i = loops - 1; i + 1 > 0; i--) {
400 r = pwrite(fd, buf1, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
401 if (r <= 0) {
402 perror("Test4: write");
403 return (1);
406 return (0);
410 do_sdtest5(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
412 int err = 0;
413 ssize_t r;
414 nsc_size_t i;
417 * Do sequential writes with verify reads for loops number
418 * of bufsize chunks, unless loops == 0, then do
419 * entire disk.
420 * 1. sequential writes from the top down,
421 * 2. sequential reads from the top down with verify,
422 * 3. sequential writes from the bottom up,
423 * 4. sequential reads from the bottom up with verify.
425 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
426 loops = filesize / fba_num_bufsize; /* entire disk */
428 gen_data(buf1, bufsize);
430 for (i = 0; i < loops; i++) {
431 r = pwrite(fd, buf1, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
432 if (r <= 0) {
433 perror("Test5: write");
434 err++;
435 return (err);
438 for (i = 0; i < loops; i++) {
439 buf2[0] = '\0'; /* clear buf to make sure something is read */
440 r = pread(fd, buf2, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
441 if (r <= 0) {
442 perror("Test5: read");
443 err++;
444 return (err);
446 if (memcmp(buf1, buf2, bufsize)) {
447 (void) printf("Test5: Data corruption,"
448 " fd:%s, fpos:%" NSC_SZFMT ", len:%d\n",
449 name[h], i, bufsize);
450 err++;
454 gen_data(buf1, bufsize);
456 for (i = loops - 1; i + 1 > 0; i--) {
457 r = pwrite(fd, buf1, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
458 if (r <= 0) {
459 perror("Test5: write");
460 err++;
461 return (err);
464 for (i = loops - 1; i + 1 > 0; i--) {
465 buf2[0] = '\0'; /* clear buf to make sure something is read */
466 r = pread(fd, buf2, bufsize, (i*fba_num_bufsize) << SCTRSHFT);
467 if (r <= 0) {
468 perror("Test5: read");
469 err++;
470 return (err);
472 if (memcmp(buf1, buf2, bufsize)) {
473 (void) printf("Test5: Data corruption,"
474 " fd:%s, fpos:%" NSC_SZFMT ", len:%d\n",
475 name[h], i, bufsize);
476 err++;
479 return (err);
484 do_sdtest6(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
486 int err = 0;
487 nsc_size_t i;
488 ssize_t r;
489 nsc_size_t endloop = filesize / fba_num_bufsize;
490 int buf3[MAXBUF];
491 int buf4[MAXBUF];
492 nsc_off_t top_pos, bottom_pos;
495 * Do alternating top down and bottom up sequential writes
496 * (working towards middle) and verify with reads
497 * for loops number of bufsize chunks, unless loops == 0, then do
498 * entire disk.
500 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
501 loops = filesize / fba_num_bufsize; /* entire disk */
503 for (i = 0; i < loops; i++) {
504 gen_data(buf1, bufsize);
505 bottom_pos = i*fba_num_bufsize;
506 r = pwrite(fd, buf1, bufsize, (off_t)(bottom_pos << SCTRSHFT));
507 if (r <= 0) {
508 perror("Test6: write");
509 err++;
510 return (err);
512 gen_data(buf2, bufsize);
513 top_pos = (endloop - i - 1)*fba_num_bufsize;
515 /* Make sure we don't collide in the middle */
517 if (abs(top_pos - bottom_pos) < fba_num_bufsize)
518 top_pos = bottom_pos + fba_num_bufsize;
520 r = pwrite(fd, buf2, bufsize, (off_t)(top_pos << SCTRSHFT));
521 if (r <= 0) {
522 perror("Test6: write");
523 err++;
524 return (err);
526 r = pread(fd, buf3, bufsize, (off_t)(bottom_pos << SCTRSHFT));
527 if (r <= 0) {
528 perror("Test6: read");
529 err++;
530 return (err);
532 if (memcmp(buf1, buf3, bufsize)) {
533 (void) printf("Data corruption(1), fd:%s, fpos:%"
534 PRId64 ", len:%d\n", name[h],
535 (int64_t)(bottom_pos << SCTRSHFT), bufsize);
536 err++;
538 r = pread(fd, buf4, bufsize, (off_t)(top_pos << SCTRSHFT));
539 if (r <= 0) {
540 perror("Test6: read");
541 return (1);
543 if (memcmp(buf2, buf4, bufsize)) {
544 (void) printf("Test6: Data corruption(2),"
545 " fd:%s, fpos:%" PRId64 ", len:%d\n",
546 name[h], (int64_t)(top_pos << SCTRSHFT), bufsize);
547 err++;
550 return (err);
553 int shmid;
555 #define MAXREADERS 32
557 struct shm_struct {
558 int writebuf[MAXBUF];
559 volatile nsc_off_t writepos;
560 int quit;
561 int err;
562 mutex_t err_mutex;
563 int rd_done[MAXREADERS];
564 int rd_done_mask[MAXREADERS];
565 } *shm;
567 #define WRITEBUF (shm->writebuf)
568 #define WRITEPOS (shm->writepos)
570 #define QUIT (shm->quit)
571 #define ERR (shm->err)
572 #define ERRMUTEX (shm->err_mutex)
573 #define RD_DONE (shm->rd_done)
574 #define RD_DONE_MASK (shm->rd_done_mask)
576 #define LOCKWRITE
577 #define LOCKREAD(i)
579 /* Clear RD_DONE and Set WRITEPOS */
580 #define FREEWRITE { \
581 bzero(RD_DONE, sizeof (RD_DONE)); \
582 WRITEPOS = wr_pos; }
584 /* Reader i+1 marks himself as finished */
585 #define FREEREAD(i) (RD_DONE[(i)] = 1)
589 do_sdtest7read(int fd, int h, int which)
591 int err;
592 ssize_t r_rd;
593 nsc_off_t curr_pos;
594 nsc_size_t loop_cnt;
595 err = 0; curr_pos = 0; loop_cnt = 0;
596 for (;;) {
597 /* Already read this? */
598 if (curr_pos == WRITEPOS) {
599 if (!QUIT) {
600 continue;
601 } else {
602 /* Time to go! */
603 /* printf("Quitting [%d]\n", which+1); */
604 break;
608 /* get location to read from */
609 curr_pos = WRITEPOS;
611 r_rd = pread(fd, buf1, bufsize, (curr_pos << SCTRSHFT));
612 loop_cnt += 1;
613 if (r_rd <= 0) {
614 FREEREAD(which);
615 perror("Test7: read");
616 err += 1;
617 continue;
620 if (memcmp(buf1, WRITEBUF, bufsize)) {
621 FREEREAD(which);
622 (void) printf("\nTest7: Data corruption, reader #%d, "
623 "fd:%s, \
624 fpos:%" PRId64 ", len:%d\n", which + 1, name[h],
625 (int64_t)(curr_pos << SCTRSHFT), bufsize);
626 err += 1;
627 continue;
630 FREEREAD(which);
633 (void) printf(
634 "Partition %s, Test 7, reader #%d: %d errors %lld loops\n",
635 name[h], which+1, err, loop_cnt);
637 if (err > 0) {
638 (void) mutex_lock(&ERRMUTEX);
639 ERR += err;
640 (void) mutex_unlock(&ERRMUTEX);
643 if (err)
644 return (1);
645 else
646 return (0);
651 do_sdtest7write(int fd, nsc_size_t filesize, int h)
653 int err = 0;
654 ssize_t r;
655 nsc_off_t wr_pos;
657 /* Wait for readers to finish */
658 while (memcmp(RD_DONE, RD_DONE_MASK, readercount*sizeof (int)))
661 gen_data(WRITEBUF, bufsize);
662 wr_pos = (
663 #ifdef NSC_MULTI_TERABYTE
664 ((nsc_off_t)rand() << 48) | ((nsc_off_t)rand() << 32) |
665 #endif
666 (rand() << 16) | rand()) % filesize;
667 r = pwrite(fd, WRITEBUF, bufsize, (off_t)(wr_pos << SCTRSHFT));
668 if (r <= 0) {
669 FREEWRITE;
670 perror("Test7: write");
671 return (1);
673 FREEWRITE;
675 /* verify write */
676 r = pread(fd, buf1, bufsize, (off_t)(wr_pos << SCTRSHFT));
677 if (r <= 0) {
678 perror("Test7: writer: read");
679 return (1);
683 if (memcmp(buf1, WRITEBUF, bufsize)) {
684 (void) printf("\nTest7: Data corruption in writer,"
685 " fd:%s, fpos:%" PRId64 ", len:%d\n",
686 name[h], (int64_t)(wr_pos << SCTRSHFT), bufsize);
687 err++;
691 return (err);
694 void
695 init_shm()
697 int i;
699 /* Clear out everything */
700 bzero(shm, sizeof (struct shm_struct));
702 (void) mutex_init(&ERRMUTEX, USYNC_PROCESS, NULL);
704 /* Set up mask (constant) to test reader doneness */
705 for (i = 0; i < readercount; i++)
706 RD_DONE_MASK[i] = 1;
708 /* Mark all readers done - so writer can start */
709 for (i = 0; i < readercount; i++)
710 RD_DONE[i] = 1;
714 do_sdtest7(int fd, nsc_size_t loops, nsc_size_t filesize, int h, nsc_fd_t *sdfd)
716 int r, i, err;
717 nsc_size_t j;
719 if ((shmid = shmget(IPC_PRIVATE, sizeof (struct shm_struct),
720 IPC_CREAT | 0666)) < 0) {
721 perror("shmget error: ");
722 (void) nsc_close(sdfd);
723 exit(1);
726 shm = (struct shm_struct *)shmat(shmid, NULL, 0);
727 if (shm == (struct shm_struct *)-1) {
728 perror("shmat error: ");
729 (void) nsc_close(sdfd);
730 exit(1); /* cleanup exits */
733 init_shm();
735 /* Start Readers */
736 for (i = 0; i < readercount; i++) {
737 r = fork();
738 if (r == 0) { /* child */
739 (void) do_sdtest7read(fd, h, i);
740 (void) nsc_close(sdfd);
741 exit(0);
742 } else
743 continue;
746 /* Start Writer */
747 srand(getpid()); err = 0;
748 for (j = 0; j < loops; j++) {
749 err += do_sdtest7write(fd, filesize, h);
751 QUIT = 1;
753 (void) printf("\n\nPartition %s, Test 7, writer: %d errors\n",
754 name[h], err);
756 for (i = 0; i < readercount; i++)
757 (void) wait(0);
759 /* No lock needed here - everybody's finished */
760 err += ERR;
762 (void) mutex_destroy(&ERRMUTEX);
763 (void) shmctl(shmid, IPC_RMID, 0);
764 return (err);
768 do_sdtest8(int fd, nsc_size_t loops, nsc_size_t filesize)
770 nsc_off_t seekpos;
771 int err = 0;
772 ssize_t r;
773 nsc_size_t i;
775 for (i = 0; i < loops; i++) {
776 seekpos = (
777 #ifdef NSC_MULTI_TERABYTE
778 ((nsc_off_t)rand() << 48) | ((nsc_off_t)rand() << 32) |
779 #endif
780 (rand() << 16) | rand()) % filesize;
781 gen_data(buf1, bufsize);
782 r = pwrite(fd, buf1, bufsize, (off_t)(seekpos << SCTRSHFT));
783 if (r <= 0) {
784 perror("Test8: write");
785 err++;
786 return (err);
789 return (err);
792 void
793 gen_data_known(int *buffer, int size, int data)
795 int i;
797 size /= 4;
798 for (i = 0; i < size; i++)
799 buffer[i] = data;
803 do_sdtest9(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
805 int err = 0;
806 ssize_t r;
807 nsc_off_t fba_offset;
808 nsc_size_t i, wrapval;
811 * Test 9 will write a given pattern over and over Test 11 or
812 * Test 12 will read same pattern.
814 /* Large loop value that would cause write overflow will wrap */
816 gen_data_known(buf1, bufsize, pattern[h]);
818 wrapval = filesize / fba_num_bufsize;
820 if (loops == 0)
821 loops = wrapval; /* entire disk */
823 for (i = 0; i < loops; i++) {
824 fba_offset = i % wrapval;
825 r = pwrite(fd, buf1, bufsize,
826 (off_t)(fba_offset * fba_num_bufsize) << SCTRSHFT);
827 if (r <= 0) {
828 perror("Test9: write");
829 err++;
830 return (err);
833 return (err);
837 do_sdtest10(int fd1, int fd2, nsc_size_t loops, nsc_size_t filesize1,
838 nsc_size_t filesize2, int h)
840 nsc_size_t filesize;
841 int err = 0;
842 nsc_size_t i;
843 ssize_t r;
846 * Do sequential copy of disk1 to disk2 for loops number
847 * of bufsize chunks, unless loops == 0, then copy size of
848 * the smaller disk.
849 * Go back and verify that the two disks are identical.
852 filesize = (filesize1 < filesize2) ? filesize1 : filesize2;
853 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
854 loops = filesize / fba_num_bufsize;
856 /* copy disk1 to to disk2 */
857 for (i = 0; i < loops; i++) {
858 r = pread(fd1, buf1, bufsize,
859 (off_t)(i*fba_num_bufsize) << SCTRSHFT);
860 if (r <= 0) {
861 perror("Test10: read");
862 return (1);
864 r = pwrite(fd2, buf1, bufsize,
865 (off_t)(i*fba_num_bufsize) << SCTRSHFT);
866 if (r <= 0) {
867 perror("Test10: write");
868 return (1);
872 /* verify disks are identical */
873 for (i = 0; i < loops; i++) {
874 buf1[0] = '\0'; /* clear buf to make sure something is read */
875 r = pread(fd1, buf1, bufsize,
876 (off_t)(i * fba_num_bufsize) << SCTRSHFT);
877 if (r <= 0) {
878 perror("Test10: read");
879 return (1);
881 buf2[0] = 'x'; /* make sure something is read */
882 r = pread(fd2, buf2, bufsize,
883 (off_t)(i * fba_num_bufsize) << SCTRSHFT);
884 if (r <= 0) {
885 perror("Test10: read");
886 return (1);
888 if (memcmp(buf1, buf2, bufsize)) {
889 (void) printf("Test10: Data corruption,"
890 " fd1:%s, fd2:%s fpos:%" NSC_SZFMT ", len:%d\n",
891 name[2*h], name[2*h+1], i, bufsize);
892 err++;
895 return (err);
899 buffcmp(int *b1, int *b2, int size)
901 int i;
903 for (i = 0; i < size/4; i++) {
904 if (b1[i] != b2[i]) {
905 (void) printf("Word %d does not match b1=0x%x, "
906 "b2=0x%x\n", i, b1[i], b2[i]);
907 return (1);
910 return (0);
915 do_sdtest11(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
917 int err = 0;
918 nsc_size_t i;
919 ssize_t r;
920 int buf3[MAXBUF];
921 int buf4[MAXBUF];
922 int timestamp;
923 time_t clock;
924 struct tm *tm;
928 * Test 9 will write a given pattern over and over Test 11 will read
929 * same pattern and clear with timestamp data (MM:SS).
932 clock = time(NULL);
933 tm = localtime(&clock);
934 (void) ascftime((char *)&timestamp, "%M""%S", tm);
936 gen_data_known(buf1, bufsize, pattern[h]);
937 gen_data_known(buf4, bufsize, timestamp);
938 if ((loops > filesize / fba_num_bufsize) || (!loops))
939 loops = filesize / fba_num_bufsize; /* entire disk */
941 for (i = 0; i < loops; i++) {
942 r = pread(fd, buf3, bufsize,
943 (off_t)(i*fba_num_bufsize) << SCTRSHFT);
944 if (r <= 0) {
945 perror("Test11: read");
946 err++;
947 return (err);
949 if (buffcmp(buf1, buf3, bufsize)) {
950 (void) printf("Data corr, fd:%s, fpos:%" NSC_SZFMT
951 ", len:%d\n", name[h], i, bufsize);
952 err++;
953 return (err);
955 r = pwrite(fd, buf4, bufsize,
956 (off_t)(i*fba_num_bufsize) << SCTRSHFT);
957 if (r <= 0) {
958 perror("Test11: write");
959 err++;
960 return (err);
963 return (err);
967 do_sdtest12(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
969 int err = 0;
970 nsc_size_t i;
971 ssize_t r;
972 int buf3[MAXBUF];
975 * Test 9 will write a given pattern over and over Test 12 will read
976 * same pattern
979 gen_data_known(buf1, bufsize, pattern[h]);
980 if ((loops > filesize / fba_num_bufsize) || (!loops))
981 loops = filesize / fba_num_bufsize; /* entire disk */
983 for (i = 0; i < loops; i++) {
984 r = pread(fd, buf3, bufsize,
985 (off_t)(i*fba_num_bufsize) << SCTRSHFT);
986 if (r <= 0) {
987 perror("Test12: read");
988 err++;
989 return (err);
991 if (buffcmp(buf1, buf3, bufsize)) {
992 (void) printf("Data corr, fd:%s, fpos:%" NSC_SZFMT
993 ", len:%d\n", name[h], i, bufsize);
994 err++;
995 return (err);
998 return (err);
1001 #ifdef lint
1003 sd_diag_lintmain(int argc, char *argv[])
1004 #else
1006 main(int argc, char *argv[])
1007 #endif
1009 int procs;
1010 nsc_size_t filesize, filesize2;
1011 int fd, fd2, r, id, h, i;
1012 nsc_fd_t *sdfd, *sdfd2;
1014 if (argc < 2) {
1015 print_usage();
1016 exit(0);
1018 (void) strcpy(config_file, DISKLIST);
1019 parse_opts(argc, argv);
1021 _nsc_nocheck();
1022 if ((procs = read_parts()) == 0)
1023 exit(0);
1025 id = strtol(argv[optind], 0, 0);
1026 if (id == 10) {
1028 * each process gets 2 disks and copies disk1 to disk2,
1029 * then goes back and verifies that the two disks are
1030 * identical.
1032 if (procs < 2) {
1033 (void) printf("%s requires having at least 2 disks for test "
1034 "#10.\n", config_file);
1035 exit(0);
1038 for (h = 0; h < procs/2; h++) {
1039 r = fork();
1040 if (r == 0) {
1041 srand(getpid());
1044 if (!(sdfd = nsc_open(name[2*h], NSC_CACHE,
1045 O_RDWR | Rflag))) {
1046 (void) fprintf(stderr,
1047 "sd_diag: Error opening %s\n", name[2*h]);
1048 exit(1);
1050 fd = nsc_fileno(sdfd);
1051 if (fd == -1) {
1052 (void) fprintf(stderr,
1053 "sd_diag: Error opening %s\n", name[2*h]);
1054 (void) nsc_close(sdfd);
1055 exit(1);
1057 filesize = set_part_size(name[2*h], sdfd);
1058 if (!(sdfd2 = nsc_open(name[2*h+1], NSC_CACHE,
1059 O_RDWR | Rflag))) {
1060 (void) fprintf(stderr,
1061 "sd_diag: Error opening %s\n", name[2*h+1]);
1062 exit(1);
1064 fd2 = nsc_fileno(sdfd2);
1065 if (fd2 == -1) {
1066 (void) fprintf(stderr,
1067 "sd_diag: Error opening %s\n", name[2*h+1]);
1068 (void) nsc_close(sdfd2);
1069 exit(1);
1071 filesize2 = set_part_size(name[2*h+1], sdfd2);
1072 (void) sleep(2);
1073 r = do_sdtest10(fd, fd2, loops, filesize, filesize2, h);
1075 (void) printf("Partitions %s and %s, Test %d,"
1076 " Completed %d errors\n",
1077 name[2*h], name[2*h+1], id, r);
1078 (void) nsc_close(sdfd);
1079 (void) nsc_close(sdfd2);
1080 exit(0);
1081 } else if (r == -1) {
1082 perror("fork");
1083 break;
1084 } else
1085 continue;
1086 } /* for */
1087 for (i = 0; i < h; i++)
1088 (void) wait(0);
1089 } else {
1091 for (h = 0; h < procs; h++) {
1092 r = fork();
1093 if (r == 0) {
1094 srand(getpid());
1096 id = strtol(argv[optind], 0, 0);
1097 if (!(sdfd = nsc_open(name[h], NSC_CACHE,
1098 O_RDWR | Rflag))) {
1099 (void) fprintf(stderr,
1100 "sd_diag: Error opening %s\n", name[h]);
1101 exit(1);
1103 fd = nsc_fileno(sdfd);
1105 if (fd == -1) {
1106 (void) fprintf(stderr,
1107 "sd_diag: Error opening %s\n", name[h]);
1108 (void) nsc_close(sdfd);
1109 exit(1);
1111 filesize = set_part_size(name[h], sdfd);
1113 (void) sleep(2);
1116 switch (id) {
1117 case 1:
1118 r = do_sdtest1(fd, r_loops, filesize);
1119 break;
1120 case 2:
1121 r = do_sdtest2(fd, r_loops, filesize, h);
1122 break;
1123 case 3:
1124 r = do_sdtest3(fd, r_loops, filesize, h, sdfd);
1125 break;
1126 case 4:
1127 r = do_sdtest4(fd, loops, filesize);
1128 break;
1129 case 5:
1130 r = do_sdtest5(fd, loops, filesize, h);
1131 break;
1132 case 6:
1133 r = do_sdtest6(fd, loops, filesize, h);
1134 break;
1135 case 7:
1136 r = do_sdtest7(fd, r_loops, filesize, h, sdfd);
1137 break;
1138 case 8:
1139 r = do_sdtest8(fd, r_loops, filesize);
1140 break;
1141 case 9:
1142 r = do_sdtest9(fd, loops, filesize, h);
1143 break;
1144 case 11:
1145 r = do_sdtest11(fd, loops, filesize, h);
1146 break;
1147 case 12:
1148 r = do_sdtest12(fd, loops, filesize, h);
1149 break;
1150 default:
1151 break;
1154 (void) printf("Partition %s, Test %d, Completed %d "
1155 "errors\n", name[h], id, r);
1156 (void) nsc_close(sdfd);
1157 exit(r ? 1 : 0);
1158 } else if (r == -1) {
1159 perror("fork");
1160 break;
1161 } else
1162 continue;
1164 for (i = 0; i < h; i++)
1165 (void) wait(0);
1168 return (0);