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 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
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>
40
41 #include <sys/nsctl/sd_cache.h>
42 #include <sys/nsctl/sd_conf.h>
43
44 #include <stdlib.h>
45 #include <thread.h>
46 #include <synch.h>
47
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 */
54
55 /*
56 * >>>>>>>>> USER LEVEL SD CACHE DIAGNOSTICS <<<<<<<<<<
57 *
58 * Write and read data blocks w/multiple processes
59 * Starts one process for each partition specified in
60 * the config file
61 */
62
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];
75
76 int
read_parts()77 read_parts()
78 {
79 FILE *dfile;
80 int partitions = 0;
81 int i;
82
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);
88 }
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;
97 }
98 partitions++;
99 }
100 (void) fclose(dfile);
101 (void) printf("No. of partitions listed in file '%s' = %d\n\n",
102 config_file, partitions);
103 return (partitions);
104 }
105
106 void
print_usage()107 print_usage()
108 {
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");
147 }
148
149 void
parse_opts(int argc,char * argv[])150 parse_opts(int argc, char *argv[])
151 {
152 extern char *optarg;
153 int c;
154
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);
187 }
188 }
189 bufsize &= ~FBA_MASK; /* multiple of 512 bytes for SECTMODE I/O */
190 fba_num_bufsize = FBA_NUM(bufsize);
191
192 /* set #ios for random io tests */
193 if (loops != 0)
194 r_loops = loops;
195
196 }
197
198 nsc_size_t
set_part_size(char * path,nsc_fd_t * sdfd)199 set_part_size(char *path, nsc_fd_t *sdfd)
200 {
201 nsc_size_t filesize;
202 int rc;
203
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);
211 }
212
213 (void) printf("Partition %s, size:%" NSC_SZFMT " blocks\n", path,
214 filesize);
215
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);
224 }
225
226 return (filesize);
227 }
228
229 int
do_sdtest1(int fd,nsc_size_t loops,nsc_size_t filesize)230 do_sdtest1(int fd, nsc_size_t loops, nsc_size_t filesize)
231 {
232 nsc_off_t seekpos;
233 nsc_size_t i;
234 ssize_t r;
235
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);
246 }
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);
256 }
257 }
258 return (0);
259 }
260
261 void
gen_data(int * buffer,int size)262 gen_data(int *buffer, int size)
263 {
264 int i;
265
266 size /= 4;
267 for (i = 0; i < size; i++)
268 buffer[i] = rand() << 16 | rand();
269 }
270
271 int
do_sdtest2(int fd,nsc_size_t loops,nsc_size_t filesize,int h)272 do_sdtest2(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
273 {
274 nsc_off_t seekpos;
275 int err = 0;
276 ssize_t r;
277 nsc_size_t i;
278
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);
291 }
292 r = pread(fd, buf2, bufsize, (off_t)(seekpos << SCTRSHFT));
293 if (r <= 0) {
294 perror("Test2: read");
295 err++;
296 return (err);
297 }
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++;
304 }
305 }
306 return (err);
307 }
308
309 int
do_sdtest3(int fd,nsc_size_t loops,nsc_size_t filesize,int h,nsc_fd_t * sdfd)310 do_sdtest3(int fd, nsc_size_t loops, nsc_size_t filesize, int h, nsc_fd_t *sdfd)
311 {
312 nsc_off_t *seekpos;
313 int err = 0;
314 nsc_size_t i;
315 ssize_t r;
316
317 seekpos = malloc(loops*sizeof (nsc_off_t));
318 if (seekpos == NULL) {
319 perror("Test3: malloc");
320 (void) nsc_close(sdfd);
321 exit(errno);
322 }
323 gen_data(buf1, bufsize);
324
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;
337 }
338 }
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;
346 }
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++;
352 }
353 }
354
355 cleanup:
356 free(seekpos);
357 return (err);
358 }
359
360 int
do_sdtest4(int fd,nsc_size_t loops,nsc_size_t filesize)361 do_sdtest4(int fd, nsc_size_t loops, nsc_size_t filesize)
362 {
363 ssize_t r;
364 nsc_size_t i;
365
366 /*
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.
374 */
375 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
376 loops = filesize / fba_num_bufsize; /* entire disk */
377
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);
383 }
384 }
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);
390 }
391 }
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);
397 }
398 }
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);
404 }
405 }
406 return (0);
407 }
408
409 int
do_sdtest5(int fd,nsc_size_t loops,nsc_size_t filesize,int h)410 do_sdtest5(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
411 {
412 int err = 0;
413 ssize_t r;
414 nsc_size_t i;
415
416 /*
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.
424 */
425 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
426 loops = filesize / fba_num_bufsize; /* entire disk */
427
428 gen_data(buf1, bufsize);
429
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);
436 }
437 }
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);
445 }
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++;
451 }
452 }
453
454 gen_data(buf1, bufsize);
455
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);
462 }
463 }
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);
471 }
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++;
477 }
478 }
479 return (err);
480 }
481
482
483 int
do_sdtest6(int fd,nsc_size_t loops,nsc_size_t filesize,int h)484 do_sdtest6(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
485 {
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;
493
494 /*
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.
499 */
500 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
501 loops = filesize / fba_num_bufsize; /* entire disk */
502
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);
511 }
512 gen_data(buf2, bufsize);
513 top_pos = (endloop - i - 1)*fba_num_bufsize;
514
515 /* Make sure we don't collide in the middle */
516
517 if (abs(top_pos - bottom_pos) < fba_num_bufsize)
518 top_pos = bottom_pos + fba_num_bufsize;
519
520 r = pwrite(fd, buf2, bufsize, (off_t)(top_pos << SCTRSHFT));
521 if (r <= 0) {
522 perror("Test6: write");
523 err++;
524 return (err);
525 }
526 r = pread(fd, buf3, bufsize, (off_t)(bottom_pos << SCTRSHFT));
527 if (r <= 0) {
528 perror("Test6: read");
529 err++;
530 return (err);
531 }
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++;
537 }
538 r = pread(fd, buf4, bufsize, (off_t)(top_pos << SCTRSHFT));
539 if (r <= 0) {
540 perror("Test6: read");
541 return (1);
542 }
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++;
548 }
549 }
550 return (err);
551 }
552
553 int shmid;
554
555 #define MAXREADERS 32
556
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;
566
567 #define WRITEBUF (shm->writebuf)
568 #define WRITEPOS (shm->writepos)
569
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)
575
576 #define LOCKWRITE
577 #define LOCKREAD(i)
578
579 /* Clear RD_DONE and Set WRITEPOS */
580 #define FREEWRITE { \
581 bzero(RD_DONE, sizeof (RD_DONE)); \
582 WRITEPOS = wr_pos; }
583
584 /* Reader i+1 marks himself as finished */
585 #define FREEREAD(i) (RD_DONE[(i)] = 1)
586
587
588 int
do_sdtest7read(int fd,int h,int which)589 do_sdtest7read(int fd, int h, int which)
590 {
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;
605 }
606 }
607
608 /* get location to read from */
609 curr_pos = WRITEPOS;
610
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;
618 }
619
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;
628 }
629
630 FREEREAD(which);
631 }
632
633 (void) printf(
634 "Partition %s, Test 7, reader #%d: %d errors %lld loops\n",
635 name[h], which+1, err, loop_cnt);
636
637 if (err > 0) {
638 (void) mutex_lock(&ERRMUTEX);
639 ERR += err;
640 (void) mutex_unlock(&ERRMUTEX);
641 }
642
643 if (err)
644 return (1);
645 else
646 return (0);
647 }
648
649
650 int
do_sdtest7write(int fd,nsc_size_t filesize,int h)651 do_sdtest7write(int fd, nsc_size_t filesize, int h)
652 {
653 int err = 0;
654 ssize_t r;
655 nsc_off_t wr_pos;
656
657 /* Wait for readers to finish */
658 while (memcmp(RD_DONE, RD_DONE_MASK, readercount*sizeof (int)))
659 ;
660
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);
672 }
673 FREEWRITE;
674
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);
680 }
681
682
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++;
688 }
689
690
691 return (err);
692 }
693
694 void
init_shm()695 init_shm()
696 {
697 int i;
698
699 /* Clear out everything */
700 bzero(shm, sizeof (struct shm_struct));
701
702 (void) mutex_init(&ERRMUTEX, USYNC_PROCESS, NULL);
703
704 /* Set up mask (constant) to test reader doneness */
705 for (i = 0; i < readercount; i++)
706 RD_DONE_MASK[i] = 1;
707
708 /* Mark all readers done - so writer can start */
709 for (i = 0; i < readercount; i++)
710 RD_DONE[i] = 1;
711 }
712
713 int
do_sdtest7(int fd,nsc_size_t loops,nsc_size_t filesize,int h,nsc_fd_t * sdfd)714 do_sdtest7(int fd, nsc_size_t loops, nsc_size_t filesize, int h, nsc_fd_t *sdfd)
715 {
716 int r, i, err;
717 nsc_size_t j;
718
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);
724 }
725
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 */
731 }
732
733 init_shm();
734
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;
744 }
745
746 /* Start Writer */
747 srand(getpid()); err = 0;
748 for (j = 0; j < loops; j++) {
749 err += do_sdtest7write(fd, filesize, h);
750 }
751 QUIT = 1;
752
753 (void) printf("\n\nPartition %s, Test 7, writer: %d errors\n",
754 name[h], err);
755
756 for (i = 0; i < readercount; i++)
757 (void) wait(0);
758
759 /* No lock needed here - everybody's finished */
760 err += ERR;
761
762 (void) mutex_destroy(&ERRMUTEX);
763 (void) shmctl(shmid, IPC_RMID, 0);
764 return (err);
765 }
766
767 int
do_sdtest8(int fd,nsc_size_t loops,nsc_size_t filesize)768 do_sdtest8(int fd, nsc_size_t loops, nsc_size_t filesize)
769 {
770 nsc_off_t seekpos;
771 int err = 0;
772 ssize_t r;
773 nsc_size_t i;
774
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);
787 }
788 }
789 return (err);
790 }
791
792 void
gen_data_known(int * buffer,int size,int data)793 gen_data_known(int *buffer, int size, int data)
794 {
795 int i;
796
797 size /= 4;
798 for (i = 0; i < size; i++)
799 buffer[i] = data;
800 }
801
802 int
do_sdtest9(int fd,nsc_size_t loops,nsc_size_t filesize,int h)803 do_sdtest9(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
804 {
805 int err = 0;
806 ssize_t r;
807 nsc_off_t fba_offset;
808 nsc_size_t i, wrapval;
809
810 /*
811 * Test 9 will write a given pattern over and over Test 11 or
812 * Test 12 will read same pattern.
813 */
814 /* Large loop value that would cause write overflow will wrap */
815
816 gen_data_known(buf1, bufsize, pattern[h]);
817
818 wrapval = filesize / fba_num_bufsize;
819
820 if (loops == 0)
821 loops = wrapval; /* entire disk */
822
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);
831 }
832 }
833 return (err);
834 }
835
836 int
do_sdtest10(int fd1,int fd2,nsc_size_t loops,nsc_size_t filesize1,nsc_size_t filesize2,int h)837 do_sdtest10(int fd1, int fd2, nsc_size_t loops, nsc_size_t filesize1,
838 nsc_size_t filesize2, int h)
839 {
840 nsc_size_t filesize;
841 int err = 0;
842 nsc_size_t i;
843 ssize_t r;
844
845 /*
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.
850 */
851
852 filesize = (filesize1 < filesize2) ? filesize1 : filesize2;
853 if ((loops > (filesize / fba_num_bufsize)) || (!loops))
854 loops = filesize / fba_num_bufsize;
855
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);
863 }
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);
869 }
870 }
871
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);
880 }
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);
887 }
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++;
893 }
894 }
895 return (err);
896 }
897
898 int
buffcmp(int * b1,int * b2,int size)899 buffcmp(int *b1, int *b2, int size)
900 {
901 int i;
902
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);
908 }
909 }
910 return (0);
911
912 }
913
914 int
do_sdtest11(int fd,nsc_size_t loops,nsc_size_t filesize,int h)915 do_sdtest11(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
916 {
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;
925
926
927 /*
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).
930 */
931
932 clock = time(NULL);
933 tm = localtime(&clock);
934 (void) ascftime((char *)×tamp, "%M""%S", tm);
935
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 */
940
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);
948 }
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);
954 }
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);
961 }
962 }
963 return (err);
964 }
965
966 int
do_sdtest12(int fd,nsc_size_t loops,nsc_size_t filesize,int h)967 do_sdtest12(int fd, nsc_size_t loops, nsc_size_t filesize, int h)
968 {
969 int err = 0;
970 nsc_size_t i;
971 ssize_t r;
972 int buf3[MAXBUF];
973
974 /*
975 * Test 9 will write a given pattern over and over Test 12 will read
976 * same pattern
977 */
978
979 gen_data_known(buf1, bufsize, pattern[h]);
980 if ((loops > filesize / fba_num_bufsize) || (!loops))
981 loops = filesize / fba_num_bufsize; /* entire disk */
982
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);
990 }
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);
996 }
997 }
998 return (err);
999 }
1000
1001 #ifdef lint
1002 int
sd_diag_lintmain(int argc,char * argv[])1003 sd_diag_lintmain(int argc, char *argv[])
1004 #else
1005 int
1006 main(int argc, char *argv[])
1007 #endif
1008 {
1009 int procs;
1010 nsc_size_t filesize, filesize2;
1011 int fd, fd2, r, id, h, i;
1012 nsc_fd_t *sdfd, *sdfd2;
1013
1014 if (argc < 2) {
1015 print_usage();
1016 exit(0);
1017 }
1018 (void) strcpy(config_file, DISKLIST);
1019 parse_opts(argc, argv);
1020
1021 _nsc_nocheck();
1022 if ((procs = read_parts()) == 0)
1023 exit(0);
1024
1025 id = strtol(argv[optind], 0, 0);
1026 if (id == 10) {
1027 /*
1028 * each process gets 2 disks and copies disk1 to disk2,
1029 * then goes back and verifies that the two disks are
1030 * identical.
1031 */
1032 if (procs < 2) {
1033 (void) printf("%s requires having at least 2 disks for test "
1034 "#10.\n", config_file);
1035 exit(0);
1036 }
1037
1038 for (h = 0; h < procs/2; h++) {
1039 r = fork();
1040 if (r == 0) {
1041 srand(getpid());
1042
1043
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);
1049 }
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);
1056 }
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);
1063 }
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);
1070 }
1071 filesize2 = set_part_size(name[2*h+1], sdfd2);
1072 (void) sleep(2);
1073 r = do_sdtest10(fd, fd2, loops, filesize, filesize2, h);
1074
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 {
1090
1091 for (h = 0; h < procs; h++) {
1092 r = fork();
1093 if (r == 0) {
1094 srand(getpid());
1095
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);
1102 }
1103 fd = nsc_fileno(sdfd);
1104
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);
1110 }
1111 filesize = set_part_size(name[h], sdfd);
1112
1113 (void) sleep(2);
1114
1115
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;
1152 }
1153
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;
1163 }
1164 for (i = 0; i < h; i++)
1165 (void) wait(0);
1166 }
1167
1168 return (0);
1169 }
1170