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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to