From 656adf2f6476c3675f49959f1519b23cab8c04c5 Mon Sep 17 00:00:00 2001 From: dpgilbert <dpgilbert@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Mon, 3 Dec 2007 02:14:20 +0000 Subject: [PATCH] improve SAT handling of aborted ATA commands git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2438 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- sm5/CHANGELOG | 6 ++- sm5/scsiata.cpp | 118 ++++++++++++++++++++++++----------------------- sm5/scsicmds.cpp | 4 +- 3 files changed, 67 insertions(+), 61 deletions(-) diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 548f2d725..ede81e67b 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.639 2007/11/26 18:11:32 guidog Exp $ +$Id: CHANGELOG,v 1.640 2007/12/03 02:14:20 dpgilbert Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -33,6 +33,10 @@ Maintainers / Developers Key: NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [DG] SAT/SCSI: Improve SAT error processing code. Aborted commands from + ATA devices (typically because SMART was disabled) were not being + properly detected. + [GG] smartd: wait for the pid file to show up, return an error if it doesn't [JH] fix bad return code (get STATUS) for QNX Part diff --git a/sm5/scsiata.cpp b/sm5/scsiata.cpp index 3a838bf47..084dcc91a 100644 --- a/sm5/scsiata.cpp +++ b/sm5/scsiata.cpp @@ -45,13 +45,14 @@ #include "scsiata.h" #include "utility.h" -const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.7 2006/08/09 20:40:19 chrfranke Exp $" +const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.8 2007/12/03 02:14:20 dpgilbert Exp $" CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID; /* for passing global control variables */ extern smartmonctrl *con; #define DEF_SAT_ATA_PASSTHRU_SIZE 16 +#define ATA_RETURN_DESCRIPTOR 9 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85) @@ -89,7 +90,7 @@ extern smartmonctrl *con; // cdb[11]: control (SCSI, leave as zero) // // -// ATA status return descriptor (component of descriptor sense data) +// ATA Return Descriptor (component of descriptor sense data) // des[0]: descriptor code (0x9) // des[1]: additional descriptor length (0xc) // des[2]: extend (bit 0) @@ -135,12 +136,12 @@ int sat_command_interface(int device, smart_command_set command, int select, struct sg_scsi_sense_hdr ssh; unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN]; unsigned char sense[32]; - const unsigned char * ucp; - int status, len; + const unsigned char * ardp; + int status, ard_len, have_sense; int copydata = 0; int outlen = 0; int extend = 0; - int chk_cond = 0; /* set to 1 to read register(s) back */ + int ck_cond = 0; /* set to 1 to read register(s) back */ int protocol = 3; /* non-data */ int t_dir = 1; /* 0 -> to device, 1 -> from device */ int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */ @@ -160,7 +161,7 @@ int sat_command_interface(int device, smart_command_set command, int select, switch (command) { case CHECK_POWER_MODE: ata_command = ATA_CHECK_POWER_MODE; - chk_cond = 1; + ck_cond = 1; copydata = 1; break; case READ_VALUES: /* READ DATA */ @@ -221,7 +222,7 @@ int sat_command_interface(int device, smart_command_set command, int select, // this command only says if SMART is working. It could be // replaced with STATUS_CHECK below. feature = ATA_SMART_STATUS; - chk_cond = 1; + ck_cond = 1; break; case AUTO_OFFLINE: feature = ATA_SMART_AUTO_OFFLINE; @@ -239,7 +240,7 @@ int sat_command_interface(int device, smart_command_set command, int select, // This command uses HDIO_DRIVE_TASK and has different syntax than // the other commands. feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */ - chk_cond = 1; + ck_cond = 1; break; default: pout("Unrecognized command %d in sat_command_interface()\n" @@ -259,7 +260,7 @@ int sat_command_interface(int device, smart_command_set command, int select, SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16; cdb[1] = (protocol << 1) | extend; - cdb[2] = (chk_cond << 5) | (t_dir << 3) | + cdb[2] = (ck_cond << 5) | (t_dir << 3) | (byte_block << 2) | t_length; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 3 : 4] = feature; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 4 : 6] = sector_count; @@ -295,79 +296,80 @@ int sat_command_interface(int device, smart_command_set command, int select, "status=%d\n", status); return -1; } - if (chk_cond) { /* expecting SAT specific sense data */ - ucp = NULL; - if (sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, - &ssh)) { - /* look for SAT extended ATA status return descriptor (9) */ - ucp = sg_scsi_sense_desc_find(io_hdr.sensep, - io_hdr.resp_sense_len, 9); - if (ucp) { - len = ucp[1] + 2; - if (len < 12) - len = 12; - else if (len > 14) - len = 14; + ardp = NULL; + ard_len = 0; + have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, + &ssh); + if (have_sense) { + /* look for SAT ATA Return Descriptor */ + ardp = sg_scsi_sense_desc_find(io_hdr.sensep, + io_hdr.resp_sense_len, + ATA_RETURN_DESCRIPTOR); + if (ardp) { + ard_len = ardp[1] + 2; + if (ard_len < 12) + ard_len = 12; + else if (ard_len > 14) + ard_len = 14; + } + scsi_do_sense_disect(&io_hdr, &sinfo); + status = scsiSimpleSenseFilter(&sinfo); + if (0 != status) { + if (con->reportscsiioctl > 0) { + pout("sat_command_interface: scsi error: %s\n", + scsiErrString(status)); + if (ardp && (con->reportscsiioctl > 1)) { + pout("Values from ATA Return Descriptor are:\n"); + dStrHex((const char *)ardp, ard_len, 1); + } + } + if (t_dir && (t_length > 0) && (copydata > 0)) + memset(data, 0, copydata); + return -1; + } + } + if (ck_cond) { /* expecting SAT specific sense data */ + if (have_sense) { + if (ardp) { if (con->reportscsiioctl > 1) { - pout("Values from ATA status return descriptor are:\n"); - dStrHex((const char *)ucp, len, 1); + pout("Values from ATA Return Descriptor are:\n"); + dStrHex((const char *)ardp, ard_len, 1); } - if (ATA_CHECK_POWER_MODE == cdb[14]) - data[0] = ucp[5]; /* sector count (0:7) */ + if (ATA_CHECK_POWER_MODE == ata_command) + data[0] = ardp[5]; /* sector count (0:7) */ else if (STATUS_CHECK == command) { - if ((ucp[9] == 0x4f) && (ucp[11] == 0xc2)) + if ((ardp[9] == 0x4f) && (ardp[11] == 0xc2)) return 0; /* GOOD smart status */ - if ((ucp[9] == 0xf4) && (ucp[11] == 0x2c)) + if ((ardp[9] == 0xf4) && (ardp[11] == 0x2c)) return 1; // smart predicting failure, "bad" status // We haven't gotten output that makes sense so // print out some debugging info syserror("Error SMART Status command failed"); pout("Please get assistance from " PACKAGE_HOMEPAGE "\n"); - pout("Values from ATA status return descriptor are:\n"); - dStrHex((const char *)ucp, len, 1); + pout("Values from ATA Return Descriptor are:\n"); + dStrHex((const char *)ardp, ard_len, 1); return -1; } } } - if (ucp == NULL) { - chk_cond = 0; /* not the type of sense data expected */ - if (t_dir && (t_length > 0)) - data[0] = 0; - } + if (ardp == NULL) + ck_cond = 0; /* not the type of sense data expected */ } - if (0 == chk_cond) { - ucp = NULL; - if (sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, - &ssh)) { + if (0 == ck_cond) { + if (have_sense) { if ((ssh.response_code >= 0x72) && ((SCSI_SK_NO_SENSE == ssh.sense_key) || (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) && (0 == ssh.asc) && (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) { - /* look for SAT extended ATA status return descriptor (9) */ - ucp = sg_scsi_sense_desc_find(io_hdr.sensep, - io_hdr.resp_sense_len, 9); - if (ucp) { + if (ardp) { if (con->reportscsiioctl > 0) { - pout("Values from ATA status return descriptor are:\n"); - len = ucp[1] + 2; - if (len < 12) - len = 12; - else if (len > 14) - len = 14; - dStrHex((const char *)ucp, len, 1); + pout("Values from ATA Return Descriptor are:\n"); + dStrHex((const char *)ardp, ard_len, 1); } return -1; } } - scsi_do_sense_disect(&io_hdr, &sinfo); - status = scsiSimpleSenseFilter(&sinfo); - if (0 != status) { - if (con->reportscsiioctl > 0) - pout("sat_command_interface: scsi error: %s\n", - scsiErrString(status)); - return -1; - } } } return 0; diff --git a/sm5/scsicmds.cpp b/sm5/scsicmds.cpp index 9af2012ef..9a3e6c855 100644 --- a/sm5/scsicmds.cpp +++ b/sm5/scsicmds.cpp @@ -47,7 +47,7 @@ #include "scsicmds.h" #include "utility.h" -const char *scsicmds_c_cvsid="$Id: scsicmds.cpp,v 1.94 2007/03/23 03:47:28 dpgilbert Exp $" +const char *scsicmds_c_cvsid="$Id: scsicmds.cpp,v 1.95 2007/12/03 02:14:20 dpgilbert Exp $" CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; /* for passing global control variables */ @@ -233,7 +233,7 @@ const char * scsiErrString(int scsiErr) case SIMPLE_ERR_UNKNOWN: return "unknown error (unexpected sense key)"; case SIMPLE_ERR_ABORTED_COMMAND: - return "aborted command (transport problem?)"; + return "aborted command"; default: return "unknown error"; } -- GitLab