sd_diag.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* #include <version.h> SKK */
#include <errno.h>
#include <sys/inttypes.h>
#include <stdio.h>
#include <strings.h>
#include <fcntl.h>
#include <unistd.h>
#include <nsctl.h>
#include <stdlib.h>
#include <thread.h>
#include <synch.h>
/*
* >>>>>>>>> USER LEVEL SD CACHE DIAGNOSTICS <<<<<<<<<<
*
* Starts one process for each partition specified in
* the config file
*/
int fba_num_bufsize;
int fsize = -1;
int readercount = 3;
char config_file[32];
int
{
int partitions = 0;
int i;
perror("fopen");
}
for (i = 0; i < MAXPARTS; i++) {
EOF) {
break;
} else
i--;
continue;
}
partitions++;
}
(void) printf("No. of partitions listed in file '%s' = %d\n\n",
return (partitions);
}
void
{
(void) printf("Usage:\n");
(void) printf(
"sd_diag [-R] [-b <bufsize>] [-d <datasize>] [-l <loops>] [-r <readers>]\n");
(void) printf(
" [-f <disk_config_file>] <test#>\n");
(void) printf(" all reads after all writes\n");
(void) printf(" all reads after all writes\n");
(void) printf(
(void) printf(" 7 = multiple readers/1 random writer\n");
(void) printf(" 8 = random writes\n");
(void) printf(" 9 = sequential write of known data\n");
(void) printf(" then clear data with timestamp\n");
(void) printf(" no clear data\n");
(void) printf("\n");
(void) printf(" <bufsize> in bytes (minimum is 512 bytes)\n");
(void) printf(" <datasize> in Mbytes per disk\n");
(void) printf(" loops = 0 tests entire datasize disk");
(void) printf(" for sequential tests.\n");
"tests\n", RAND_LOOPS);
(void) printf(" <readers> is count of readers for test #7 (default "
"is 3).\n");
(void) printf(" [ defaults: bufsize = %d bytes, loops = %d,",
(void) printf(" datasize = disksize ]\n");
(void) printf("\n");
(void) printf(" -R : do nsc_reserve(), nsc_release(0 around each "
"I/O\n");
}
void
{
extern char *optarg;
int c;
switch (c) {
case 'f':
/* printf("\n%s", optarg); */
break;
case 'b':
/* bufsize between 1*512 and 512*512 */
break;
case 'd':
/* convert datasize from Mb's to fba */
break;
case 'l':
break;
case 'r':
/* count of readers for test 7 */
break;
case 'R':
/* do reserve, release on a per io basis */
Rflag = 0;
break;
case '?':
print_usage();
exit(0);
}
}
/* set #ios for random io tests */
if (loops != 0)
}
{
int rc;
"set_part_size: cannot access partition size");
exit(1);
}
filesize);
if (filesize < fba_num_bufsize) {
filesize);
exit(0);
}
return (filesize);
}
int
{
nsc_size_t i;
ssize_t r;
for (i = 0; i < loops; i++) {
seekpos = (
#ifdef NSC_MULTI_TERABYTE
#endif
if (r <= 0) {
perror("Test1: write");
return (1);
}
seekpos = (
#ifdef NSC_MULTI_TERABYTE
#endif
if (r <= 0) {
perror("Test1: read");
return (1);
}
}
return (0);
}
void
{
int i;
size /= 4;
for (i = 0; i < size; i++)
}
int
{
int err = 0;
ssize_t r;
nsc_size_t i;
for (i = 0; i < loops; i++) {
seekpos = (
#ifdef NSC_MULTI_TERABYTE
#endif
if (r <= 0) {
perror("Test2: write");
err++;
return (err);
}
if (r <= 0) {
perror("Test2: read");
err++;
return (err);
}
(void) printf("Test2: Data corruption,"
bufsize);
err++;
}
}
return (err);
}
int
{
int err = 0;
nsc_size_t i;
ssize_t r;
perror("Test3: malloc");
}
for (i = 0; i < loops; i++) {
seekpos[i] = (
#ifdef NSC_MULTI_TERABYTE
#endif
if (r <= 0) {
perror("Test3: write");
err++;
goto cleanup;
}
}
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test3: read");
err++;
goto cleanup;
}
", len:%d\n", name[h],
err++;
}
}
return (err);
}
int
{
ssize_t r;
nsc_size_t i;
/*
* of bufsize chunks, unless loops == 0, then do
* entire disk.
* 1. sequential reads from the top down,
* 2. sequential writes from the top down,
* 3. sequential reads from the bottom up,
* 4. sequential writes from the bottom up.
*/
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test4: read");
return (1);
}
}
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test4: write");
return (1);
}
}
if (r <= 0) {
perror("Test4: read");
return (1);
}
}
if (r <= 0) {
perror("Test4: write");
return (1);
}
}
return (0);
}
int
{
int err = 0;
ssize_t r;
nsc_size_t i;
/*
* Do sequential writes with verify reads for loops number
* of bufsize chunks, unless loops == 0, then do
* entire disk.
* 1. sequential writes from the top down,
* 2. sequential reads from the top down with verify,
* 3. sequential writes from the bottom up,
* 4. sequential reads from the bottom up with verify.
*/
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test5: write");
err++;
return (err);
}
}
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test5: read");
err++;
return (err);
}
(void) printf("Test5: Data corruption,"
err++;
}
}
if (r <= 0) {
perror("Test5: write");
err++;
return (err);
}
}
if (r <= 0) {
perror("Test5: read");
err++;
return (err);
}
(void) printf("Test5: Data corruption,"
err++;
}
}
return (err);
}
int
{
int err = 0;
nsc_size_t i;
ssize_t r;
/*
* Do alternating top down and bottom up sequential writes
* (working towards middle) and verify with reads
* for loops number of bufsize chunks, unless loops == 0, then do
* entire disk.
*/
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test6: write");
err++;
return (err);
}
/* Make sure we don't collide in the middle */
if (r <= 0) {
perror("Test6: write");
err++;
return (err);
}
if (r <= 0) {
perror("Test6: read");
err++;
return (err);
}
(void) printf("Data corruption(1), fd:%s, fpos:%"
err++;
}
if (r <= 0) {
perror("Test6: read");
return (1);
}
(void) printf("Test6: Data corruption(2),"
err++;
}
}
return (err);
}
int shmid;
#define MAXREADERS 32
struct shm_struct {
int quit;
int err;
int rd_done[MAXREADERS];
int rd_done_mask[MAXREADERS];
} *shm;
#define LOCKWRITE
#define LOCKREAD(i)
/* Clear RD_DONE and Set WRITEPOS */
#define FREEWRITE { \
/* Reader i+1 marks himself as finished */
int
{
int err;
for (;;) {
/* Already read this? */
if (!QUIT) {
continue;
} else {
/* Time to go! */
/* printf("Quitting [%d]\n", which+1); */
break;
}
}
/* get location to read from */
loop_cnt += 1;
if (r_rd <= 0) {
perror("Test7: read");
err += 1;
continue;
}
(void) printf("\nTest7: Data corruption, reader #%d, "
"fd:%s, \
err += 1;
continue;
}
}
(void) printf(
"Partition %s, Test 7, reader #%d: %d errors %lld loops\n",
if (err > 0) {
(void) mutex_lock(&ERRMUTEX);
(void) mutex_unlock(&ERRMUTEX);
}
if (err)
return (1);
else
return (0);
}
int
{
int err = 0;
ssize_t r;
/* Wait for readers to finish */
;
wr_pos = (
#ifdef NSC_MULTI_TERABYTE
#endif
if (r <= 0) {
perror("Test7: write");
return (1);
}
/* verify write */
if (r <= 0) {
perror("Test7: writer: read");
return (1);
}
(void) printf("\nTest7: Data corruption in writer,"
err++;
}
return (err);
}
void
init_shm()
{
int i;
/* Clear out everything */
/* Set up mask (constant) to test reader doneness */
for (i = 0; i < readercount; i++)
RD_DONE_MASK[i] = 1;
/* Mark all readers done - so writer can start */
for (i = 0; i < readercount; i++)
RD_DONE[i] = 1;
}
int
{
int r, i, err;
nsc_size_t j;
IPC_CREAT | 0666)) < 0) {
perror("shmget error: ");
exit(1);
}
perror("shmat error: ");
}
init_shm();
/* Start Readers */
for (i = 0; i < readercount; i++) {
r = fork();
if (r == 0) { /* child */
(void) do_sdtest7read(fd, h, i);
exit(0);
} else
continue;
}
/* Start Writer */
for (j = 0; j < loops; j++) {
}
QUIT = 1;
(void) printf("\n\nPartition %s, Test 7, writer: %d errors\n",
for (i = 0; i < readercount; i++)
wait(0);
/* No lock needed here - everybody's finished */
(void) mutex_destroy(&ERRMUTEX);
return (err);
}
int
{
int err = 0;
ssize_t r;
nsc_size_t i;
for (i = 0; i < loops; i++) {
seekpos = (
#ifdef NSC_MULTI_TERABYTE
#endif
if (r <= 0) {
perror("Test8: write");
err++;
return (err);
}
}
return (err);
}
void
{
int i;
size /= 4;
for (i = 0; i < size; i++)
}
int
{
int err = 0;
ssize_t r;
nsc_size_t i, wrapval;
/*
* Test 9 will write a given pattern over and over Test 11 or
* Test 12 will read same pattern.
*/
/* Large loop value that would cause write overflow will wrap */
if (loops == 0)
for (i = 0; i < loops; i++) {
fba_offset = i % wrapval;
if (r <= 0) {
perror("Test9: write");
err++;
return (err);
}
}
return (err);
}
int
nsc_size_t filesize2, int h)
{
int err = 0;
nsc_size_t i;
ssize_t r;
/*
* Do sequential copy of disk1 to disk2 for loops number
* of bufsize chunks, unless loops == 0, then copy size of
* the smaller disk.
* Go back and verify that the two disks are identical.
*/
/* copy disk1 to to disk2 */
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test10: read");
return (1);
}
if (r <= 0) {
perror("Test10: write");
return (1);
}
}
/* verify disks are identical */
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test10: read");
return (1);
}
if (r <= 0) {
perror("Test10: read");
return (1);
}
(void) printf("Test10: Data corruption,"
err++;
}
}
return (err);
}
int
{
int i;
for (i = 0; i < size/4; i++) {
(void) printf("Word %d does not match b1=0x%x, "
return (1);
}
}
return (0);
}
int
{
int err = 0;
nsc_size_t i;
ssize_t r;
int timestamp;
/*
* Test 9 will write a given pattern over and over Test 11 will read
* same pattern and clear with timestamp data (MM:SS).
*/
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test11: read");
err++;
return (err);
}
err++;
return (err);
}
if (r <= 0) {
perror("Test11: write");
err++;
return (err);
}
}
return (err);
}
int
{
int err = 0;
nsc_size_t i;
ssize_t r;
/*
* Test 9 will write a given pattern over and over Test 12 will read
* same pattern
*/
for (i = 0; i < loops; i++) {
if (r <= 0) {
perror("Test12: read");
err++;
return (err);
}
err++;
return (err);
}
}
return (err);
}
#ifdef lint
int
#else
int
#endif
{
int procs;
if (argc < 2) {
print_usage();
exit(0);
}
_nsc_nocheck();
if ((procs = read_parts()) == 0)
exit(0);
if (id == 10) {
/*
* each process gets 2 disks and copies disk1 to disk2,
* then goes back and verifies that the two disks are
* identical.
*/
if (procs < 2) {
(void) printf("%s requires having at least 2 disks for test "
"#10.\n", config_file);
exit(0);
}
for (h = 0; h < procs/2; h++) {
r = fork();
if (r == 0) {
exit(1);
}
if (fd == -1) {
exit(1);
}
exit(1);
}
if (fd2 == -1) {
exit(1);
}
(void) sleep(2);
(void) printf("Partitions %s and %s, Test %d,"
" Completed %d errors\n",
exit(0);
} else if (r == -1) {
perror("fork");
break;
} else
continue;
} /* for */
for (i = 0; i < h; i++)
wait(0);
} else {
for (h = 0; h < procs; h++) {
r = fork();
if (r == 0) {
"sd_diag: Error opening %s\n", name[h]);
exit(1);
}
if (fd == -1) {
"sd_diag: Error opening %s\n", name[h]);
exit(1);
}
(void) sleep(2);
switch (id) {
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 11:
break;
case 12:
break;
default:
break;
}
(void) printf("Partition %s, Test %d, Completed %d "
exit(r ? 1 : 0);
} else if (r == -1) {
perror("fork");
break;
} else
continue;
}
for (i = 0; i < h; i++)
wait(0);
}
return (0);
}