Whoops, sorry about the previous misfire...

> In message <[EMAIL PROTECTED]> Edward Elhauge writes:
> : to autorecover on bad sectors, but every system that I've had to recover
> : seems to be in a state where the bad sectors aren't remapping. I've tried
> 
> I've often wanted to write a bad block remapper.  While SCSI is
> supposed to do this automatically, I've found that a scan on any
> adaptec controller will remap these blocks (forces the remapping).

I've got a program which attempts to read all blocks and may be able
to rewrite bad blocks.  It's nothing fancy.  Only works if you've got
auto-reallocate turned on in the drive.

% cat diskscan.c
#include        <stdio.h>
#include        <unistd.h>
#include        <errno.h>
#include        <fcntl.h>





int fixup(off, fd)
off_t off;
int fd;
{
        char buffer[512];
        int i, rval;

        for (i = 0; i < 65536; i += 512) {
                if (lseek(fd, off + i, SEEK_SET) < 0) {
                        doerror("lseek", off + i, 0);
                }
                if ((rval = read(fd, buffer, sizeof(buffer))) != sizeof(buffer)) {
                        if (errno) {
                                if (lseek(fd, off + i, SEEK_SET) < 0) {
                                        doerror("lseek", off + i, 0);
                                }
                                write(fd, buffer, sizeof(buffer));
                        }
                }
        }
}





int doerror(str, off, type)
char *str;
off_t off;
int type;
{
        static int ign = 0;
        char buffer[80];

        fprintf(stderr, "\nError at %qx, ", (quad_t) off);
        perror(str);
        if (! ign) {
                if (type) {
                        fprintf(stderr, "Attempt to correct?  (y/n/a) ");
                } else {
                        fprintf(stderr, "Press 'y' to continue: ");
                }
                while (! ign) {
                        fgets(buffer, sizeof(buffer), stdin);
                        if (*buffer == 'y') {
                                return(0);
                        }
                        if (*buffer == 'n') {
                                return(1);
                        }
                        if (*buffer == 'a') {
                                ign++;
                                return(0);
                        }
                }
        }
        return(0);
}





int main(argc, argv)
int argc;
char *argv[];
{
        int fd, rval;
        char buffer[65536];
        off_t off = 0;
        int eof = 0;
        int count = 0;

        if (argc != 2) {
                fprintf(stderr, "usage: diskscan <dev>\n");
                exit(1);
        }
        if ((fd = open(argv[1], O_RDWR, 0644)) < 0) {
                perror(argv[1]);
        }
        while (! eof) {
                if (! count) {
                        fprintf(stderr, "%qx, ", (quad_t) off);
                }
                count++;
                count %= 8;

                if (lseek(fd, off, SEEK_SET) < 0) {
                        doerror("lseek", off, 0);
                }
                if ((rval = read(fd, buffer, sizeof(buffer))) != sizeof(buffer)) {
                        if (errno) {
                                if (! doerror("read", off, 1)) {
                                        fixup(off, fd);
                                }
                        }
                }
                off += sizeof(buffer);
        }
}

I don't even guarantee that it's correct, but I do use it with some
success...  vinum takes an entire drive offline when it sees an error,
and I use this to scan for and fix errors before turning the drive back
on.
-- 
... Joe

-------------------------------------------------------------------------------
Joe Greco - Systems Administrator                             [EMAIL PROTECTED]
Solaria Public Access UNIX - Milwaukee, WI                         414/342-4847


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to