Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 May 2011 20:14:10 +0000 (UTC)
From:      Ulrich Spoerlein <uqs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r221304 - head/sbin/recoverdisk
Message-ID:  <201105012014.p41KEAIc006059@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: uqs
Date: Sun May  1 20:14:10 2011
New Revision: 221304
URL: http://svn.freebsd.org/changeset/base/221304

Log:
  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]

Modified:
  head/sbin/recoverdisk/recoverdisk.1
  head/sbin/recoverdisk/recoverdisk.c

Modified: head/sbin/recoverdisk/recoverdisk.1
==============================================================================
--- head/sbin/recoverdisk/recoverdisk.1	Sun May  1 19:47:34 2011	(r221303)
+++ head/sbin/recoverdisk/recoverdisk.1	Sun May  1 20:14:10 2011	(r221304)
@@ -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
 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.

Modified: head/sbin/recoverdisk/recoverdisk.c
==============================================================================
--- head/sbin/recoverdisk/recoverdisk.c	Sun May  1 19:47:34 2011	(r221303)
+++ head/sbin/recoverdisk/recoverdisk.c	Sun May  1 20:14:10 2011	(r221304)
@@ -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, &sectorsize);
 		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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105012014.p41KEAIc006059>