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>