Add a "-D" flag to restore which puts it into "degraded" mode. This
makes restore less efficient, but it makes a bigger effore to read corrupted dumps. Specifiacally, when in degreded mode: 1) Restore shifts the input by 1 byte if it sees a problem, rather than one tape block. 2) It doesn't assume the inodes are stored in ascending order. 3) It turns some panics into warning printfs. We also verify some fields more carefully than before. There's probably more a degreded mode could do, but this seems to help a lot. Approved by: imp, iedowse, mckusick MFC after: 3 weeks
This commit is contained in:
parent
f352d33919
commit
12df44b425
@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "restore.h"
|
||||
#include "extern.h"
|
||||
|
||||
int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
|
||||
int bflag = 0, cvtflag = 0, dflag = 0, Dflag = 0, vflag = 0, yflag = 0;
|
||||
int hflag = 1, mflag = 1, Nflag = 0;
|
||||
int uflag = 0;
|
||||
int pipecmd = 0;
|
||||
@ -97,7 +97,7 @@ main(int argc, char *argv[])
|
||||
|
||||
inputdev = NULL;
|
||||
obsolete(&argc, &argv);
|
||||
while ((ch = getopt(argc, argv, "b:df:himNP:Rrs:tuvxy")) != -1)
|
||||
while ((ch = getopt(argc, argv, "b:dDf:himNP:Rrs:tuvxy")) != -1)
|
||||
switch(ch) {
|
||||
case 'b':
|
||||
/* Change default tape blocksize. */
|
||||
@ -111,6 +111,9 @@ main(int argc, char *argv[])
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'D':
|
||||
Dflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (pipecmd)
|
||||
errx(1,
|
||||
|
@ -38,32 +38,32 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Fl i
|
||||
.Op Fl dhmNuvy
|
||||
.Op Fl dDhmNuvy
|
||||
.Op Fl b Ar blocksize
|
||||
.Op Fl f Ar file | Fl P Ar pipecommand
|
||||
.Op Fl s Ar fileno
|
||||
.Nm
|
||||
.Fl R
|
||||
.Op Fl dNuvy
|
||||
.Op Fl dDNuvy
|
||||
.Op Fl b Ar blocksize
|
||||
.Op Fl f Ar file | Fl P Ar pipecommand
|
||||
.Op Fl s Ar fileno
|
||||
.Nm
|
||||
.Fl r
|
||||
.Op Fl dNuvy
|
||||
.Op Fl dDNuvy
|
||||
.Op Fl b Ar blocksize
|
||||
.Op Fl f Ar file | Fl P Ar pipecommand
|
||||
.Op Fl s Ar fileno
|
||||
.Nm
|
||||
.Fl t
|
||||
.Op Fl dhNuvy
|
||||
.Op Fl dDhNuvy
|
||||
.Op Fl b Ar blocksize
|
||||
.Op Fl f Ar file | Fl P Ar pipecommand
|
||||
.Op Fl s Ar fileno
|
||||
.Op Ar
|
||||
.Nm
|
||||
.Fl x
|
||||
.Op Fl dhmNuvy
|
||||
.Op Fl dDhmNuvy
|
||||
.Op Fl b Ar blocksize
|
||||
.Op Fl f Ar file | Fl P Ar pipecommand
|
||||
.Op Fl s Ar fileno
|
||||
@ -278,6 +278,12 @@ option is not specified,
|
||||
tries to determine the media block size dynamically.
|
||||
.It Fl d
|
||||
Sends verbose debugging output to the standard error.
|
||||
.It Fl D
|
||||
This puts
|
||||
.Nm
|
||||
into degraded mode,
|
||||
causing restore to operate less efficiently
|
||||
but to try harder to read corrupted backups.
|
||||
.It Fl f Ar file
|
||||
Read the backup from
|
||||
.Ar file ;
|
||||
|
@ -687,6 +687,17 @@ createfiles(void)
|
||||
*/
|
||||
if (first > last)
|
||||
return;
|
||||
if (Dflag) {
|
||||
if (curfile.ino == maxino)
|
||||
return;
|
||||
if((ep = lookupino(curfile.ino)) != NULL &&
|
||||
(ep->e_flags & (NEW|EXTRACT))) {
|
||||
goto justgetit;
|
||||
} else {
|
||||
skipfile();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Reject any volumes with inodes greater than the last
|
||||
* one needed, so that we can quickly skip backwards to
|
||||
@ -749,6 +760,7 @@ createfiles(void)
|
||||
ep = lookupino(next);
|
||||
if (ep == NULL)
|
||||
panic("corrupted symbol table\n");
|
||||
justgetit:
|
||||
(void) extractfile(myname(ep));
|
||||
ep->e_flags &= ~NEW;
|
||||
if (volno != curvol)
|
||||
|
@ -40,6 +40,7 @@
|
||||
*/
|
||||
extern int bflag; /* set input block size */
|
||||
extern int dflag; /* print out debugging info */
|
||||
extern int Dflag; /* degraded mode - try hard to get stuff back */
|
||||
extern int hflag; /* restore heirarchies */
|
||||
extern int mflag; /* restore by name instead of inode number */
|
||||
extern int Nflag; /* do not write the disk */
|
||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -74,6 +75,7 @@ static int blkcnt;
|
||||
static int numtrec;
|
||||
static char *tapebuf;
|
||||
static union u_spcl endoftapemark;
|
||||
static long byteslide = 0;
|
||||
static long blksread; /* blocks read since last header */
|
||||
static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */
|
||||
static long tapesread;
|
||||
@ -170,12 +172,13 @@ newtapebuf(long size)
|
||||
if (size <= tapebufsize)
|
||||
return;
|
||||
if (tapebuf != NULL)
|
||||
free(tapebuf);
|
||||
tapebuf = malloc(size * TP_BSIZE);
|
||||
free(tapebuf - TP_BSIZE);
|
||||
tapebuf = malloc((size+1) * TP_BSIZE);
|
||||
if (tapebuf == NULL) {
|
||||
fprintf(stderr, "Cannot allocate space for tape buffer\n");
|
||||
done(1);
|
||||
}
|
||||
tapebuf += TP_BSIZE;
|
||||
tapebufsize = size;
|
||||
}
|
||||
|
||||
@ -733,6 +736,15 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long))
|
||||
gettingfile++;
|
||||
loop:
|
||||
for (i = 0; i < spcl.c_count; i++) {
|
||||
if (!readmapflag && i > TP_NINDIR) {
|
||||
if (Dflag) {
|
||||
fprintf(stderr, "spcl.c_count = %jd\n",
|
||||
(intmax_t)spcl.c_count);
|
||||
break;
|
||||
} else
|
||||
panic("spcl.c_count = %jd\n",
|
||||
(intmax_t)spcl.c_count);
|
||||
}
|
||||
if (readmapflag || spcl.c_addr[i]) {
|
||||
readtape(&buf[curblk++][0]);
|
||||
if (curblk == fssize / TP_BSIZE) {
|
||||
@ -751,9 +763,20 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long))
|
||||
TP_BSIZE : size));
|
||||
}
|
||||
if ((size -= TP_BSIZE) <= 0) {
|
||||
for (i++; i < spcl.c_count; i++)
|
||||
for (i++; i < spcl.c_count; i++) {
|
||||
if (!readmapflag && i > TP_NINDIR) {
|
||||
if (Dflag) {
|
||||
fprintf(stderr,
|
||||
"spcl.c_count = %jd\n",
|
||||
(intmax_t)spcl.c_count);
|
||||
break;
|
||||
} else
|
||||
panic("spcl.c_count = %jd\n",
|
||||
(intmax_t)spcl.c_count);
|
||||
}
|
||||
if (readmapflag || spcl.c_addr[i])
|
||||
readtape(junk);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -872,15 +895,19 @@ xtrnull(char *buf, long size)
|
||||
static void
|
||||
readtape(char *buf)
|
||||
{
|
||||
long rd, newvol, i;
|
||||
long rd, newvol, i, oldnumtrec;
|
||||
int cnt, seek_failed;
|
||||
|
||||
if (blkcnt < numtrec) {
|
||||
memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE);
|
||||
if (blkcnt + (byteslide > 0) < numtrec) {
|
||||
memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE);
|
||||
blksread++;
|
||||
tapeaddr++;
|
||||
return;
|
||||
}
|
||||
if (numtrec > 0)
|
||||
memmove(&tapebuf[-TP_BSIZE],
|
||||
&tapebuf[(numtrec-1) * TP_BSIZE], (long)TP_BSIZE);
|
||||
oldnumtrec = numtrec;
|
||||
for (i = 0; i < ntrec; i++)
|
||||
((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
|
||||
if (numtrec == 0)
|
||||
@ -981,8 +1008,12 @@ readtape(char *buf)
|
||||
terminateinput();
|
||||
memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE);
|
||||
}
|
||||
blkcnt = 0;
|
||||
memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE);
|
||||
if (oldnumtrec == 0)
|
||||
blkcnt = 0;
|
||||
else
|
||||
blkcnt -= oldnumtrec;
|
||||
memmove(buf,
|
||||
&tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE);
|
||||
blksread++;
|
||||
tapeaddr++;
|
||||
}
|
||||
@ -1069,6 +1100,8 @@ gethead(struct s_spcl *buf)
|
||||
}
|
||||
if (checksum((int *)buf) == FAIL)
|
||||
return (FAIL);
|
||||
if (_time64_to_time(buf->c_date) != dumpdate)
|
||||
fprintf(stderr, "Header with wrong dumpdate.\n");
|
||||
if (Bcvt) {
|
||||
swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf);
|
||||
swabst((u_char *)"l",(u_char *) &buf->c_level);
|
||||
@ -1225,8 +1258,17 @@ findinode(struct s_spcl *header)
|
||||
if (header->c_addr[i])
|
||||
readtape(buf);
|
||||
while (gethead(header) == FAIL ||
|
||||
_time64_to_time(header->c_date) != dumpdate)
|
||||
_time64_to_time(header->c_date) != dumpdate) {
|
||||
skipcnt++;
|
||||
if (Dflag) {
|
||||
byteslide++;
|
||||
if (byteslide < TP_BSIZE) {
|
||||
blkcnt--;
|
||||
blksread--;
|
||||
} else
|
||||
byteslide = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_INODE:
|
||||
@ -1263,18 +1305,36 @@ findinode(struct s_spcl *header)
|
||||
break;
|
||||
|
||||
case TS_TAPE:
|
||||
panic("unexpected tape header\n");
|
||||
/* NOTREACHED */
|
||||
if (Dflag)
|
||||
fprintf(stderr, "unexpected tape header\n");
|
||||
else
|
||||
panic("unexpected tape header\n");
|
||||
|
||||
default:
|
||||
panic("unknown tape header type %d\n", spcl.c_type);
|
||||
/* NOTREACHED */
|
||||
if (Dflag)
|
||||
fprintf(stderr, "unknown tape header type %d\n",
|
||||
spcl.c_type);
|
||||
else
|
||||
panic("unknown tape header type %d\n",
|
||||
spcl.c_type);
|
||||
while (gethead(header) == FAIL ||
|
||||
_time64_to_time(header->c_date) != dumpdate) {
|
||||
skipcnt++;
|
||||
if (Dflag) {
|
||||
byteslide++;
|
||||
if (byteslide < TP_BSIZE) {
|
||||
blkcnt--;
|
||||
blksread--;
|
||||
} else
|
||||
byteslide = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} while (htype == TS_ADDR);
|
||||
if (skipcnt > 0)
|
||||
fprintf(stderr, "resync restore, skipped %ld blocks\n",
|
||||
skipcnt);
|
||||
fprintf(stderr, "resync restore, skipped %ld %s\n",
|
||||
skipcnt, Dflag ? "bytes" : "blocks");
|
||||
skipcnt = 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user