Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Mar 2009 10:37:02 +0000 (UTC)
From:      Poul-Henning Kamp <phk@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r189691 - head/sbin/recoverdisk
Message-ID:  <200903111037.n2BAb2tj093282@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: phk
Date: Wed Mar 11 10:37:02 2009
New Revision: 189691
URL: http://svn.freebsd.org/changeset/base/189691

Log:
  Some improvements to recoverdisk

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

Modified: head/sbin/recoverdisk/recoverdisk.1
==============================================================================
--- head/sbin/recoverdisk/recoverdisk.1	Wed Mar 11 09:57:11 2009	(r189690)
+++ head/sbin/recoverdisk/recoverdisk.1	Wed Mar 11 10:37:02 2009	(r189691)
@@ -32,7 +32,9 @@
 .Nd recover data from hard disk or optical media
 .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
@@ -46,15 +48,24 @@ It starts reading in multiples of the se
 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.
 .Pp
-It uses block sizes of roughly 1 MB, 64kB, and the native sector size (usually
-512 bytes).
+By default it uses block sizes of roughly 1 MB, 32kB, and the native
+sector size (usually 512 bytes).
 These figures are adjusted slightly, for devices whose sectorsize is not a
 power of 2, e.g., audio CDs with a sector size of 2352 bytes.
 .Pp
+.Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl b Ar bigsize
+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
 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
+go well, this is the same as once per minute.
 .It Fl w Ar wlist
 Write the list of remaining blocks to read to the specified file if
 .Nm
@@ -106,6 +117,10 @@ recoverdisk -r worklist -w worklist /dev
 
 # recover a single file from the unreadable media
 touch file.avi; recoverdisk /cdrom/file.avi file.avi
+
+# If the disk hangs the system on read-errors try:
+recoverdisk -b 0 /dev/ad3 /somewhere
+
 .Ed
 .Sh SEE ALSO
 .Xr dd 1

Modified: head/sbin/recoverdisk/recoverdisk.c
==============================================================================
--- head/sbin/recoverdisk/recoverdisk.c	Wed Mar 11 09:57:11 2009	(r189690)
+++ head/sbin/recoverdisk/recoverdisk.c	Wed Mar 11 10:37:02 2009	(r189691)
@@ -26,7 +26,7 @@
 
 volatile sig_atomic_t aborting = 0;
 static size_t bigsize = 1024 * 1024;
-static size_t medsize = 64 * 1024;
+static size_t medsize;
 static size_t minsize = 512;
 
 struct lump {
@@ -76,6 +76,7 @@ static void
 save_worklist(void)
 {
 	FILE *file;
+	struct lump *llp;
 
 	if (wworklist != NULL) {
 		(void)fprintf(stderr, "\nSaving worklist ...");
@@ -85,14 +86,11 @@ save_worklist(void)
 		if (file == NULL)
 			err(1, "Error opening file %s", wworklist);
 
-		for (;;) {
-			lp = TAILQ_FIRST(&lumps);
-			if (lp == NULL)
-				break;
+		TAILQ_FOREACH(llp, &lumps, list) 
 			fprintf(file, "%jd %jd %d\n",
-			    (intmax_t)lp->start, (intmax_t)lp->len, lp->state);
-			TAILQ_REMOVE(&lumps, lp, list);
-		}
+			    (intmax_t)llp->start, (intmax_t)llp->len,
+			    llp->state);
+		fclose(file);
 		(void)fprintf(stderr, " done.\n");
 	}
 }
@@ -160,14 +158,21 @@ main(int argc, char * const argv[])
 	u_int sectorsize;
 	time_t t1, t2;
 	struct stat sb;
+	u_int n, snapshot = 60;
 
-	while ((ch = getopt(argc, argv, "r:w:")) != -1) {
+	while ((ch = getopt(argc, argv, "b:r:w:s:")) != -1) {
 		switch (ch) {
+		case 'b':
+			bigsize = strtoul(optarg, NULL, 0);
+			break;
 		case 'r':
 			rworklist = strdup(optarg);
 			if (rworklist == NULL)
 				err(1, "Cannot allocate enough memory");
 			break;
+		case 's':
+			snapshot = strtoul(optarg, NULL, 0);
+			break;
 		case 'w':
 			wworklist = strdup(optarg);
 			if (wworklist == NULL)
@@ -197,15 +202,8 @@ main(int argc, char * const argv[])
 		if (error < 0)
 			err(1, "DIOCGSECTORSIZE failed");
 
-		/*
-		 * Make medsize roughly 64kB, depending on native sector
-		 * size. bigsize has to be a multiple of medsize.
-		 * For media with 2352 sectors, this will
-		 * result in 2352, 63504, and 1016064 bytes.
-		 */
 		minsize = sectorsize;
-		medsize = (medsize / sectorsize) * sectorsize;
-		bigsize = medsize * 16;
+		bigsize = (bigsize / sectorsize) * sectorsize;
 
 		error = ioctl(fdr, DIOCGMEDIASIZE, &t);
 		if (error < 0)
@@ -215,6 +213,17 @@ main(int argc, char * const argv[])
 		flags |= O_CREAT | O_TRUNC;
 	}
 
+	if (bigsize < minsize)
+		bigsize = minsize;
+
+	for (ch = 0; (bigsize >> ch) > minsize; ch++)
+		continue;
+	medsize = bigsize >> (ch / 2);
+	medsize = (medsize / minsize) * minsize;
+
+	fprintf(stderr, "Bigsize = %u, medsize = %u, minsize = %u\n",
+	    bigsize, medsize, minsize);
+
 	buf = malloc(bigsize);
 	if (buf == NULL)
 		err(1, "Cannot allocate %jd bytes buffer", (intmax_t)bigsize);
@@ -238,6 +247,7 @@ main(int argc, char * const argv[])
 	t1 = 0;
 	start = len = i = state = 0;
 	PRINT_HEADER;
+	n = 0;
 	for (;;) {
 		lp = TAILQ_FIRST(&lumps);
 		if (lp == NULL)
@@ -257,6 +267,10 @@ main(int argc, char * const argv[])
 			if (t1 != t2 || lp->len < (off_t)bigsize) {
 				PRINT_STATUS(start, i, len, state, d, t);
 				t1 = t2;
+				if (++n == snapshot) {
+					save_worklist();
+					n = 0;
+				}
 			}
 			if (i == 0) {
 				errx(1, "BOGUS i %10jd", (intmax_t)i);



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