Subject: Another patch for dkctl(8) (was Re: PATCH: `dkctl dev' shows
To: None <uebayasi@gmail.com>
From: Takahiro Kambe <taca@back-street.net>
List: tech-userlevel
Date: 12/12/2007 12:16:50
Hi,

Here is my little patch for dkctl(8).

This patch add "badsector rewrite" to fix bad sectors.  (IDE disks
allocate an alternative sector for a bad sector when writing to the
bad sector.)

Works fine for me.

-- 
Takahiro Kambe <taca@back-street.net>


diff -u -r1.1.1.1 dkctl.8
--- sbin/dkctl/dkctl.8	2 Dec 2006 09:16:01 -0000	1.1.1.1
+++ sbin/dkctl/dkctl.8	12 Dec 2007 03:14:48 -0000
@@ -87,7 +87,7 @@
 is specified, drop if
 .Ar no
 is specified.)
-.It Ic badsector Ar flush | list | retry
+.It Ic badsector Ar flush | list | retry | rewrite
 Used for managing the kernel's bad sector list for
 .Xr wd 4
 devices.
@@ -105,6 +105,9 @@
 This option
 .Em can only
 be used with character devices.
+.It rewrite
+Try to write to bad sectors and do retry function.
+It might fix bad sectors allocating alternative sectors by the disk drive.
 .El
 .It Ic addwedge Ar name Ar startblk Ar blkcnt Ar ptype
 Define a
Index: sbin/dkctl/dkctl.c
===================================================================
RCS file: /data/cvs/src/sbin/dkctl/dkctl.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 dkctl.c
--- sbin/dkctl/dkctl.c	2 Dec 2006 09:16:01 -0000	1.1.1.1
+++ sbin/dkctl/dkctl.c	11 Dec 2007 06:54:10 -0000
@@ -122,7 +122,7 @@
 	  O_RDWR },
 
 	{ "badsector",
-	  "flush | list | retry",
+	  "flush | list | retry | rewrite",
 	   disk_badsectors,
 	   O_RDWR },
 
@@ -352,6 +352,7 @@
 	struct stat sb;
 	u_char *block;
 	time_t tm;
+	int pass, retry_only = 1;
 
 	if (argc != 1)
 		usage();
@@ -387,7 +388,8 @@
 		if (ioctl(fd, DIOCBSFLUSH) == -1)
 			err(1, "%s: badsectors flush", dvname);
 
-	} else if (strcmp(argv[0], "retry") == 0) {
+	} else if (strcmp(argv[0], "retry") == 0 ||
+		   (retry_only = strcmp(argv[0], "rewrite")) == 0) {
 		/*
 		 * Enforce use of raw device here because the block device
 		 * causes access to blocks to be clustered in a larger group,
@@ -471,13 +473,28 @@
 			printf("%s: Retrying %"PRIdaddr" - %"
 			    PRIdaddr"\n", dvname, dbs->dbs_min, dbs->dbs_max);
 
+			pass = 0;
 			for (blk = dbs->dbs_min; blk <= dbs->dbs_max; blk++) {
+			again:
 				if (lseek(fd, (off_t)blk * DEV_BSIZE,
 				    SEEK_SET) == -1) {
 					warn("%s: lseek block %" PRIdaddr "",
 					    dvname, blk);
 					continue;
 				}
+				if (!retry_only) {
+					switch (pass) {
+					case 0:
+						pass = 1;
+						if (write(fd, block, DEV_BSIZE) != DEV_BSIZE)
+							printf("write failed\n");
+						goto again;
+						break;
+					case 1:
+						pass = 0;
+						break;
+					}
+				}
 				printf("%s: block %"PRIdaddr" - ", dvname, blk);
 				if (read(fd, block, DEV_BSIZE) != DEV_BSIZE)
 					printf("failed\n");