Subject: Re: Rash of "sd0(aha0:0:0): medium error, info = NNNNNN (decimal)"
To: None <earle@isolar.tujunga.ca.us>
From: Tobias Weingartner <weingart@austin.BrandonU.CA>
List: port-i386
Date: 04/22/1995 10:07:23
In message <9504220635.AA13240@isolar.Tujunga.CA.US>, Greg Earle writes:
> Sigh.  My nice little 486DX/33 PC installation of NetBSD/i386 1.0 was doing
> just fine until recently, when all of a sudden it started getting struck by a
> rash of disk errors.
> 
[Deleted]

I had something similar happen to me, but I did not really want to re-format
or boot DOS(yuk!) to fix the errors.  To top it off, my errors were within the
root partition, which made things even more fun to try and fix.

My 'solution' was to modify my kernel slightly, so that I could issue SCSI
'REASSIGN BLOCK' commands to the drive in question.  Then a quick hack to
actually do the ioctl's.  Here are the relevant diffs to NetBSD-1.0/i386.

OF COURSE, NO WARRANTY, ETC, BLAH, BLAH, BLAH.  IF YOU LOOSE DATA, I AM NOT
RESPONSIBLE.

Couple words of advice:
	Back up first.
	Run fsck afterwards.

NOTE: if the reass.c program does not print anything out, the block will
have been reassigned.  Do not reassign the same block twice, as you will
only be wasting space on one of the bad lists on the drive.  Also, you will
have to copy /sys/sys/disklabel.h into /usr/include/sys/disklable.h after
applying the patch.  (I'm not sure, but a 'make install' in /usr/src/include
might do that for ya.)


/sys/scsi/sd.c
===================================================================
RCS file: RCS/sd.c,v
retrieving revision 1.1
diff -c -r1.1 sd.c
*** 1.1 1995/04/12 06:41:58
--- sd.c        1995/04/12 21:27:39
***************
*** 612,617 ****
--- 612,622 ----
                        return error;
                }
  
+       case DIOCREASSIGN: {
+               int blockno = *(int *)addr;
+               return(sd_reassign_blocks(sd, blockno));
+               }
+ 
        default:
                if (part != RAW_PART)
                        return ENOTTY;
===================================================================


/sys/sys/disklabel.h
===================================================================
RCS file: RCS/disklabel.h,v
retrieving revision 1.1
diff -c -r1.1 disklabel.h
*** 1.1 1995/04/12 06:49:53
--- disklabel.h 1995/04/12 06:51:57
***************
*** 369,374 ****
--- 369,376 ----
  
  #define DIOCSBAD      _IOW('d', 110, struct dkbad)    /* set kernel dkbad */
  
+ #define DIOCREASSIGN  _IOW('d', 111, int) /* reassign block */
+ 
  #ifdef KERNEL
  #ifdef i386
  int bounds_check_with_label __P((struct buf *, struct disklabel *, int));
===================================================================


reass.c
===================================================================
/*
 * $Id$
 */

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <err.h>
#include <fcntl.h>
#include <sys/disklabel.h>
#include <sys/types.h>
#include <sys/ioctl.h>

int usage(const char* prog){
        const char *s = strrchr(prog, '/');

        if(s == NULL) s = prog;
        (void)fprintf(stderr, "usage: %s <-f device> <blockno>\n", s);
        return(1);
}


int main(int argc, char *argv[]){
        int fd, ch;
        int blockno = -1;
        char *dev = NULL;


        /* Get options */
        while ((ch = getopt(argc, argv, "f:")) != EOF){
                switch (ch) {
                case 'f':
                        dev = optarg;
                        break;
                case '?':
                default:
                        return(usage(argv[0]));
                }
        }
        blockno = atoi(argv[optind]);

        /* Check arguments */
        if(argc - optind < 1) return(usage(argv[0]));
        if(blockno == -1 || dev == NULL) return(usage(argv[0]));

        /* Fix arguments
        argc -= optind;
        argv += optind;
        */

        /* Now do the funky stuff */
        if((fd = open(dev, O_RDONLY)) < 0) perror("open");
        if(ioctl(fd, DIOCREASSIGN, &blockno)) warn("CDIOREASSIGN");

        /* Close and clean up */
        close(fd);

        return(0);
}
===================================================================


--Toby.
*----------------------------------------------------------------------------*
| Tobias Weingartner | Email: weingart@BrandonU.Ca | Need a Unix sys-admin?  |
| Box 27, Beulah, MB |-----------------------------| Send E-Mail for resume, |
| R0M 0B0, Canada    | Unix Guru, Admin, Sys-Prgmr | and other details...    |
|----------------------------------------------------------------------------|
|      %SYSTEM-F-ANARCHISM, The operating system has been overthrown         |
*----------------------------------------------------------------------------*