Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Apr 1999 21:25:12 -0700 (PWT)
From:      Matthew Jacob <mjacob@feral.com>
To:        Greg Lehey <grog@lemis.com>
Cc:        Brad Knowles <brad@shub-internet.org>, FreeBSD current users <FreeBSD-current@FreeBSD.ORG>
Subject:   Re: Porting Greg Lehey's rawio.c from FreeBSD to Linux...
Message-ID:  <Pine.LNX.4.04.9904302114210.9878-100000@feral.com>
In-Reply-To: <19990501134333.G80561@freebie.lemis.com>

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

> On Friday, 30 April 1999 at 20:51:06 -0700, Matt Jacob wrote:
> >>
> >> I don't really understand why you ask a FreeBSD group about it; it's a
> >> Linux issue.  FWIW, about the only area where you're liable to run
> >> into difficulties is in the disk label handling round line 300, which
> >> is pretty peripheral to the function: it's just there as one way of
> >> finding out the size of the partition.  You'll need in-depth Linux
> >> information to even find out if Linux has an equivalent function.
> >
> > Open the device, and
> >
> >         if (ioctl(fd, BLKGETSIZE, (caddr_t) &seeklim) < 0) {
> >
> > see <linux/fs.h>
> 
> Thanks for the info.  Looking at this, it looks as if this ioctl is
> for a block device.  rawio uses character devices.  Does that make a
> difference?
> 

(

everyone... wait for it .... wait for it.... wait for it... NOW!


AAAAAAAAAAAAAAARRRRRRRRRRRRRRRRRGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!

)


There are no raw devices in Linux. Linus is totally against them as
stupid. Linus has some good points about this, but it's still an, um,
interesting stance.

Let me qualify that slightly- Steve Tweedie has some patches to provide
this finally in the post 2.2 time frame. I helped folks hack an mmap of
kernel memory to provide 'raw, direct I/O' functionality years ago (they
needed to get video images off of disk, into memory, topped and tailed
with UDP info and sent out to the appropriate clients- when they went from
one Wide/Fast controller (it was that long ago) to two they only saw a 5%
increase in speed (can you spell 'copyin/copyout' boyz && gurlz? Oh,
okay,. it's get_fs_long and put_fs_long in linux...)...

I just sent this to Brad, but here's a little pattern checker I use for *BSD,
solaris && linux, oh yeah, and ConvexOS- much like rawio (which looks a
little more clean- I also have a disk exerciser-....Yes, it's GPLd, but
basically it's for whomever... I really ought to add the DVH header for
IRIX/MIPS....

For raw pattern testing Linux has a special challenge since you right
directly into the buffer cache. There *is* a BLKFLSBUF ioctl that can try
and force a flush but this probably ought to be written to use O_FSYNC- I
think that the ll_rw code might use it or an fsync could be done...

-matt



#ident	"$Id: $ "
/*
 *
 * Copyright (c) 1998, Matthew Jacob
 *
 *	This software is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Library General Public
 *	License as published by the Free Software Foundation; version 2.
 *
 *	This software is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Library General Public License for more details.
 *
 *	You should have received a copy of the GNU Library General Public
 *	License along with this software; if not, write to the Free
 *	Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *	The author may be reached via electronic communications at
 *
 *		mjacob@feral.com
 *
 *	or, via United States Postal Address
 *
 *		Matthew Jacob
 *		1831 Castro Street
 *		San Francisco, CA, 94131
 *
 ***************************************************************************
 *
 * $Log: patchk.c,v $
 * Revision 1.2  1999/02/02 17:23:07  mjacob
 * checkpoint
 *
 */
#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-current" in the body of the message




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