recoverdisk(8): treat output file consistently and abort on EINVAL
This improves usability a little as we no longer require using touch. Also reword the manpage wrt. parameters and fix usage() [1] With no media in a cd(4) drive, the reads will loop producing EINVAL, abort in that case [2]. Document the shortcoming of sectorsize and MAXPHYS (a quick solution to this might be having MAXPHYS as the "bigsize", in short testing it didn't make a difference on throughput). Submitted by: arundel [1] PR: bin/154528 [2]
This commit is contained in:
parent
3ec54ea245
commit
93c5246832
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 6, 2006
|
||||
.Dd May 1, 2011
|
||||
.Dt RECOVERDISK 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -33,17 +33,20 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl b Ar bigsize
|
||||
.Op Fl r Ar rlist
|
||||
.Op Fl s Ar snapshot
|
||||
.Op Fl w Ar wlist
|
||||
.Ar special
|
||||
.Op Ar file
|
||||
.Op Fl r Ar readlist
|
||||
.Op Fl s Ar interval
|
||||
.Op Fl w Ar writelist
|
||||
.Ar source
|
||||
.Op Ar destination
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility reads data from the
|
||||
.Ar special
|
||||
.Ar source
|
||||
file until all blocks could be successfully read.
|
||||
If
|
||||
.Ar destination
|
||||
was specified all data is being written to that file.
|
||||
It starts reading in multiples of the sector size.
|
||||
Whenever a block fails, it is put to the end of the working queue and will be
|
||||
read again, possibly with a smaller read size.
|
||||
@ -59,13 +62,13 @@ The options are as follows:
|
||||
The size of reads attempted first.
|
||||
The middle pass is roughly the logarithmic average of the bigsize and
|
||||
the sectorsize.
|
||||
.It Fl r Ar rlist
|
||||
.It Fl r Ar readlist
|
||||
Read the list of blocks and block sizes to read from the specified file.
|
||||
.It Fl s Ar snapshot
|
||||
How often we should update the worklist file while things go OK.
|
||||
The default is 60 and the units is "progress messages" so if things
|
||||
.It Fl s Ar interval
|
||||
How often we should update the writelist file while things go OK.
|
||||
The default is 60 and the unit is "progress messages" so if things
|
||||
go well, this is the same as once per minute.
|
||||
.It Fl w Ar wlist
|
||||
.It Fl w Ar writelist
|
||||
Write the list of remaining blocks to read to the specified file if
|
||||
.Nm
|
||||
is aborted via
|
||||
@ -102,20 +105,19 @@ Percent complete.
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal
|
||||
# recover data from failing hard drive ad3
|
||||
touch /data/lots_of_space
|
||||
recoverdisk /dev/ad3 /data/lots_of_space
|
||||
recoverdisk /dev/ad3 /data/disk.img
|
||||
|
||||
# clone a hard disk
|
||||
recoverdisk /dev/ad3 /dev/ad4
|
||||
|
||||
# read an ISO image from a CD-ROM
|
||||
touch /data/cd.iso; recoverdisk /dev/acd0 /data/cd.iso
|
||||
recoverdisk /dev/cd0 /data/cd.iso
|
||||
|
||||
# continue reading from a broken CD and update the existing worklist
|
||||
recoverdisk -r worklist -w worklist /dev/acd0 /data/cd.iso
|
||||
recoverdisk -r worklist -w worklist /dev/cd0 /data/cd.iso
|
||||
|
||||
# recover a single file from the unreadable media
|
||||
touch file.avi; recoverdisk /cdrom/file.avi file.avi
|
||||
recoverdisk /cdrom/file.avi file.avi
|
||||
|
||||
# If the disk hangs the system on read-errors try:
|
||||
recoverdisk -b 0 /dev/ad3 /somewhere
|
||||
@ -133,7 +135,7 @@ utility first appeared in
|
||||
The original implementation was done by
|
||||
.An Poul-Henning Kamp Aq phk@FreeBSD.org
|
||||
with minor improvements from
|
||||
.An Ulrich Sp\(:orlein Aq uspoerlein@gmail.com .
|
||||
.An Ulrich Sp\(:orlein Aq uqs@FreeBSD.org .
|
||||
.Pp
|
||||
This manual page was written by
|
||||
.An Ulrich Sp\(:orlein .
|
||||
@ -144,4 +146,13 @@ This is due to the DMA reads being split up into blocks of at most 128kB.
|
||||
These reads then fail if the sectorsize is not a divisor of 128kB.
|
||||
When reading a full raw audio CD, this leads to roughly 700 error messages
|
||||
flying by.
|
||||
This is harmless.
|
||||
This is harmless and can be avoided by setting
|
||||
.Fl b
|
||||
to no more than 128kB.
|
||||
.\".Pp
|
||||
.\"When reading from optical media, a bug in the GEOM framework will
|
||||
.\"prevent it from seeing that the media has been removed.
|
||||
.\"The device can still be opened, but all reads will fail.
|
||||
.\"This is usually harmless, but will send
|
||||
.\".Nm
|
||||
.\"into an infinite loop.
|
||||
|
@ -86,7 +86,7 @@ save_worklist(void)
|
||||
if (file == NULL)
|
||||
err(1, "Error opening file %s", wworklist);
|
||||
|
||||
TAILQ_FOREACH(llp, &lumps, list)
|
||||
TAILQ_FOREACH(llp, &lumps, list)
|
||||
fprintf(file, "%jd %jd %d\n",
|
||||
(intmax_t)llp->start, (intmax_t)llp->len,
|
||||
llp->state);
|
||||
@ -134,8 +134,8 @@ read_worklist(off_t t)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: recoverdisk [-r worklist] [-w worklist] source-drive [destination]\n");
|
||||
(void)fprintf(stderr, "usage: recoverdisk [-b bigsize] [-r readlist] "
|
||||
"[-s interval] [-w writelist] source [destination]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ main(int argc, char * const argv[])
|
||||
int fdr, fdw;
|
||||
off_t t, d, start, len;
|
||||
size_t i, j;
|
||||
int error, flags, state;
|
||||
int error, state;
|
||||
u_char *buf;
|
||||
u_int sectorsize;
|
||||
time_t t1, t2;
|
||||
@ -196,7 +196,6 @@ main(int argc, char * const argv[])
|
||||
error = fstat(fdr, &sb);
|
||||
if (error < 0)
|
||||
err(1, "fstat failed");
|
||||
flags = O_WRONLY;
|
||||
if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
|
||||
error = ioctl(fdr, DIOCGSECTORSIZE, §orsize);
|
||||
if (error < 0)
|
||||
@ -210,7 +209,6 @@ main(int argc, char * const argv[])
|
||||
err(1, "DIOCGMEDIASIZE failed");
|
||||
} else {
|
||||
t = sb.st_size;
|
||||
flags |= O_CREAT | O_TRUNC;
|
||||
}
|
||||
|
||||
if (bigsize < minsize)
|
||||
@ -229,9 +227,12 @@ main(int argc, char * const argv[])
|
||||
err(1, "Cannot allocate %zu bytes buffer", bigsize);
|
||||
|
||||
if (argc > 1) {
|
||||
fdw = open(argv[1], flags, DEFFILEMODE);
|
||||
fdw = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE);
|
||||
if (fdw < 0)
|
||||
err(1, "Cannot open write descriptor %s", argv[1]);
|
||||
if (ftruncate(fdw, t) < 0)
|
||||
err(1, "Cannot truncate output %s to %jd bytes",
|
||||
argv[1], (intmax_t)t);
|
||||
} else
|
||||
fdw = -1;
|
||||
|
||||
@ -292,6 +293,10 @@ main(int argc, char * const argv[])
|
||||
}
|
||||
printf("\n%jd %zu failed (%s)\n",
|
||||
lp->start, i, strerror(errno));
|
||||
if (errno == EINVAL) {
|
||||
printf("read() size too big? Try with -b 131072");
|
||||
aborting = 1;
|
||||
}
|
||||
if (errno == ENXIO)
|
||||
aborting = 1;
|
||||
new_lump(lp->start, i, lp->state + 1);
|
||||
|
Loading…
Reference in New Issue
Block a user