Subject: Re: increasing dump's speed
To: Manuel Bouyer <bouyer@antioche.lip6.fr>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-userlevel
Date: 03/19/1999 12:13:24
--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Ok, following the advice from Ignatios Souvatzis, I added a command line
option to change the block size. I also changed the functions and
variables names to respect the coding style.
New diffs appened below, I expect to commit this Monday.
--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel.Bouyer@lip6.fr
--
--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff
Index: Makefile
===================================================================
RCS file: /cvsroot/src/sbin/dump/Makefile,v
retrieving revision 1.21
diff -u -r1.21 Makefile
--- Makefile 1999/03/09 17:25:52 1.21
+++ Makefile 1999/03/19 11:12:30
@@ -16,8 +16,8 @@
PROG= dump
LINKS= ${BINDIR}/dump ${BINDIR}/rdump
CPPFLAGS+=-DRDUMP
-# CPPFLAGS+= -DDEBUG -DTDEBUG -DFDEBUG -DWRITEDEBUG
-SRCS= itime.c main.c optr.c dumprmt.c tape.c traverse.c unctime.c \
+# CPPFLAGS+= -DDEBUG -DTDEBUG -DFDEBUG -DWRITEDEBUG -DSTATS -DDIAGNOSTICS
+SRCS= itime.c main.c optr.c dumprmt.c rcache.c tape.c traverse.c unctime.c \
ffs_bswap.c
BINGRP= tty
BINMODE=2555
Index: dump.8
===================================================================
RCS file: /cvsroot/src/sbin/dump/dump.8,v
retrieving revision 1.31
diff -u -r1.31 dump.8
--- dump.8 1999/03/09 17:25:52 1.31
+++ dump.8 1999/03/19 11:12:33
@@ -49,7 +49,9 @@
.Op Fl d Ar density
.Op Fl f Ar file
.Op Fl h Ar level
+.Op Fl k Ar read blocksize
.Op Fl L Ar label
+.Op Fl r Ar cachesize
.Op Fl s Ar feet
.Op Fl T Ar date
.Ar files-to-dump
@@ -170,6 +172,8 @@
The default honor level is 1,
so that incremental backups omit such files
but full backups retain them.
+.It Fl k Ar read blocksize
+The size in kilobyte of a the read buffers. Default is 32k.
.It Fl L Ar label
The user-supplied text string
.Ar label
@@ -190,6 +194,14 @@
.Qq operator
by means similar to a
.Xr wall 1 .
+.It Fl r Ar cachesize
+Use that many buffers for read cache operations.
+A value of zero disables the read cache altogether, higher values
+improve read performance by reading larger data blocks from the
+disk and maintaining them in an LRU cache. See the
+.Fl k
+option for the size of the buffers. Maximum is 512, the size of the cache is
+limited to 15% of the avail RAM by default.
.It Fl s Ar feet
Attempt to calculate the amount of tape needed
at a particular density.
Index: dump.h
===================================================================
RCS file: /cvsroot/src/sbin/dump/dump.h,v
retrieving revision 1.15
diff -u -r1.15 dump.h
--- dump.h 1999/01/15 13:32:06 1.15
+++ dump.h 1999/03/19 11:12:35
@@ -146,10 +146,15 @@
/* file dumping routines */
void blksout __P((daddr_t *blkp, int frags, ino_t ino));
-void bread __P((daddr_t blkno, char *buf, int size));
void dumpino __P((struct dinode *dp, ino_t ino));
void dumpmap __P((char *map, int type, ino_t ino));
void writeheader __P((ino_t ino));
+
+/* data block caching */
+void bread __P((daddr_t blkno, char *buf, int size));
+void rawread __P((daddr_t, char *, int));
+void initcache __P((int, int));
+void printcachestats __P((void));
/* tape writing routines */
int alloctape __P((void));
Index: main.c
===================================================================
RCS file: /cvsroot/src/sbin/dump/main.c,v
retrieving revision 1.21
diff -u -r1.21 main.c
--- main.c 1999/01/03 02:17:46 1.21
+++ main.c 1999/03/19 11:12:35
@@ -93,6 +93,8 @@
long dev_bsize = 1; /* recalculated below */
long blocksperfile = 0; /* output blocks per file */
char *host = NULL; /* remote host (if any) */
+int readcache = -1; /* read cache size (in readblksize blks) */
+int readblksize = 32 * 1024; /* read block size */
int main __P((int, char *[]));
static long numarg __P((char *, long, long));
@@ -136,7 +138,7 @@
obsolete(&argc, &argv);
while ((ch = getopt(argc, argv,
- "0123456789B:b:cd:f:h:L:ns:ST:uWw")) != -1)
+ "0123456789B:b:cd:f:h:k:L:nr:s:ST:uWw")) != -1)
switch (ch) {
/* dump level */
case '0': case '1': case '2': case '3': case '4':
@@ -171,6 +173,10 @@
honorlevel = numarg("honor level", 0L, 10L);
break;
+ case 'k':
+ readblksize = numarg("read block size", 0, 64) * 1024;
+ break;
+
case 'L':
/*
* Note that although there are LBLSIZE characters,
@@ -191,6 +197,10 @@
notify = 1;
break;
+ case 'r': /* read cache size */
+ readcache = numarg("read cache size", 0, 512);
+ break;
+
case 's': /* tape size, feet */
tsize = numarg("tape size", 1L, 0L) * 12 * 10;
break;
@@ -379,7 +389,7 @@
}
sync();
sblock = (struct fs *)sblock_buf;
- bread(SBOFF, (char *) sblock, SBSIZE);
+ rawread(SBOFF, (char *) sblock, SBSIZE);
if (sblock->fs_magic != FS_MAGIC) {
if (sblock->fs_magic == bswap32(FS_MAGIC)) {
ffs_sb_swap(sblock, sblock, 0);
@@ -442,6 +452,8 @@
nonodump = iswap32(spcl.c_level) < honorlevel;
+ initcache(readcache, readblksize);
+
(void)signal(SIGINFO, statussig);
msg("mapping (Pass I) [regular files]\n");
@@ -582,9 +594,10 @@
usage()
{
- (void)fprintf(stderr, "%s\n%s\n%s\n",
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
"usage: dump [-0123456789cnu] [-B records] [-b blocksize] [-d density]",
-" [-f file] [-h level] [-L label] [-s feet] [-T date] filesystem",
+" [-f file] [-h level] [-k read block size] [-L label]",
+" [-r read cache size] [-s feet] [-T date] filesystem",
" dump [-W | -w]");
exit(1);
}
Index: rcache.c
===================================================================
RCS file: rcache.c
diff -N rcache.c
--- /dev/null Fri Mar 19 00:42:00 1999
+++ rcache.c Fri Mar 19 03:12:36 1999
@@ -0,0 +1,445 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Martin J. Laubach <mjl@emsi.priv.at> and
+ * Manuel Bouyer <Manuel.Bouyer@lip6.fr>.
+ *
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+/*-----------------------------------------------------------------------*/
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "dump.h"
+
+/*-----------------------------------------------------------------------*/
+#define MAXCACHEBUFS 512 /* max 512 buffers */
+#define MAXMEMPART 6 /* max 15% of the user mem */
+
+/*-----------------------------------------------------------------------*/
+struct cheader {
+ volatile size_t count;
+};
+
+struct cdesc {
+ volatile daddr_t blkstart;
+ volatile daddr_t blkend;/* start + nblksread */
+ volatile daddr_t blocksRead;
+ volatile size_t time;
+#ifdef DIAGNOSTICS
+ volatile pid_t owner;
+#endif
+};
+
+static int findlru __P((void));
+
+static void *sharebuffer = NULL;
+static struct cheader *cheader;
+static struct cdesc *cdesc;
+static char *cdata;
+static int cachebufs;
+static int nblksread;
+
+#ifdef STATS
+static int nreads;
+static int nphysread;
+static int64_t readsize;
+static int64_t physreadsize;
+#endif
+
+#define CDATA(i) (cdata + ((i) * nblksread * dev_bsize))
+
+/*-----------------------------------------------------------------------*/
+void
+initcache(cachesize, readblksize)
+ int cachesize;
+ int readblksize;
+{
+ size_t len;
+ size_t sharedsize;
+
+ nblksread = readblksize / dev_bsize;
+ if(cachesize == -1) { /* Compute from memory available */
+ int usermem;
+ int mib[2] = { CTL_HW, HW_USERMEM };
+
+ len = sizeof(usermem);
+ if (sysctl(mib, 2, &usermem, &len, NULL, 0) < 0) {
+ msg("sysctl(hw.usermem) failed: %s\n", strerror(errno));
+ return;
+ }
+ cachebufs = (usermem / MAXMEMPART) / (nblksread * dev_bsize);
+ } else { /* User specified */
+ cachebufs = cachesize;
+ }
+
+ if(cachebufs) { /* Don't allocate if zero --> no caching */
+ if (cachebufs > MAXCACHEBUFS)
+ cachebufs = MAXCACHEBUFS;
+
+ sharedsize = sizeof(struct cheader) +
+ sizeof(struct cdesc) * cachebufs +
+ nblksread * cachebufs * dev_bsize;
+#ifdef STATS
+ fprintf(stderr, "Using %d buffers (%d bytes)\n", cachebufs,
+ sharedsize);
+#endif
+ sharebuffer = mmap(NULL, sharedsize, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_SHARED, -1, 0);
+ if (sharebuffer == (void *)-1) {
+ msg("can't mmap shared memory for buffer: %s\n",
+ strerror(errno));
+ return;
+ }
+ cheader = sharebuffer;
+ cdesc = (struct cdesc *) (((char *) sharebuffer) +
+ sizeof(struct cheader));
+ cdata = ((char *) sharebuffer) + sizeof(struct cheader) +
+ sizeof(struct cdesc) * cachebufs;
+
+ memset(sharebuffer, '\0', sharedsize);
+ }
+}
+/*-----------------------------------------------------------------------*/
+/* Find the cache buffer descriptor that shows the minimal access time */
+
+static int
+findlru()
+{
+ int i;
+ int mintime = cdesc[0].time;
+ int minidx = 0;
+
+ for (i = 0; i < cachebufs; i++) {
+ if (cdesc[i].time < mintime) {
+ minidx = i;
+ mintime = cdesc[i].time;
+ }
+ }
+
+ return minidx;
+}
+/*-----------------------------------------------------------------------*/
+/*
+ * Read data directly from disk, with smart error handling.
+ * Try to recover from hard errors by reading in sector sized pieces.
+ * Error recovery is attempted at most BREADEMAX times before seeking
+ * consent from the operator to continue.
+ */
+
+
+static int breaderrors = 0;
+#define BREADEMAX 32
+
+void
+rawread(blkno, buf, size)
+ daddr_t blkno;
+ char *buf;
+ int size;
+{
+ int cnt, i;
+#ifdef STATS
+ nphysread++;
+ physreadsize += size;
+#endif
+
+ if (lseek(diskfd, ((off_t) blkno << dev_bshift), 0) < 0) {
+ msg("rawread: lseek fails\n");
+ goto err;
+ }
+ if ((cnt = read(diskfd, buf, size)) == size)
+ return;
+ if (cnt == -1)
+ msg("read error from %s: %s: [block %d]: count=%d\n",
+ disk, strerror(errno), blkno, size);
+ else
+ msg("short read error from %s: [block %d]: count=%d, got=%d\n",
+ disk, blkno, size, cnt);
+err:
+ if (++breaderrors > BREADEMAX) {
+ msg("More than %d block read errors from %d\n",
+ BREADEMAX, disk);
+ broadcast("DUMP IS AILING!\n");
+ msg("This is an unrecoverable error.\n");
+ if (!query("Do you want to attempt to continue?")){
+ dumpabort(0);
+ /*NOTREACHED*/
+ } else
+ breaderrors = 0;
+ }
+ /*
+ * Zero buffer, then try to read each sector of buffer separately.
+ */
+ memset(buf, 0, size);
+ for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) {
+ if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) < 0) {
+ msg("rawread: lseek2 fails: %s!\n",
+ strerror(errno));
+ continue;
+ }
+ if ((cnt = read(diskfd, buf, (int)dev_bsize)) == dev_bsize)
+ continue;
+ if (cnt == -1) {
+ msg("read error from %s: %s: [sector %d]: count=%d: "
+ "%s\n", disk, strerror(errno), blkno, dev_bsize,
+ strerror(errno));
+ continue;
+ }
+ msg("short read error from %s: [sector %d]: count=%d, got=%d\n",
+ disk, blkno, dev_bsize, cnt);
+ }
+}
+
+/*-----------------------------------------------------------------------*/
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+void
+bread(blkno, buf, size)
+ daddr_t blkno;
+ char *buf;
+ int size;
+{
+ int osize = size;
+ daddr_t oblkno = blkno;
+ char *obuf = buf;
+ daddr_t numblocks = (size + dev_bsize -1) / dev_bsize;
+
+#ifdef STATS
+ nreads++;
+ readsize += size;
+#endif
+
+ if (!sharebuffer) {
+ rawread(blkno, buf, size);
+ return;
+ }
+
+ if (flock(diskfd, LOCK_EX)) {
+ msg("flock(LOCK_EX) failed: %s\n",
+ strerror(errno));
+ rawread(blkno, buf, size);
+ return;
+ }
+
+
+retry:
+ while(size > 0) {
+ int i;
+
+ for (i = 0; i < cachebufs; i++) {
+ struct cdesc *curr = &cdesc[i];
+
+#ifdef DIAGNOSTICS
+ if (curr->owner) {
+ fprintf(stderr, "Owner is set (%d, me=%d), can"
+ "not happen.\n", curr->owner, getpid());
+ }
+#endif
+
+ if (curr->blkend == 0)
+ continue;
+ /*
+ * If we find a bit of the read in the buffers,
+ * now compute how many blocks we can copy,
+ * copy them out, adjust blkno, buf and size,
+ * and restart
+ */
+ if (curr->blkstart <= blkno &&
+ blkno < curr->blkend) {
+ /* Number of data blocks to be copied */
+ int tocopy = min(size,
+ (curr->blkend - blkno) * dev_bsize);
+#ifdef DIAGNOSTICS
+ if (tocopy <= 0 ||
+ tocopy > nblksread * dev_bsize) {
+ fprintf(stderr, "tocopy %d !\n",
+ tocopy);
+ dumpabort(0);
+ }
+ if (CDATA(i) + (blkno - curr->blkstart) *
+ dev_bsize < CDATA(i) ||
+ CDATA(i) + (blkno - curr->blkstart) *
+ dev_bsize >
+ CDATA(i) + nblksread * dev_bsize) {
+ fprintf(stderr, "%p < %p !!!\n",
+ CDATA(i) + (blkno -
+ curr->blkstart) * dev_bsize,
+ CDATA(i));
+ fprintf(stderr, "cdesc[i].blkstart %d "
+ "blkno %d dev_bsize %ld\n",
+ curr->blkstart, blkno, dev_bsize);
+ dumpabort(0);
+ }
+#endif
+ memcpy(buf, CDATA(i) +
+ (blkno - curr->blkstart) * dev_bsize,
+ tocopy);
+
+ buf += tocopy;
+ size -= tocopy;
+ blkno += (tocopy + dev_bsize - 1) / dev_bsize;
+ numblocks -=
+ (tocopy + dev_bsize - 1) / dev_bsize;
+
+ curr->time = cheader->count++;
+
+ /*
+ * If all data of a cache block have been
+ * read, chances are good no more reads
+ * will occur, so expire the cache immediately
+ */
+
+ curr->blocksRead +=
+ (tocopy + dev_bsize -1) / dev_bsize;
+ if (curr->blocksRead >= nblksread)
+ curr->time = 0;
+
+ goto retry;
+ }
+ }
+
+ /* No more to do? */
+ if (size == 0)
+ break;
+
+ /*
+ * This does actually not happen if fs blocks are not greater
+ * than nblksread.
+ */
+ if (numblocks > nblksread) {
+ rawread(oblkno, obuf, osize);
+ break;
+ } else {
+ int idx;
+ ssize_t rsize;
+ daddr_t blockblkno;
+
+ blockblkno = (blkno / nblksread) * nblksread;
+ idx = findlru();
+ rsize = min(nblksread,
+ fsbtodb(sblock, sblock->fs_size) - blockblkno) *
+ dev_bsize;
+
+#ifdef DIAGNOSTICS
+ if (cdesc[idx].owner)
+ fprintf(stderr, "Owner is set (%d, me=%d), can"
+ "not happen(2).\n", cdesc[idx].owner,
+ getpid());
+ cdesc[idx].owner = getpid();
+#endif
+ cdesc[idx].time = cheader->count++;
+ cdesc[idx].blkstart = blockblkno;
+ cdesc[idx].blocksRead = 0;
+
+ if (lseek(diskfd,
+ ((off_t) (blockblkno) << dev_bshift), 0) < 0) {
+ msg("readBlocks: lseek fails: %s\n",
+ strerror(errno));
+ rsize = -1;
+ } else {
+ rsize = read(diskfd, CDATA(idx), rsize);
+ if (rsize < 0) {
+ msg("readBlocks: read fails: %s\n",
+ strerror(errno));
+ }
+ }
+
+ /* On errors, panic, punt, try to read without
+ * cache and let raw read routine do the rest.
+ */
+
+ if (rsize <= 0) {
+ rawread(oblkno, obuf, osize);
+#ifdef DIAGNOSTICS
+ if (cdesc[idx].owner != getpid())
+ fprintf(stderr, "Owner changed from "
+ "%d to %d, can't happen\n",
+ getpid(), cdesc[idx].owner);
+ cdesc[idx].owner = 0;
+#endif
+ break;
+ }
+
+ /* On short read, just note the fact and go on */
+ cdesc[idx].blkend = blockblkno + rsize / dev_bsize;
+
+#ifdef STATS
+ nphysread++;
+ physreadsize += rsize;
+#endif
+#ifdef DIAGNOSTICS
+ if (cdesc[idx].owner != getpid())
+ fprintf(stderr, "Owner changed from "
+ "%d to %d, can't happen\n",
+ getpid(), cdesc[idx].owner);
+ cdesc[idx].owner = 0;
+#endif
+ /*
+ * We swapped some of data in, let the loop fetch
+ * them from cache
+ */
+ }
+ }
+
+ if (flock(diskfd, LOCK_UN))
+ msg("flock(LOCK_UN) failed: %s\n",
+ strerror(errno));
+ return;
+}
+
+/*-----------------------------------------------------------------------*/
+void
+printcachestats()
+{
+#ifdef STATS
+ fprintf(stderr, "Pid %d: %d reads (%u bytes) "
+ "%d physical reads (%u bytes) %d%% hits, %d%% overhead\n",
+ getpid(), nreads, (u_int) readsize, nphysread,
+ (u_int) physreadsize, (nreads - nphysread) * 100 / nreads,
+ (int) (((physreadsize - readsize) * 100) / readsize));
+#endif
+}
+
+/*-----------------------------------------------------------------------*/
Index: tape.c
===================================================================
RCS file: /cvsroot/src/sbin/dump/tape.c,v
retrieving revision 1.17
diff -u -r1.17 tape.c
--- tape.c 1998/07/18 05:04:36 1.17
+++ tape.c 1999/03/19 11:12:36
@@ -866,7 +866,7 @@
wrote = write(tapefd, slp->tblock[0]+size,
writesize-size);
#ifdef WRITEDEBUG
- printf("slave %d wrote %d\n", slave_number, wrote);
+ fprintf(stderr, "slave %d wrote %d\n", slave_number, wrote);
#endif
if (wrote < 0)
break;
@@ -877,7 +877,7 @@
#ifdef WRITEDEBUG
if (size != writesize)
- printf("slave %d only wrote %d out of %d bytes and gave up.\n",
+ fprintf(stderr, "slave %d only wrote %d out of %d bytes and gave up.\n",
slave_number, size, writesize);
#endif
@@ -907,6 +907,7 @@
*/
(void) kill(nextslave, SIGUSR2);
}
+ printcachestats();
if (nread != 0)
quit("error reading command pipe: %s\n", strerror(errno));
}
Index: traverse.c
===================================================================
RCS file: /cvsroot/src/sbin/dump/traverse.c,v
retrieving revision 1.23
diff -u -r1.23 traverse.c
--- traverse.c 1999/03/09 17:25:52 1.23
+++ traverse.c 1999/03/19 11:12:36
@@ -696,76 +696,3 @@
maxino = minino + INOPB(sblock);
return (&inoblock[inum - minino]);
}
-
-/*
- * Read a chunk of data from the disk.
- * Try to recover from hard errors by reading in sector sized pieces.
- * Error recovery is attempted at most BREADEMAX times before seeking
- * consent from the operator to continue.
- */
-int breaderrors = 0;
-#define BREADEMAX 32
-
-void
-bread(blkno, buf, size)
- daddr_t blkno;
- char *buf;
- int size;
-{
- int cnt, i;
- extern int errno;
-
-loop:
- if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) < 0)
- msg("bread: lseek fails\n");
- if ((cnt = read(diskfd, buf, size)) == size)
- return;
- if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) {
- /*
- * Trying to read the final fragment.
- *
- * NB - dump only works in TP_BSIZE blocks, hence
- * rounds `dev_bsize' fragments up to TP_BSIZE pieces.
- * It should be smarter about not actually trying to
- * read more than it can get, but for the time being
- * we punt and scale back the read only when it gets
- * us into trouble. (mkm 9/25/83)
- */
- size -= dev_bsize;
- goto loop;
- }
- if (cnt == -1)
- msg("read error from %s: %s: [block %d]: count=%d\n",
- disk, strerror(errno), blkno, size);
- else
- msg("short read error from %s: [block %d]: count=%d, got=%d\n",
- disk, blkno, size, cnt);
- if (++breaderrors > BREADEMAX) {
- msg("More than %d block read errors from %d\n",
- BREADEMAX, disk);
- broadcast("DUMP IS AILING!\n");
- msg("This is an unrecoverable error.\n");
- if (!query("Do you want to attempt to continue?")){
- dumpabort(0);
- /*NOTREACHED*/
- } else
- breaderrors = 0;
- }
- /*
- * Zero buffer, then try to read each sector of buffer separately.
- */
- memset(buf, 0, size);
- for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) {
- if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) < 0)
- msg("bread: lseek2 fails!\n");
- if ((cnt = read(diskfd, buf, (int)dev_bsize)) == dev_bsize)
- continue;
- if (cnt == -1) {
- msg("read error from %s: %s: [sector %d]: count=%d\n",
- disk, strerror(errno), blkno, dev_bsize);
- continue;
- }
- msg("short read error from %s: [sector %d]: count=%d, got=%d\n",
- disk, blkno, dev_bsize, cnt);
- }
-}
--WIyZ46R2i8wDzkSu--