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");