Centralized interpretation of SCSI command outcome

This commit is contained in:
Thomas Schmitt 2010-09-14 12:50:06 +00:00
parent 4cc524097b
commit c1f4063193
7 changed files with 198 additions and 38 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2010.08.21.095456" #define Cdrskin_timestamP "2010.09.14.124934"

View File

@ -759,13 +759,17 @@ int sg_release(struct burn_drive *d)
int sg_issue_command(struct burn_drive *d, struct command *c) int sg_issue_command(struct burn_drive *d, struct command *c)
{ {
int done = 0, err, sense_len = 0, ret, ignore_error, no_retry = 0; int done = 0, err, sense_len = 0, ret, ignore_error, no_retry = 0, i;
int cam_pass_err_recover = 0, key, asc, ascq; int cam_pass_err_recover = 0, key, asc, ascq, timeout_ms;
union ccb *ccb; union ccb *ccb;
char buf[161]; char buf[161];
static FILE *fp = NULL; static FILE *fp = NULL;
time_t start_time;
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d", #define Libburn_use_scsi_eval_cmd_outcomE yes
snprintf(buf, sizeof (buf),
"sg_issue_command d->cam=%p d->released=%d",
(void*)d->cam, d->released); (void*)d->cam, d->released);
mmc_function_spy(NULL, buf); mmc_function_spy(NULL, buf);
@ -854,7 +858,9 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
ccb->csio.dxfer_len = 0; ccb->csio.dxfer_len = 0;
} }
do { start_time = time(NULL);
timeout_ms = 200000;
for (i = 0; !done; i++) {
memset(c->sense, 0, sizeof(c->sense)); memset(c->sense, 0, sizeof(c->sense));
err = cam_send_ccb(d->cam, ccb); err = cam_send_ccb(d->cam, ccb);
@ -954,6 +960,17 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
c->sense[13] = 0x00; c->sense[13] = 0x00;
no_retry = 1; no_retry = 1;
} }
#ifdef Libburn_use_scsi_eval_cmd_outcomE
done = scsi_eval_cmd_outcome(d, c, fp, c->sense,
sense_len, 0, start_time,
timeout_ms, i,
2 | !!ignore_error);
#else /* Libburn_use_scsi_eval_cmd_outcomE */
if (no_retry || ignore_error || !c->retry) { if (no_retry || ignore_error || !c->retry) {
c->error = 1; c->error = 1;
{ret = 1; goto ex;} {ret = 1; goto ex;}
@ -983,12 +1000,18 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
0, 1 | 2); 0, 1 | 2);
{ret = 1; goto ex;} {ret = 1; goto ex;}
} }
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
} else { } else {
done = 1; done = 1;
} }
} while (!done); } while (!done);
ret = 1; ret = 1;
ex:; ex:;
#ifndef Libburn_use_scsi_eval_cmd_outcomE
if (c->error) if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0); scsi_notify_error(d, c, c->sense, 18, 0);
@ -997,6 +1020,8 @@ ex:;
scsi_log_err(c, fp, c->sense, sense_len > 0 ? sense_len : 18, scsi_log_err(c, fp, c->sense, sense_len > 0 ? sense_len : 18,
0, (c->error != 0) | 2); 0, (c->error != 0) | 2);
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
cam_freeccb(ccb); cam_freeccb(ccb);
return ret; return ret;
} }

View File

@ -586,6 +586,9 @@ int sg_release(struct burn_drive *d)
} }
#define Libburn_use_scsi_eval_cmd_outcomE yes
/** 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.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
@ -597,8 +600,8 @@ int sg_release(struct burn_drive *d)
*/ */
int sg_issue_command(struct burn_drive *d, struct command *c) int sg_issue_command(struct burn_drive *d, struct command *c)
{ {
int sense_valid = 0, i, usleep_time, timeout_ms, no_retry = 0; int sense_valid = 0, i, timeout_ms, no_retry = 0;
int key = 0, asc = 0, ascq = 0; int key = 0, asc = 0, ascq = 0, done = 0;
time_t start_time; time_t start_time;
driver_return_code_t i_status; driver_return_code_t i_status;
unsigned int dxfer_len; unsigned int dxfer_len;
@ -608,6 +611,10 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
CdIo_t *p_cdio; CdIo_t *p_cdio;
unsigned char *sense_pt = NULL; unsigned char *sense_pt = NULL;
#ifndef Libburn_use_scsi_eval_cmd_outcomE
int usleep_time;
#endif
c->error = 0; c->error = 0;
if (d->p_cdio == NULL) { if (d->p_cdio == NULL) {
return 0; return 0;
@ -643,7 +650,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
/* retry-loop */ /* retry-loop */
start_time = time(NULL); start_time = time(NULL);
timeout_ms = 200000; timeout_ms = 200000;
for(i = 0; ; i++) { for(i = 0; !done; i++) {
i_status = mmc_run_cmd(p_cdio, timeout_ms, &cdb, e_direction, i_status = mmc_run_cmd(p_cdio, timeout_ms, &cdb, e_direction,
dxfer_len, c->page->data); dxfer_len, c->page->data);
@ -688,6 +695,14 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
} }
} }
if (i_status != 0 || (key || asc || ascq)) { if (i_status != 0 || (key || asc || ascq)) {
#ifdef Libburn_use_scsi_eval_cmd_outcomE
done = scsi_eval_cmd_outcome(d, c, fp, c->sense, 18,
0, start_time, timeout_ms, i, 2);
#else /* Libburn_use_scsi_eval_cmd_outcomE */
if (no_retry || !c->retry) { if (no_retry || !c->retry) {
c->error = 1; c->error = 1;
goto ex; goto ex;
@ -724,17 +739,24 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
goto ex; goto ex;
} }
usleep(usleep_time); usleep(usleep_time);
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
} else } else
break; /* retry-loop */ done = 1;
} /* end of retry-loop */ } /* end of retry-loop */
#ifndef Libburn_use_scsi_eval_cmd_outcomE
ex:; ex:;
if (c->error) if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0); scsi_notify_error(d, c, c->sense, 18, 0);
if (burn_sg_log_scsi & 3) if (burn_sg_log_scsi & 3)
/* >>> Need own duration time measurement. Then remove bit1 */ /* >>> Need own duration time measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 18, 0, (c->error != 0) | 2); scsi_log_err(c, fp, c->sense, 18, 0, (c->error != 0) | 2);
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
return 1; return 1;
} }

View File

@ -1782,13 +1782,19 @@ int sg_release(struct burn_drive *d)
*/ */
int sg_issue_command(struct burn_drive *d, struct command *c) int sg_issue_command(struct burn_drive *d, struct command *c)
{ {
int done = 0, no_c_page = 0, usleep_time, i; int done = 0, no_c_page = 0, i;
int err; int err;
time_t start_time; time_t start_time;
sg_io_hdr_t s; sg_io_hdr_t s;
/* ts A61030 */ /* ts A61030 */
static FILE *fp= NULL; static FILE *fp= NULL;
#define Libburn_use_scsi_eval_cmd_outcomE yes
#ifndef Libburn_use_scsi_eval_cmd_outcomE
int usleep_time;
#endif
/* <<< ts A60821 /* <<< ts A60821
debug: for tracing calls which might use open drive fds */ debug: for tracing calls which might use open drive fds */
char buf[161]; char buf[161];
@ -1910,6 +1916,14 @@ if(0){
/* <<< */ /* <<< */
#endif /* NIX */ #endif /* NIX */
#ifdef Libburn_use_scsi_eval_cmd_outcomE
done = scsi_eval_cmd_outcome(d, c, fp, s.sbp, s.sb_len_wr,
s.duration, start_time, s.timeout, i, 0);
#else /* Libburn_use_scsi_eval_cmd_outcomE */
if (s.sb_len_wr) { if (s.sb_len_wr) {
if (!c->retry) { if (!c->retry) {
c->error = 1; c->error = 1;
@ -1951,14 +1965,28 @@ if(0){
} else { } else {
done = 1; done = 1;
} }
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
} }
/* ts A61106 */ /* ts A61106 */
#ifdef Libburn_use_scsi_eval_cmd_outcomE
if (s.host_status != Libburn_sg_host_oK ||
(s.driver_status != Libburn_sg_driver_oK && !c->error)) {
#else /* Libburn_use_scsi_eval_cmd_outcomE */
ex:; ex:;
if (c->error) { if (c->error) {
scsi_notify_error(d, c, s.sbp, s.sb_len_wr, 0); scsi_notify_error(d, c, s.sbp, s.sb_len_wr, 0);
} else if (s.host_status != Libburn_sg_host_oK || } else if (s.host_status != Libburn_sg_host_oK ||
s.driver_status != Libburn_sg_driver_oK) { s.driver_status != Libburn_sg_driver_oK) {
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
char msg[161]; char msg[161];
sprintf(msg, sprintf(msg,
@ -1973,9 +2001,13 @@ ex:;
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0); msg, 0, 0);
} }
#ifndef Libburn_use_scsi_eval_cmd_outcomE
if (burn_sg_log_scsi & 3) if (burn_sg_log_scsi & 3)
scsi_log_err(c, fp, s.sbp, s.sb_len_wr, scsi_log_err(c, fp, s.sbp, s.sb_len_wr,
s.duration, c->error != 0); s.duration, c->error != 0);
#endif
return 1; return 1;
} }

View File

@ -565,12 +565,17 @@ int sg_release(struct burn_drive *d)
*/ */
int sg_issue_command(struct burn_drive *d, struct command *c) int sg_issue_command(struct burn_drive *d, struct command *c)
{ {
int i, usleep_time, timeout_ms, no_retry = 0, ret, key, asc, ascq; int i, timeout_ms, ret, key, asc, ascq, done = 0;
time_t start_time; time_t start_time;
struct uscsi_cmd cgc; struct uscsi_cmd cgc;
char msg[80]; char msg[80];
static FILE *fp = NULL; static FILE *fp = NULL;
#define Libburn_use_scsi_eval_cmd_outcomE yes
#ifndef Libburn_use_scsi_eval_cmd_outcomE
int usleep_time, no_retry = 0;
#endif
c->error = 0; c->error = 0;
memset(c->sense, 0, sizeof(c->sense)); memset(c->sense, 0, sizeof(c->sense));
if (d->fd == -1) if (d->fd == -1)
@ -616,7 +621,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
/* retry-loop */ /* retry-loop */
start_time = time(NULL); start_time = time(NULL);
timeout_ms = 200000; timeout_ms = 200000;
for(i = 0; ; i++) { for(i = 0; !done; i++) {
ret = ioctl(d->fd, USCSICMD, &cgc); ret = ioctl(d->fd, USCSICMD, &cgc);
@ -639,6 +644,25 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
return -1; return -1;
} }
#ifdef Libburn_use_scsi_eval_cmd_outcomE
/* >>> Should replace "18" by realistic sense length.
What's about following older remark ?
*/
/* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */;
spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
if (key || asc || ascq) {
done = scsi_eval_cmd_outcome(d, c, fp, c->sense, 18, 0,
start_time, timeout_ms, i, 2);
} else
done = 1;
#else /* Libburn_use_scsi_eval_cmd_outcomE */
/* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */; /* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */;
spc_decode_sense(c->sense, 0, &key, &asc, &ascq); spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
@ -681,15 +705,24 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
usleep(usleep_time); usleep(usleep_time);
} else } else
break; /* retry-loop */ break; /* retry-loop */
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
} /* end of retry-loop */ } /* end of retry-loop */
#ifndef Libburn_use_scsi_eval_cmd_outcomE
ex:; ex:;
if (c->error) if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0); scsi_notify_error(d, c, c->sense, 18, 0);
if (burn_sg_log_scsi & 3) if (burn_sg_log_scsi & 3)
/* >>> Need own duration time measurement. Then remove bit1 */ /* >>> Need own duration time measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 18, 0, (c->error != 0) | 2); scsi_log_err(c, fp, c->sense, 18, 0, (c->error != 0) | 2);
#endif /* ! Libburn_use_scsi_eval_cmd_outcomE */
return 1; return 1;
} }

View File

@ -1408,28 +1408,10 @@ int scsi_notify_error(struct burn_drive *d, struct command *c,
sprintf(msg, "SCSI error condition on command %2.2Xh %s: ", sprintf(msg, "SCSI error condition on command %2.2Xh %s: ",
c->opcode[0], c->opcode[0],
scsi_command_name((unsigned int) c->opcode[0], 0)); scsi_command_name((unsigned int) c->opcode[0], 0));
#ifdef NIX
if (key>=0)
sprintf(msg+strlen(msg), " key=%Xh", key);
if (asc>=0)
sprintf(msg+strlen(msg), " asc=%2.2Xh", asc);
if (ascq>=0)
sprintf(msg+strlen(msg), " ascq=%2.2Xh", ascq);
ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0);
if (ret < 0)
return ret;
ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
scsi_msg,0,0);
#else
strcat(msg, scsi_msg); strcat(msg, scsi_msg);
ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f, ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0);
#endif /* NIX */
return ret; return ret;
} }
@ -1530,13 +1512,6 @@ int scsi_log_err(struct command *c, void *fp_in, unsigned char sense[18],
if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) { if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
if (flag & 1) { if (flag & 1) {
durtxt[0] = 0;
if (!(flag & 2))
sprintf(durtxt, " (%6d ms)", duration);
spc_decode_sense(sense, 0, &key, &asc, &ascq);
fprintf(fp, "+++ key=%X asc=%2.2Xh ascq=%2.2Xh%s\n",
(unsigned int) key, (unsigned int) asc,
(unsigned int) ascq, durtxt);
l = 18; l = 18;
if ((sense[0] & 0x7f) == 0x72 || if ((sense[0] & 0x7f) == 0x72 ||
(sense[0] & 0x7f) == 0x73) (sense[0] & 0x7f) == 0x73)
@ -1547,6 +1522,13 @@ int scsi_log_err(struct command *c, void *fp_in, unsigned char sense[18],
for (i = 0 ; i < l; i++) for (i = 0 ; i < l; i++)
fprintf(fp, " %2.2X", sense[i]); fprintf(fp, " %2.2X", sense[i]);
fprintf(fp, "\n"); fprintf(fp, "\n");
durtxt[0] = 0;
if (!(flag & 2))
sprintf(durtxt, " (%6d ms)", duration);
spc_decode_sense(sense, 0, &key, &asc, &ascq);
fprintf(fp, "+++ key=%X asc=%2.2Xh ascq=%2.2Xh%s\n",
(unsigned int) key, (unsigned int) asc,
(unsigned int) ascq, durtxt);
} else { } else {
scsi_show_cmd_reply(c, fp, 0); scsi_show_cmd_reply(c, fp, 0);
if (!(flag & 2)) if (!(flag & 2))
@ -1561,3 +1543,51 @@ int scsi_log_err(struct command *c, void *fp_in, unsigned char sense[18],
return 1; return 1;
} }
/* ts B00808 */
/*
@param flag bit0 = do not retry
bit1 = do not print duration
@return 0 = not yet done , 1 = done , -1 = error
*/
int scsi_eval_cmd_outcome(struct burn_drive *d, struct command *c, void *fp,
unsigned char *sense, int sense_len,
int duration, time_t start_time, int timeout_ms,
int loop_count, int flag)
{
enum response outcome;
int done = -1, usleep_time;
if (sense_len <= 0)
return 1;
if (burn_sg_log_scsi & 3)
scsi_log_err(c, fp, sense, sense_len, duration,
1 | (flag & 2));
outcome = scsi_error(d, sense, sense_len);
if (outcome == RETRY && c->retry && !(flag & 1)) {
/* Calming down retries and breaking up endless cycle
*/
usleep_time = Libburn_scsi_retry_usleeP +
loop_count * Libburn_scsi_retry_incR;
if (time(NULL) + usleep_time / 1000000 - start_time >
timeout_ms / 1000 + 1) {
done = 1;
goto ex;
}
usleep(usleep_time);
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c, fp, 0);
return 0;
} else if (outcome == RETRY) {
done = 1;
} else if (outcome == GO_ON) {
return 1;
} else if (outcome == FAIL) {
done = 1;
}
ex:;
c->error = 1;
scsi_notify_error(d, c, sense, sense_len, 0);
return done;
}

View File

@ -84,5 +84,23 @@ int scsi_log_err(struct command *c, void *fp, unsigned char sense[18],
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);
/* ts B00808 */
/** Evaluates outcome of a single SCSI command, eventually logs sense data,
and issues DEBUG error message in case the command is evaluated as done.
@param flag bit1 = do not print duration
@return 0 = not yet done , 1 = done , -1 = error
*/
int scsi_eval_cmd_outcome(struct burn_drive *d, struct command *c, void *fp_in,
unsigned char *sense, int sense_len,
int duration, time_t start_time, int timeout_ms,
int loop_count, int flag);
/* The waiting time before eventually retrying a failed SCSI command.
Before each retry wait Libburn_scsi_retry_incR longer than with
the previous one.
*/
#define Libburn_scsi_retry_usleeP 100000
#define Libburn_scsi_retry_incR 100000
#endif /*__SPC*/ #endif /*__SPC*/