Date: Sat, 1 Feb 1997 13:08:55 -0500 (EST) From: Peter Dufault <dufault@hda.com> To: Don.Lewis@tsc.tdk.com (Don Lewis) Cc: joerg_wunsch@uriah.heep.sax.de, Don.Lewis@tsc.tdk.com, freebsd-scsi@freebsd.org Subject: Re: SCSI disk MEDIUM ERROR with a few twists Message-ID: <199702011808.NAA16376@hda.hda.com> In-Reply-To: <199702011537.HAA28985@salsa.gv.tsc.tdk.com> from Don Lewis at "Feb 1, 97 07:37:09 am"
next in thread | previous in thread | raw e-mail | index | archive | help
> As Don Lewis wrote: > > > } We need a remapping tool as well. Anybody here who ever dealt with > > } defect list management? Since we do already know the block number > > } (from the info field in the syslog message), it should be easy to add > > } it to the defect list. > > > > I was reading the SCSI spec and thinking about writing something that > > would at dump out the current defect list, but then my brain started > > hurting too much :-( > > Metoo. This defect list stuff is even worse to understand (from just > reading the specs only) than mode pages. The remapping tool is easy: write anything to the block. Here is an sector slipper I wrote in C once, however, it may fail also if it can't recover the data - I don't have time to check the spec right now. I also put together a defect list dumper for Satoshi when he was having some problems, so I'm putting that here too. Caveat emptor. # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # slipsec.c # dump-defects.c # defect # echo x - slipsec.c sed 's/^X//' >slipsec.c << 'END-of-slipsec.c' X/* slipsec: Slip a sector using "reallocate block". X */ X#include <stdlib.h> X#include <sys/scsiio.h> X#include <errno.h> X#include <sys/file.h> X X#include <scsi.h> X Xint main(int argc, char *argv[]) X{ X scsireq_t *scsireq; X X int qualifier, type, rmb, modifier, iso, ecma, ansi; X char vendor_id[17], product_id[17], revision[5]; X int lba, len; X int i; X int fid; X u_char *inq_buf = malloc(96), *lbas; X u_long block = 0; X int n; X X if (argc < 3) X { X fprintf(stderr, "Usage: %s device sector1 ... sectorn\n", argv[0]); X exit(-1); X } X X fid = scsi_open(argv[1], O_RDWR); X if (fid == -1) X { X perror(argv[1]); X exit(errno); X } X X scsireq = scsireq_build(scsireq_new(), X 96, inq_buf, SCCMD_READ, X "12 0 0 0 v 0", 96); X X if (scsireq_enter(fid, scsireq) == -1) X { X scsi_debug(stderr, -1, scsireq); X exit(errno); X } X X scsireq_decode(scsireq, "b3 b5 b1 b7 b2 b3 b3 s8 z16 z16 z4", X &qualifier, &type, &rmb, &modifier, &iso, &ecma, &ansi, X vendor_id, product_id, revision); X X printf("%s %s %s\n", vendor_id, product_id, revision); X if (type != 0) X { X printf("This is not a direct access device.\n"); X exit(0); X } X X switch(ansi) X { X case 0: X printf("WARNING: This device might not comply to any standard.\n"); X break; X X case 1: X printf("This is a SCSI-1 device.\n"); X break; X X case 2: X printf("This is a SCSI-2 device.\n"); X break; X } X X /* How many blocks? X */ X if (scsireq_enter(fid, scsireq_build(scsireq, X 8, inq_buf, SCCMD_READ, X "25 0 0 0 0 0 0 0 0 0")) == -1) /* Read capacity */ X { X scsi_debug(stderr, -1, scsireq); X exit(errno); X } X X scsireq_decode(scsireq, "i4 i4", &lba, &len); X X printf("The device has %d %d byte blocks.\n", lba, len); X fflush(stdout); X X /* Verify all blocks seem reasonable first: X */ X for (i = 2; i < argc; i++) X { X if ((block = strtoul(argv[i], 0, 0)) > lba) X { X fprintf(stderr, X "Block at %ld outside of maximum %d.\n", block, lba); X exit(-1); X } X } X X n = i - 2; X len = 4 + 4 * n; X if ( (lbas = malloc(len)) == 0 ) X { X perror("malloc"); X exit(errno); X } X X (void)scsireq_build(scsireq, X len, lbas, SCCMD_WRITE, X "07 0 0 0 0 0"); X X scsireq_encode(scsireq, "0 0 v:i2 ", 4 * n); X X for (i = 0; i < n; i++) X scsireq_encode(scsireq, "sv v:i4 ", 4 + 4 * i, strtoul(argv[i + 2], 0, 0)); X X if (scsireq_enter(fid, scsireq) == -1) X { X perror("scsireq_enter"); X exit(errno); X } X X /* Did we get sense? X */ X if (scsireq->senselen_used) X { X int valid, code, key, info, asc, ascq; X X scsireq_buff_decode(scsireq->sense, scsireq->senselen_used, X "b1 b7 *i1 *b4 b4 i4 s12 i1 i1", &valid, &code, X &key, &info, &asc, &ascq); X X printf("Block %lx: valid %d code %02x sense key %02x info %x asc %02x ascq %02x\n", X block, valid, code, key, info, asc, ascq); X fflush(stdout); X } X X exit(0); X} END-of-slipsec.c echo x - dump-defects.c sed 's/^X//' >dump-defects.c << 'END-of-dump-defects.c' X#include <sys/types.h> X#include <stdio.h> Xint main(int ac, char *av[]) X{ X struct header { X u_char stuff[2]; X u_char length[2]; X } h; X X struct physical_sector { X u_char cyl[3]; X u_char head; X u_char sec[4]; X } p; X X if (fread(&h, sizeof(h), 1, stdin) == 1) X while (fread(&p, sizeof(p), 1, stdin) == 1) X printf("%d %d %d\n", (p.cyl[0] << 16) | (p.cyl[1] << 8) | p.cyl[2], X p.head, X (p.sec[0] << 24) | (p.sec[1] << 16) | (p.sec[2] << 8) | p.sec[3]); X} END-of-dump-defects.c echo x - defect sed 's/^X//' >defect << 'END-of-defect' X#!/bin/sh Xusage() X{ X echo "usage: defect raw-device-name" 1>&2 X exit 2 X} X X# Get the grown defect length: X Xif [ $# -ne 1 ] ; then X usage Xfi X XCTL=$1 XBASE=$CTL X X# X# Select what you want to read. PList include the primary defect list X# from the factory. GList is grown defects only. X# X XGList=1 XPList=0 X Xif [ "x$CTL" = "x" ] ; then X usage Xfi X Xif expr "$CTL" : 'sd[0-9][0-9]*$' > /dev/null ; then X # generic disk name given, convert to control device name X CTL="/dev/r${CTL}.ctl" Xfi X Xlength=`scsi -f ${CTL} \ X-c "{ Op code} 37 0 0:3 v:1 v:1 5:3 0 0 0 0 4:i2 0" $PList $GList \ X-i 4 "{ stuff } *i2 { Defect list length } i2"` X Xecho "There are" `expr $length / 8` defects X X# Adjust for the header: Xlength=`expr $length + 4` X X# Read the defects and store to disk X Xscsi -f ${CTL} \ X-c "{ Op code} 37 0 0:3 v:1 v:1 5:3 0 0 0 0 v:i2 0" $PList $GList $length \ X-i $length - > /tmp/defects.$BASE X Xecho "Defects in /tmp/defects.$BASE" X X# They are in the physical sector format. The format (assume packing) is: X# struct physical_sector { X# u_short cylinder; X# u_char head; X# u_long sector; X# }; X# X# Note that they are bigendian! You'll have to use ntohl or something. X# END-of-defect exit
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702011808.NAA16376>