diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 4fea97e8f..4ddfc4bb7 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -302,7 +302,7 @@ void cmnd_done(struct iscsi_cmnd *cmnd) case ISCSI_CMD_STATE_PROCESSED: TRACE_DBG("cmd %p PROCESSED", cmnd); scst_tgt_cmd_done(cmnd->scst_cmd, - SCST_CONTEXT_DIRECT); + SCST_CONTEXT_DIRECT_ATOMIC); break; case ISCSI_CMD_STATE_AFTER_PREPROC: diff --git a/scst/include/scst.h b/scst/include/scst.h index 096ce5e05..8234ba9cf 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -539,7 +539,7 @@ enum scst_cdb_flags { SCST_SKIP_UA = 0x080, SCST_WRITE_MEDIUM = 0x100, SCST_LOCAL_CMD = 0x200, - SCST_LOCAL_EXEC_NEEDED = 0x400, + SCST_FULLY_LOCAL_CMD = 0x400, }; /* @@ -2382,8 +2382,17 @@ enum dma_data_direction scst_to_dma_dir(int scst_dir); enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir); /* - * Returns true, if cmd's CDB is locally handled by SCST and 0 otherwise. - * Dev handlers parse() and dev_done() not called for such commands. + * Returns true, if cmd's CDB is fully locally handled by SCST and false + * otherwise. Dev handlers parse() and dev_done() not called for such commands. + */ +static inline bool scst_is_cmd_fully_local(struct scst_cmd *cmd) +{ + return (cmd->op_flags & SCST_FULLY_LOCAL_CMD) != 0; +} + +/* + * Returns true, if cmd's CDB is locally handled by SCST and + * false otherwise. */ static inline bool scst_is_cmd_local(struct scst_cmd *cmd) { diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 62f0d77e6..8b77139b0 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -671,7 +671,7 @@ static int dev_user_alloc_space(struct scst_user_cmd *ucmd) goto out; } - if ((cmd->data_direction != SCST_DATA_WRITE) && + if (!(cmd->data_direction & SCST_DATA_WRITE) && !scst_is_cmd_local(cmd)) { TRACE_DBG("Delayed alloc, ucmd %p", ucmd); goto out; diff --git a/scst/src/scst_cdbprobe.h b/scst/src/scst_cdbprobe.h index 39034c13c..eae710341 100644 --- a/scst/src/scst_cdbprobe.h +++ b/scst/src/scst_cdbprobe.h @@ -122,7 +122,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x02, "VVVVVV V ", "REQUEST BLOCK ADDR", SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, {0x03, "MMMMMMMMMMMMMMMM", "REQUEST SENSE", - SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_EXEC_NEEDED, + SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_CMD, 4, get_trans_len_1}, {0x04, "M O O ", "FORMAT UNIT", SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH|SCST_WRITE_MEDIUM, @@ -190,12 +190,12 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x14, "VOOVVV ", "RECOVER BUFFERED DATA", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3}, {0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)", - SCST_DATA_WRITE, SCST_LOCAL_EXEC_NEEDED, 4, get_trans_len_1}, + SCST_DATA_WRITE, SCST_LOCAL_CMD, 4, get_trans_len_1}, {0x16, "MMMMMMMMMMMMMMMM", "RESERVE", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD, 0, get_trans_len_none}, {0x17, "MMMMMMMMMMMMMMMM", "RELEASE", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD, 0, get_trans_len_none}, {0x18, "OOOOOOOO ", "COPY", SCST_DATA_WRITE, SCST_LONG_TIMEOUT, 2, get_trans_len_3}, @@ -352,12 +352,12 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x54, " O ", "SEND OPC INFORMATION", SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2}, {0x55, "OOOOOOOOOOOOOOOO", "MODE SELECT(10)", - SCST_DATA_WRITE, SCST_LOCAL_EXEC_NEEDED, 7, get_trans_len_2}, + SCST_DATA_WRITE, SCST_LOCAL_CMD, 7, get_trans_len_2}, {0x56, "OOOOOOOOOOOOOOOO", "RESERVE(10)", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD, 0, get_trans_len_none}, {0x57, "OOOOOOOOOOOOOOOO", "RELEASE(10)", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD, 0, get_trans_len_none}, {0x58, " O ", "REPAIR TRACK", SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, @@ -431,7 +431,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = { /* 12-bytes length CDB */ {0xA0, "VVVVVVVVVV M ", "REPORT LUNS", SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA| - SCST_LOCAL_CMD|SCST_LOCAL_EXEC_NEEDED, + SCST_FULLY_LOCAL_CMD|SCST_LOCAL_CMD, 6, get_trans_len_4}, {0xA1, " O ", "BLANK", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 339beece3..0e70224d9 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -480,7 +480,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd) TRACE_ENTRY(); - if (likely(!scst_is_cmd_local(cmd))) { + if (likely(!scst_is_cmd_fully_local(cmd))) { if (unlikely(!dev->handler->parse_atomic && scst_cmd_atomic(cmd))) { /* @@ -1603,12 +1603,13 @@ static int scst_request_sense_local(struct scst_cmd *cmd) scst_put_buf(cmd, buffer); -out_compl: tgt_dev->tgt_dev_valid_sense_len = 0; - scst_set_resp_data_len(cmd, sl); spin_unlock_bh(&tgt_dev->tgt_dev_lock); + scst_set_resp_data_len(cmd, sl); + +out_compl: cmd->completed = 1; out_done: @@ -1620,6 +1621,7 @@ out: return res; out_hw_err: + spin_unlock_bh(&tgt_dev->tgt_dev_lock); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); goto out_compl; @@ -2133,12 +2135,7 @@ static int scst_do_local_exec(struct scst_cmd *cmd) goto out_done; } - /* - * Adding new commands here don't forget to update - * scst_is_cmd_local() in scst.h, if necessary - */ - - if (!(cmd->op_flags & SCST_LOCAL_EXEC_NEEDED)) { + if (!scst_is_cmd_local(cmd)) { res = SCST_EXEC_NOT_COMPLETED; goto out; } @@ -2745,7 +2742,7 @@ static int scst_dev_done(struct scst_cmd *cmd) state = SCST_CMD_STATE_PRE_XMIT_RESP; - if (likely(!scst_is_cmd_local(cmd)) && + if (likely(!scst_is_cmd_fully_local(cmd)) && likely(dev->handler->dev_done != NULL)) { int rc; @@ -3503,6 +3500,8 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) TRACE_ENTRY(); EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled()); + EXTRACHECKS_WARN_ON((in_atomic() || in_interrupt() || irqs_disabled()) && + !atomic); cmd->atomic = atomic;