diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2008-06-02 04:30:22 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2008-06-02 04:30:22 +0000 |
commit | 9142d9b9540cd02b22b38c3cdb0d4759b920ee4e (patch) | |
tree | 5eb11d45840702147c5111561f0bb4228e251a87 /src/sg_dd.c | |
parent | c1ed9f408928a54378eb8360a96eb10e1528ac0c (diff) | |
download | sg3_utils-9142d9b9540cd02b22b38c3cdb0d4759b920ee4e.tar.gz |
widen coe processing to medium and hard errors that don't report bad lba
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@175 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src/sg_dd.c')
-rw-r--r-- | src/sg_dd.c | 119 |
1 files changed, 80 insertions, 39 deletions
diff --git a/src/sg_dd.c b/src/sg_dd.c index 3747888d..df10b4c7 100644 --- a/src/sg_dd.c +++ b/src/sg_dd.c @@ -57,7 +57,7 @@ This version is designed for the linux kernel 2.4 and 2.6 series. */ -static char * version_str = "5.66 20080130"; +static char * version_str = "5.67 20080530"; #define ME "sg_dd: " @@ -163,7 +163,9 @@ static struct flags_t oflag; static void calc_duration_throughput(int contin); -static void install_handler(int sig_num, void (*sig_handler) (int sig)) + +static void +install_handler(int sig_num, void (*sig_handler) (int sig)) { struct sigaction sigact; sigaction (sig_num, NULL, &sigact); @@ -176,7 +178,9 @@ static void install_handler(int sig_num, void (*sig_handler) (int sig)) } } -static void print_stats(const char * str) + +static void +print_stats(const char * str) { if (0 != dd_count) fprintf(stderr, " remaining block count=%"PRId64"\n", dd_count); @@ -199,7 +203,9 @@ static void print_stats(const char * str) unrecovered_errs); } -static void interrupt_handler(int sig) + +static void +interrupt_handler(int sig) { struct sigaction sigact; @@ -214,7 +220,9 @@ static void interrupt_handler(int sig) kill(getpid (), sig); } -static void siginfo_handler(int sig) + +static void +siginfo_handler(int sig) { sig = sig; /* dummy to stop -W warning messages */ fprintf(stderr, "Progress report, continuing ...\n"); @@ -223,7 +231,9 @@ static void siginfo_handler(int sig) print_stats(" "); } -static int dd_filetype(const char * filename) + +static int +dd_filetype(const char * filename) { struct stat st; size_t len = strlen(filename); @@ -247,7 +257,9 @@ static int dd_filetype(const char * filename) return FT_OTHER; } -static char * dd_filetype_str(int ft, char * buff) + +static char * +dd_filetype_str(int ft, char * buff) { int off = 0; @@ -268,7 +280,9 @@ static char * dd_filetype_str(int ft, char * buff) return buff; } -static void usage() + +static void +usage() { fprintf(stderr, "Usage: " "sg_dd [bs=BS] [count=COUNT] [ibs=BS] [if=IFILE]" @@ -332,8 +346,10 @@ static void usage() "specialized for SCSI devices\n"); } + /* Return of 0 -> success, see sg_ll_read_capacity*() otherwise */ -static int scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz) +static int +scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz) { int k, res; unsigned int ui; @@ -374,10 +390,11 @@ static int scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz) return 0; } + /* Return of 0 -> success, -1 -> failure. BLKGETSIZE64, BLKGETSIZE and */ /* BLKSSZGET macros problematic (from <linux/fs.h> or <sys/mount.h>). */ -static int read_blkdev_capacity(int sg_fd, int64_t * num_sect, - int * sect_sz) +static int +read_blkdev_capacity(int sg_fd, int64_t * num_sect, int * sect_sz) { #ifdef BLKSSZGET if ((ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) && (*sect_sz > 0)) { @@ -419,9 +436,10 @@ static int read_blkdev_capacity(int sg_fd, int64_t * num_sect, #endif } -static int sg_build_scsi_cdb(unsigned char * cdbp, int cdb_sz, - unsigned int blocks, int64_t start_block, - int write_true, int fua, int dpo) + +static int +sg_build_scsi_cdb(unsigned char * cdbp, int cdb_sz, unsigned int blocks, + int64_t start_block, int write_true, int fua, int dpo) { int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88}; int wr_opcode[] = {0xa, 0x2a, 0xaa, 0x8a}; @@ -511,6 +529,7 @@ static int sg_build_scsi_cdb(unsigned char * cdbp, int cdb_sz, return 0; } + /* 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, SG_LIB_CAT_UNIT_ATTENTION -> try again, SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> 'io_addrp' written to, @@ -518,10 +537,10 @@ static int sg_build_scsi_cdb(unsigned char * cdbp, int cdb_sz, SG_LIB_CAT_NOT_READY, SG_LIB_CAT_ABORTED_COMMAND, -2 -> ENOMEM -1 other errors */ -static int sg_read_low(int sg_fd, unsigned char * buff, int blocks, - int64_t from_block, int bs, - const struct flags_t * ifp, int * diop, - uint64_t * io_addrp) +static int +sg_read_low(int sg_fd, unsigned char * buff, int blocks, int64_t from_block, + int bs, const struct flags_t * ifp, int * diop, + uint64_t * io_addrp) { unsigned char rdCmd[MAX_SCSI_CDBSZ]; unsigned char senseBuff[SENSE_BUFF_LEN]; @@ -617,22 +636,26 @@ static int sg_read_low(int sg_fd, unsigned char * buff, int blocks, if (verbose > 1) sg_chk_n_print3("reading", &io_hdr, verbose > 1); if (sg_scsi_normalize_sense(sbp, slen, &ssh) && - (0x64 == ssh.asc) && (0x0 == ssh.ascq) && - (sg_get_sense_filemark_eom_ili(sbp, slen, NULL, NULL, &ili)) - && ili) { - info_valid = sg_get_sense_info_fld(sbp, slen, io_addrp); - if (*io_addrp > 0) { - ++unrecovered_errs; - return SG_LIB_CAT_MEDIUM_HARD_WITH_INFO; - } else - fprintf(stderr, "MMC READ gave 'illegal mode for this " - "track' and ILI but no LBA of failure\n"); + (0x64 == ssh.asc) && (0x0 == ssh.ascq)) { + if (sg_get_sense_filemark_eom_ili(sbp, slen, NULL, NULL, + &ili) && ili) { + info_valid = sg_get_sense_info_fld(sbp, slen, io_addrp); + if (*io_addrp > 0) { + ++unrecovered_errs; + return SG_LIB_CAT_MEDIUM_HARD_WITH_INFO; + } else + fprintf(stderr, "MMC READ gave 'illegal mode for " + "this track' and ILI but no LBA of failure\n"); + } + ++unrecovered_errs; + return SG_LIB_CAT_MEDIUM_HARD; } } /* drop through */ default: ++unrecovered_errs; - sg_chk_n_print3("reading", &io_hdr, verbose > 1); + if (verbose > 0) + sg_chk_n_print3("reading", &io_hdr, verbose > 1); return res; } if (diop && *diop && @@ -642,13 +665,14 @@ static int sg_read_low(int sg_fd, unsigned char * buff, int blocks, return 0; } + /* 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, SG_LIB_CAT_UNIT_ATTENTION -> try again, SG_LIB_CAT_NOT_READY, SG_LIB_CAT_MEDIUM_HARD, SG_LIB_CAT_ABORTED_COMMAND, -2 -> ENOMEM, -1 other errors */ -static int sg_read(int sg_fd, unsigned char * buff, int blocks, - int64_t from_block, int bs, struct flags_t * ifp, - int * diop, int * blks_readp) +static int +sg_read(int sg_fd, unsigned char * buff, int blocks, int64_t from_block, + int bs, struct flags_t * ifp, int * diop, int * blks_readp) { uint64_t io_addr; int64_t lba; @@ -656,12 +680,14 @@ static int sg_read(int sg_fd, unsigned char * buff, int blocks, unsigned char * bp; int retries_tmp; int ret = 0; + int may_coe = 0; retries_tmp = ifp->retries; for (xferred = 0, blks = blocks, lba = from_block, bp = buff; blks > 0; blks = blocks - xferred) { io_addr = 0; repeat = 0; + may_coe = 0; res = sg_read_low(sg_fd, bp, blks, lba, bs, ifp, diop, &io_addr); switch (res) { case 0: @@ -713,6 +739,7 @@ static int sg_read(int sg_fd, unsigned char * buff, int blocks, ret = res; goto err_out; case SG_LIB_CAT_MEDIUM_HARD: + may_coe = 1; default: if (retries_tmp > 0) { fprintf(stderr, ">>> retrying a sgio read, lba=0x%"PRIx64"\n", @@ -735,6 +762,7 @@ static int sg_read(int sg_fd, unsigned char * buff, int blocks, "correct range:\n\t[0x%"PRIx64",0x%"PRIx64"]\n", io_addr, (uint64_t)lba, (uint64_t)(lba + blks - 1)); + may_coe = 1; goto err_out; } blks = (int)(io_addr - (uint64_t)lba); @@ -880,21 +908,29 @@ err_out: memset(bp, 0, bs * blks); fprintf(stderr, ">> unable to read at blk=%"PRId64" for " "%d bytes, use zeros\n", lba, bs * blks); + if (blks > 1) + fprintf(stderr, ">> try reducing bpt to limit number " + "of zeros written near bad block(s)\n"); /* fudge success */ if (blks_readp) *blks_readp = xferred + blks; - return ret; + if ((coe_limit > 0) && (++coe_count > coe_limit)) { + fprintf(stderr, ">> coe_limit on consecutive reads exceeded\n"); + return ret; + } + return may_coe ? 0 : ret; } else return ret ? ret : -1; } + /* 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, SG_LIB_CAT_NOT_READY, SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_MEDIUM_HARD, SG_LIB_CAT_ABORTED_COMMAND, -2 -> recoverable (ENOMEM), -1 -> unrecoverable error + others */ -static int sg_write(int sg_fd, unsigned char * buff, int blocks, - int64_t to_block, int bs, const struct flags_t * ofp, - int * diop) +static int +sg_write(int sg_fd, unsigned char * buff, int blocks, int64_t to_block, + int bs, const struct flags_t * ofp, int * diop) { unsigned char wrCmd[MAX_SCSI_CDBSZ]; unsigned char senseBuff[SENSE_BUFF_LEN]; @@ -984,7 +1020,9 @@ static int sg_write(int sg_fd, unsigned char * buff, int blocks, return 0; } -static void calc_duration_throughput(int contin) + +static void +calc_duration_throughput(int contin) { struct timeval end_tm, res_tm; double a, b; @@ -1012,7 +1050,9 @@ static void calc_duration_throughput(int contin) } } -static int process_flags(const char * arg, struct flags_t * fp) + +static int +process_flags(const char * arg, struct flags_t * fp) { char buff[256]; char * cp; @@ -1061,7 +1101,8 @@ static int process_flags(const char * arg, struct flags_t * fp) } -int main(int argc, char * argv[]) +int +main(int argc, char * argv[]) { int64_t skip = 0; int64_t seek = 0; |