From owner-svn-src-head@FreeBSD.ORG Sun May 1 20:14:10 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CBEA01065672; Sun, 1 May 2011 20:14:10 +0000 (UTC) (envelope-from uqs@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id BB5408FC1B; Sun, 1 May 2011 20:14:10 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p41KEANr006062; Sun, 1 May 2011 20:14:10 GMT (envelope-from uqs@svn.freebsd.org) Received: (from uqs@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p41KEAIc006059; Sun, 1 May 2011 20:14:10 GMT (envelope-from uqs@svn.freebsd.org) Message-Id: <201105012014.p41KEAIc006059@svn.freebsd.org> From: Ulrich Spoerlein Date: Sun, 1 May 2011 20:14:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r221304 - head/sbin/recoverdisk X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 May 2011 20:14:10 -0000 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, §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);