Improved reaction on Linux SG_IO transport problems
This commit is contained in:
parent
ac385002e9
commit
4ba3d10687
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2013.11.11.160915"
|
#define Cdrskin_timestamP "2013.11.14.101636"
|
||||||
|
@ -520,7 +520,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
|
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
|
||||||
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
|
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
|
||||||
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
|
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
|
||||||
0x0002014d (SORRY,HIGH) = Asynchromous SCSI error
|
0x0002014d (SORRY,HIGH) = Asynchronous SCSI error
|
||||||
0x0002014f (SORRY,HIGH) = Timeout with asynchronous SCSI command
|
0x0002014f (SORRY,HIGH) = Timeout with asynchronous SCSI command
|
||||||
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
|
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
|
||||||
0x00020151 (FAILURE,HIGH) = Read attempt on write-only drive
|
0x00020151 (FAILURE,HIGH) = Read attempt on write-only drive
|
||||||
@ -606,6 +606,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x000201a2 (FAILURE,HIGH) = Error while writing to disk file
|
0x000201a2 (FAILURE,HIGH) = Error while writing to disk file
|
||||||
0x000201a3 (UPDATE,HIGH) = Progress message of burn_drive_extract_audio()
|
0x000201a3 (UPDATE,HIGH) = Progress message of burn_drive_extract_audio()
|
||||||
0x000201a4 (FAILURE,HIGH) = Failure to read audio sectors
|
0x000201a4 (FAILURE,HIGH) = Failure to read audio sectors
|
||||||
|
0x000201a5 (FAILURE,HIGH) = Asynchronous SCSI error
|
||||||
|
0x000201a6 (FATAL,HIGH) = Lost connection to drive
|
||||||
|
0x000201a7 (FAILURE,HIGH) = SCSI command yielded host problem
|
||||||
|
0x000201a8 (FAILURE,HIGH) = SCSI command yielded driver problem
|
||||||
|
|
||||||
|
|
||||||
libdax_audioxtr:
|
libdax_audioxtr:
|
||||||
|
@ -1884,6 +1884,167 @@ int sg_release(struct burn_drive *d)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* @return -1= transport failed, give up drive
|
||||||
|
0= transport failed, do not retry
|
||||||
|
1= transport succeeded
|
||||||
|
2- transport failed, please retry
|
||||||
|
*/
|
||||||
|
static int evaluate_transport_success(struct burn_drive *d, struct command *c,
|
||||||
|
FILE *fp,
|
||||||
|
unsigned short host_status,
|
||||||
|
unsigned short driver_status)
|
||||||
|
{
|
||||||
|
int ret, do_retry= 0, give_up_drive= 0;
|
||||||
|
char *msg = NULL, *host_problem, *driver_problem, *driver_sugg;
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(msg, char, 161);
|
||||||
|
|
||||||
|
if ((host_status == Libburn_sg_host_oK &&
|
||||||
|
driver_status == Libburn_sg_driver_oK) || c->error)
|
||||||
|
{ret = 1; goto ex;} /* No transport problems */
|
||||||
|
|
||||||
|
/* See http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html */
|
||||||
|
|
||||||
|
switch(host_status) {
|
||||||
|
case 0x00:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_OK (No error)";
|
||||||
|
break; case 0x01:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_NO_CONNECT (Could not connect before timeout period)";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x02:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_BUS_BUSY (Bus stayed busy through time out period)";
|
||||||
|
break; case 0x03:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_TIME_OUT (Timed out for miscellaneous reasons)";
|
||||||
|
break; case 0x04:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_BAD_TARGET (Bad target, device not responding ?)";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x05:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_ABORT (Told to abort)";
|
||||||
|
break; case 0x06:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_PARITY (Parity error)";
|
||||||
|
break; case 0x07:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_ERROR (Internal error detected in the host adapter)";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x08:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_RESET (The SCSI bus or the device have been reset)";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x09:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_BAD_INTR (Got an unexpected interrupt)";
|
||||||
|
break; case 0x0a:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_PASSTHROUGH (Force command past mid-layer)";
|
||||||
|
break; case 0x0b:
|
||||||
|
host_problem =
|
||||||
|
"SG_ERR_DID_SOFT_ERROR (The low level driver wants a retry)";
|
||||||
|
do_retry = 1;
|
||||||
|
default:
|
||||||
|
host_problem =
|
||||||
|
"? (unknown host_status code)";
|
||||||
|
}
|
||||||
|
if (host_status != Libburn_sg_host_oK) {
|
||||||
|
sprintf(msg, "SCSI command %2.2Xh yielded host problem: ",
|
||||||
|
(unsigned int) c->opcode[0]);
|
||||||
|
sprintf(msg+strlen(msg), "0x%x %s",
|
||||||
|
(unsigned int) host_status, host_problem);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x000201a7,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, 0, 0);
|
||||||
|
sprintf(msg, "--- SG_IO: host_status= 0x%x %s",
|
||||||
|
(unsigned int) host_status, host_problem);
|
||||||
|
scsi_log_message(d, fp, msg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (driver_status & 0x0f) {
|
||||||
|
case 0:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_OK";
|
||||||
|
break; case 1:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_BUSY";
|
||||||
|
break; case 2:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_SOFT";
|
||||||
|
break; case 3:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_MEDIA";
|
||||||
|
break; case 4:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_ERROR";
|
||||||
|
break; case 5:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_INVALID";
|
||||||
|
break; case 6:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_TIMEOUT";
|
||||||
|
break; case 7:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_HARD";
|
||||||
|
break; case 8:
|
||||||
|
driver_problem = "SG_ERR_DRIVER_SENSE";
|
||||||
|
default:
|
||||||
|
driver_problem = "(unknown driver_status code)";
|
||||||
|
}
|
||||||
|
switch (driver_status & 0xf0) {
|
||||||
|
case 0:
|
||||||
|
driver_sugg = "(no suggestion)";
|
||||||
|
break; case 0x10:
|
||||||
|
driver_sugg = "SG_ERR_SUGGEST_RETRY";
|
||||||
|
do_retry = 1;
|
||||||
|
break; case 0x20:
|
||||||
|
driver_sugg = "SG_ERR_SUGGEST_ABORT";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x30:
|
||||||
|
driver_sugg = "SG_ERR_SUGGEST_REMAP";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x40:
|
||||||
|
driver_sugg = "SG_ERR_SUGGEST_DIE";
|
||||||
|
give_up_drive= 1;
|
||||||
|
break; case 0x80:
|
||||||
|
driver_sugg = "SG_ERR_SUGGEST_SENSE";
|
||||||
|
default:
|
||||||
|
driver_sugg = "(unknown driver_status suggestion)";
|
||||||
|
}
|
||||||
|
if (driver_status != Libburn_sg_driver_oK) {
|
||||||
|
sprintf(msg, "SCSI command %2.2Xh yielded driver problem: ",
|
||||||
|
(unsigned int) c->opcode[0]);
|
||||||
|
sprintf(msg+strlen(msg), "driver_status= 0x%x %s / %s",
|
||||||
|
(unsigned int) driver_status,
|
||||||
|
driver_problem, driver_sugg);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x000201a8,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, 0, 0);
|
||||||
|
sprintf(msg, "--- SG_IO: driver_status= 0x%x %s / %s",
|
||||||
|
(unsigned int) driver_status,
|
||||||
|
driver_problem, driver_sugg);
|
||||||
|
scsi_log_message(d, fp, msg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! do_retry)
|
||||||
|
c->error = 1;
|
||||||
|
ret = give_up_drive ? -1 : do_retry ? 2 : 0;
|
||||||
|
ex:;
|
||||||
|
BURN_FREE_MEM(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void react_on_drive_loss(struct burn_drive *d, struct command *c,
|
||||||
|
FILE *fp)
|
||||||
|
{
|
||||||
|
sg_close_drive(d);
|
||||||
|
d->released = 1;
|
||||||
|
d->busy = BURN_DRIVE_IDLE;
|
||||||
|
d->cancel = 1;
|
||||||
|
c->error = 1;
|
||||||
|
libdax_msgs_submit(libdax_messenger,
|
||||||
|
d->global_index, 0x000201a6,
|
||||||
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Lost connection to drive", 0, 0);
|
||||||
|
scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0);
|
||||||
|
}
|
||||||
|
|
||||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||||
the command succeeded or shall be retried or finally failed.
|
the command succeeded or shall be retried or finally failed.
|
||||||
@ -1923,8 +2084,6 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
"\n-----------------------------------------\n");
|
"\n-----------------------------------------\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (burn_sg_log_scsi & 3)
|
|
||||||
scsi_log_cmd(c,fp,0);
|
|
||||||
|
|
||||||
/* ts A61010 : with no fd there is no chance to send an ioctl */
|
/* ts A61010 : with no fd there is no chance to send an ioctl */
|
||||||
if (d->fd < 0) {
|
if (d->fd < 0) {
|
||||||
@ -1932,8 +2091,11 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
{ret = 0; goto ex;}
|
{ret = 0; goto ex;}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
c->error = 0;
|
c->error = 0;
|
||||||
memset(&s, 0, sizeof(sg_io_hdr_t));
|
memset(&s, 0, sizeof(sg_io_hdr_t));
|
||||||
|
if (burn_sg_log_scsi & 3)
|
||||||
|
scsi_log_cmd(c,fp,0);
|
||||||
|
|
||||||
s.interface_id = 'S';
|
s.interface_id = 'S';
|
||||||
|
|
||||||
@ -2012,32 +2174,31 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Failed to transfer command to drive",
|
"Failed to transfer command to drive",
|
||||||
errno, 0);
|
errno, 0);
|
||||||
sg_close_drive(d);
|
sprintf(msg, "--- SG_IO: return= -1 , ");
|
||||||
d->released = 1;
|
sprintf(msg + strlen(msg), "errno= %d , ", errno);
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
sprintf(msg + strlen(msg),
|
||||||
c->error = 1;
|
"host_status= 0x%x , driver_status= 0x%x",
|
||||||
|
(unsigned int) s.host_status,
|
||||||
|
(unsigned int) s.driver_status);
|
||||||
|
scsi_log_message(d, fp, msg, 0);
|
||||||
|
react_on_drive_loss(d, c, fp);
|
||||||
{ret = -1; goto ex;}
|
{ret = -1; goto ex;}
|
||||||
}
|
}
|
||||||
done = scsi_eval_cmd_outcome(d, c, fp, s.sbp, s.sb_len_wr,
|
done = scsi_eval_cmd_outcome(d, c, fp, s.sbp, s.sb_len_wr,
|
||||||
start_time, s.timeout, i, 0);
|
start_time, s.timeout, i, 0);
|
||||||
if (d->cancel)
|
if (d->cancel)
|
||||||
done = 1;
|
break;
|
||||||
|
ret = evaluate_transport_success(d, c, fp,
|
||||||
|
s.host_status, s.driver_status);
|
||||||
|
if (ret == -1)
|
||||||
|
react_on_drive_loss(d, c, fp);
|
||||||
|
if (ret <= 0)
|
||||||
|
{ret = -1; goto ex;}
|
||||||
|
if (ret != 2 || d->cancel)
|
||||||
|
break;
|
||||||
|
/* loop for retry */;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.host_status != Libburn_sg_host_oK ||
|
|
||||||
(s.driver_status != Libburn_sg_driver_oK && !c->error)) {
|
|
||||||
sprintf(msg,
|
|
||||||
"SCSI command %2.2Xh indicates host or driver error:",
|
|
||||||
(unsigned int) c->opcode[0]);
|
|
||||||
sprintf(msg+strlen(msg),
|
|
||||||
" host_status= %xh , driver_status= %xh",
|
|
||||||
(unsigned int) s.host_status,
|
|
||||||
(unsigned int) s.driver_status);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x0002013b,
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
}
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
ex:;
|
ex:;
|
||||||
BURN_FREE_MEM(msg);
|
BURN_FREE_MEM(msg);
|
||||||
|
@ -1747,6 +1747,22 @@ int scsi_log_err(struct burn_drive *d, struct command *c,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ts B31112 */
|
||||||
|
int scsi_log_message(struct burn_drive *d, void *fp_in, char * msg, int flag)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
FILE *fp = fp_in;
|
||||||
|
|
||||||
|
if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
|
||||||
|
fprintf(fp, "%s\n", msg);
|
||||||
|
if (burn_sg_log_scsi & 4)
|
||||||
|
fflush(fp);
|
||||||
|
}
|
||||||
|
if (fp == stderr || !(burn_sg_log_scsi & 2))
|
||||||
|
return 1;
|
||||||
|
ret = scsi_log_message(d, stderr, msg, flag);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* ts B00808 */
|
/* ts B00808 */
|
||||||
/*
|
/*
|
||||||
|
@ -98,6 +98,9 @@ int scsi_log_err(struct burn_drive *d, struct command *c,
|
|||||||
void *fp, unsigned char sense[18],
|
void *fp, unsigned char sense[18],
|
||||||
int sense_len, int flag);
|
int sense_len, int flag);
|
||||||
|
|
||||||
|
/* ts B31112 */
|
||||||
|
int scsi_log_message(struct burn_drive *d, void *fp, char * msg, int flag);
|
||||||
|
|
||||||
/* ts B00728 */
|
/* ts B00728 */
|
||||||
int spc_decode_sense(unsigned char *sense, int senselen,
|
int spc_decode_sense(unsigned char *sense, int senselen,
|
||||||
int *key, int *asc, int *ascq);
|
int *key, int *asc, int *ascq);
|
||||||
|
Loading…
Reference in New Issue
Block a user