Date: Thu, 21 Sep 2000 21:37:46 -0500 (CDT) From: Joe Greco <jgreco@ns.sol.net> To: imp@village.org Cc: hackers@freebsd.org, isp@freebsd.org Subject: Re: Frustration with SCSI system Message-ID: <200009220237.VAA16401@aurora.sol.net>
next in thread | raw e-mail | index | archive | help
Whoops, sorry about the previous misfire...
> In message <200009201958.MAA45703@ns2.uncanny.net> 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 jgreco@ns.sol.net
Solaria Public Access UNIX - Milwaukee, WI 414/342-4847
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-isp" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200009220237.VAA16401>
