Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Aug 1999 11:19:28 -0700 (PDT)
From:      Matthew Jacob <mjacob@feral.com>
To:        Brian McGovern <bmcgover@cisco.com>
Cc:        hackers@freebsd.org
Subject:   Re: Looking for good QA tests... Part 2..
Message-ID:  <Pine.BSF.4.05.9908271113370.2537-100000@semuta.feral.com>
In-Reply-To: <Pine.BSF.4.05.9908271110230.2537-100000@semuta.feral.com>

next in thread | previous in thread | raw e-mail | index | archive | help

Raw pattern checker...less well polished...runs on a lot of platforms...
Avoids trashing disk labels... 

Usage is a little less than obvious...

1. patchk RAWDISK TransferSize c

Create/Validate/Test patterns.. creates patterns in TransferSize
chunks..validates that they were correctly written, then randoml reads or
updates same patterns.

2. patchk RAWDISK TransferSize u

Skips the create step....


3. patchk RAWDISK TransferSize v

Skips the create and refresh test- just validates the pattern.


Gary Palmer managed to find some pretty serious problems in a disk array
by running multiple 'u' instantiations on the same partitition after an
initial 'c' test.


/*
 * Copyright (c) 1999 Matthew Jacob
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification, immediately at the beginning of the file.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Id: patchk.c,v 1.3 1999/08/27 18:14:34 mjacob Exp $
 */
#ifdef convex
#include <sys/types.h>
extern int optind;
extern int getopt(int, char **, const char *);
#define	SEEK_T	off64_t
#define	SEEK	lseek64
#define	FSTAT	fstat64
#define	STAT_T	stat64_t
#else
#define	SEEK_T	off_t
#define	SEEK	lseek
#define	FSTAT	fstat
#define	STAT_T	struct stat
#endif
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#ifdef sun
#define	rand	lrand48
#define	srand	srand48
#ifdef	__SVR4
#include <sys/dkio.h>
#else
#include <sun/dkio.h>
extern int gettimeofday(struct timeval *, struct timezone *);
extern void bzero(char *, int);
extern int strtol(const char *, char **, int);
#endif
extern int optind;
#endif
#ifdef __linux__
#include <sys/ioctl.h>
#include <linux/fs.h>
#endif
#ifdef	convex
#include <sys/ioctl.h>
#include <interfaces/io_if/scsi/scsi.h>
#endif
#if	defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/disklabel.h>
#include <sys/dkio.h>
#endif
#ifdef	__FreeBSD__
#include <sys/disklabel.h>
#endif
#ifdef __ultrix
extern int optind;
#endif


#ifndef	O_LARGEFILE
#define	O_LARGEFILE	0
#endif


static int szarg(char *);


int
main(int a, char **v)
{
    SEEK_T seekbase, seeklim, *buffer, wloc;
    int blksize;
    long long sb, sl;
    STAT_T st;
    int fd, i, error, create, nowrite;

    seekbase = (SEEK_T) 0;
    nowrite = 0;
    srand((int)(time((time_t *) 0)/getpid()));

    if (a != 4) {
usage:
	fprintf(stderr,
	    "Usage: %s raw-disk xfersize {c[reate]|u[se]|v[alidate]}\n", *v);
	return (1);
    }
    blksize = szarg(v[2]);
    buffer = (SEEK_T *) calloc((size_t) blksize, sizeof (SEEK_T));
    if (buffer == NULL) {
	perror("malloc");
	return (1);
    }

    if (*v[3] == 'c') {
	create = 1;
    } else if (*v[3] == 'u') {
	create = 0;
    } else if (*v[3] == 'v') {
	create = 0;
	nowrite = 1;
    } else {
	goto usage;
    }

    fd = open(v[1], nowrite? O_RDONLY : O_RDWR, 0666);
    if (fd < 0) {
	perror(v[2]);
	exit(1);
    }
    if (FSTAT(fd, &st) < 0) {
	perror("fstat");
	exit(1);
    }
    if (S_ISCHR(st.st_mode)) {
#if	defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
	int part;
	struct disklabel x;

	if (ioctl(fd, DIOCGDINFO, (caddr_t) &x) < 0) {
	    perror("DIOCGDINFO");
	    exit(1);
	}
	seekbase = 8192;
	part = v[1][strlen(v[1]) - 1] - 'a';
	seeklim = ((SEEK_T) x.d_partitions[part].p_size) * (SEEK_T) DEV_BSIZE;
#elif	defined(sun)
	struct dk_allmap x;
	int part;

	if (blksize < DEV_BSIZE) {
	    fprintf(stderr, "%s: block size must be at least %d bytes on "
		"raw device\n", *v, DEV_BSIZE);
	    exit(1);
	}
#if	defined(__svr4__)
	part = v[1][strlen(v[1]) - 1] - '0';
#else
	part = v[1][strlen(v[1]) - 1] - 'a';
#endif
	if (ioctl(fd,  DKIOCGAPART, (caddr_t) &x) < 0) {
	    perror("DKIOCGAPART");
	    exit(1);
	}
	seekbase = 8192;
	seeklim = ((SEEK_T) x.dka_map[part].dkl_nblk) * (SEEK_T) DEV_BSIZE;
#elif	defined(convex)
	struct topology top;
	seeklim = 0;
	if (ioctl(fd, SIOC_READ_TOPOLOGY, (caddr_t)&top) >= 0) {
		seeklim = (SEEK_T) top.partition[st.st_rdev & 0xf].size *
		    (SEEK_T) DEV_BSIZE;
	}
#else
	seeklim = (SEEK_T) 1;
#endif
    } else {
#ifdef	linux
	if (ioctl(fd, BLKGETSIZE, (caddr_t) &seeklim) < 0) {
	    perror("BLKGETSIZE");
	    exit(1);
	}
	seeklim <<= 9;  
#else
	fprintf(stderr, "%s: is not a raw device\n", v[1]);
	return (1);
#endif
    }

    if (seekbase < blksize)
	seekbase = blksize;


    /*
     * Truncate to lower block boundary.
     */
    seeklim &= ~(blksize-1);

    /*
     * An back off one.
     */
    seeklim -= blksize;
    if (seeklim < (SEEK_T) 0) {
	printf("%s too big for lseek(2) call\n", v[1]);
	exit(1);
    }
    if (seeklim < (seekbase+blksize)) {
	fprintf(stderr, "%s: botch, seeklim (%ld) < seekbase + blksize (%ld)\n",
	    *v, seeklim, seekbase + blksize);
	exit(1);
    }

    sb = (long long) seekbase;
    sl = (long long) seeklim;
    fprintf(stdout, "%s: Seek base %lx%08lx Seek lim %lx%08lx blocksize %d\n",
	v[1], (long) (sb >> 32LL), (long) (sb & 0xFFFFFFFF),
	(long) (sl >> 32LL), (long) (sl & 0xFFFFFFFF), blksize);
    wloc = SEEK(fd, (SEEK_T) seekbase, 0);
    if (wloc < (SEEK_T) 0) {
	perror("seek");
    	exit (1);
    }
    if (create) {
	fprintf(stdout, "Creating Patterns...");
	fflush(stdout);
	for (wloc = seekbase; wloc < seeklim; wloc += blksize) {
	    sb = (long long) wloc;
	    for (i = 0; i < (blksize/sizeof (SEEK_T)); i++) {
		buffer[i] = wloc;
	    }
	    if ((i = write(fd, (char *)buffer, (int) blksize)) != blksize) {
		if (errno)
		    perror("write");
		fprintf(stderr, "write returned %d at offset 0x%lx0x%08lx\n", i,
		    (long) (sb >> 32LL), (long) (sb & 0xFFFFFFFF));
		exit (1);
	    }
	}
	wloc = SEEK(fd, (SEEK_T) seekbase, 0);
	if (wloc < (SEEK_T) 0) {
	    perror("seek");
	    exit (1);
	}
    }
    fprintf(stdout, "Checking Patterns...");
    fflush(stdout);
    for (wloc = seekbase; wloc < seeklim; wloc += blksize) {
	sb = (long long) wloc;
	if ((i = read(fd, (char *)buffer, blksize)) != blksize) {
	    if (errno)
	        perror("read");
	    fprintf(stderr, "read returned %d at offset 0x%lx%08lx\n", i,
		(long) (sb >> 32LL), (long) (sb & 0xFFFFFFFF));
	    exit (1);
	}
	for (error = i = 0; i < (blksize/sizeof (SEEK_T)); i++) {
	    if (buffer[i] != wloc) {
		sb = wloc;
		sl = (long long) buffer[i];
		error++;
		fprintf(stderr, "compare error at block loc 0x%lx%08lx offset "
		    "%d got %lx%08lx\n", (long) (sb >> 32LL),
		    (long) (sb & 0xFFFFFFFF), i, (long) (sl >> 32LL),
		    (long) (sl & 0xFFFFFFFF));
	    }
	}
	if (error)
	    exit (1);
    }
    fprintf(stdout, "Randomly Checking Patterns\n");
    while (1) {
	SEEK_T sloc;
	wloc = rand();
	wloc &= ~(((SEEK_T)blksize) - 1);
	if (wloc < seekbase)
	    continue;
	if (wloc >= (seeklim-(SEEK_T) blksize))
	    continue;
	sloc = SEEK(fd, wloc, 0);
	if (sloc < (SEEK_T) 0) {
	    perror("seek");
	    exit (1);
	}
	if (sloc != wloc) {
	    if (errno)
	        perror("seek2");
	    fprintf(stderr, "wanted to seek to %lx and got to %lx instead\n",
		wloc, sloc);
	    continue;
	}
	sb = (long long) wloc;
	if (!nowrite  && (rand() & 1)) {
	    for (i = 0; i < (blksize/sizeof (SEEK_T)); i++) {
		buffer[i] = wloc;
	    }
	    if ((i = write(fd, (char *)buffer, blksize)) != blksize) {
		fprintf(stderr, "\n");
		if (errno)
		    perror("write");
		fprintf(stderr, "write returned %d at offset 0x%lx%08lx\n", i,
		    (long) (sb >> 32LL), (long) (sb & 0xFFFFFFFF));
printf("wloc %lx sloc %lx\n", wloc, sloc);
		exit (1);
	    }
	} else {
	    if ((i = read(fd, (char *)buffer, blksize)) != blksize) {
		fprintf(stderr, "\n");
		if (errno)
		    perror("read");
		fprintf(stderr, "read returned %d at offset 0x%lx%08lx\n", i,
		    (long) (sb >> 32LL), (long) (sb & 0xFFFFFFFF));
printf("wloc %lx sloc %lx\n", wloc, sloc);
		exit (1);
	    }
	    for (error = i = 0; i < (blksize/sizeof (SEEK_T)); i++) {
		if (buffer[i] != wloc) {
		    sb = wloc;
		    sl = (long long) buffer[i];
		    if (error++ == 0)
			fprintf(stderr, "\n");
		    fprintf(stderr, "compare error at buffer offset %d should "
			"be 0x%lx%08lx got 0x%lx%08lx\n", i,
			(long) (sb >> 32LL), (long) (sb & 0xFFFFFFFF),
			(long) (sl >> 32LL), (long) (sl & 0xFFFFFFFF));
		}
	    }
	    if (error)
		exit (1);
	}
    }
}

static int
szarg(char *n)
{
    register int shift = 0;
    register char *q = n;

    while (*q != (char) 0)
	q++;
    q--;

    if (*q == 'b' || *q == 'B')
	q--;

    if (*q == 'k' || *q == 'K') {
	shift = 10;
	*q = 0;
    } else if (*q == 'm' || *q == 'M') {
	shift = 20;
	*q = 0;
    } else if (*q == 'g' || *q == 'G') {
	shift = 30;
	*q = 0;
    }
    return ((SEEK_T) strtol((const char *)n, (char **) NULL, 0) << shift);
}
/*
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-indent-level: 4
 * c-brace-imaginary-offset: 0
 * c-brace-offset: -4
 * c-argdecl-indent: 4
 * c-label-offset: -4
 * c-continued-statement-offset: 4
 * c-continued-brace-offset: 0
 * End:
 */




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9908271113370.2537-100000>