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