Subject: Re: SCSI reassign ioctl.
To: Brian Buhrow <buhrow@cats.ucsc.edu>
From: Tobias Weingartner <weingart@austin.BrandonU.CA>
List: current-users
Date: 05/11/1995 13:35:50
In message <199505092315.QAA08014@baloo.ucsc.edu>, Brian Buhrow writes:
>
> 1. My understanding is that the scsi system can operate in two modes. A.
> Automatic correction mode, and B. Manual correction mode. In A, the scsi
> disk automatically moves bad sectors to good portions of the disk as the
> errors are discovered. In the second mode, scsi operations on a bad block
> will continue to try and use the bad block until the scsi system is
> explicitly told not to, either by locking the sector out, or by remapping
> it to a new portion of the physical disk. In which mode does the netbsd
> scsi subsystem operate?
I believe it uses the first case. At least NetBSD-1.0 seemed to, last time
I took a look at this code.
> 2. Even if the netbsd scsi system operates in the automatic mode, is it
> possible to explicitly give scsi commands to remap sectors of hard disks
> through an ioctl interface?
Well, since you have code, most anything is possible! ;-)
On a more serious note, I needed to remap some bad blocks on my root drive,
and could not think of any other way to do it. I patched a 1.0 kernel, to
give me the ioctl (the code to remap is in there), and then wrote a bare-
bones program to remap the blocks. The patches are attached
> 3. Even if it is possible, is the ability to reassign bad blocks an
> extension to the scsi spec which only some controllers are capable of
> handling?
>From reading the scsi-spec, it is not the controller that needs to
understand, but the disk drive.
PS: If you use the following code, all standard disclaimers apply. Also,
remap each bad sector only *ONCE*, otherwise you will be remapping the
good sector put in place of the bad one the second time 'round.
--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 |
*----------------------------------------------------------------------------*
natasha% rcsdiff -c !$
rcsdiff -c 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));
natasha% rcsdiff -c 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;
natasha% diff -c /dev/null reass.c
*** /dev/null Thu May 11 02:02:29 1995
--- reass.c Wed Apr 12 15:59:42 1995
***************
*** 0 ****
--- 1,61 ----
+ /*
+ * $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);
+ }
+