From b9d4a45cca9796e3cd57f7368afda5260634df6d Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 9 Mar 2010 11:13:50 +0000 Subject: [PATCH] This patch allows for SCST_USER_PARSE to return status and abort commands execution on the parse stage. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1536 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst_user.h | 21 ++++++++++++------ scst/src/dev_handlers/scst_user.c | 36 ++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/scst/include/scst_user.h b/scst/include/scst_user.h index 2c59372d1..39fccdbfc 100644 --- a/scst/include/scst_user.h +++ b/scst/include/scst_user.h @@ -211,12 +211,21 @@ struct scst_user_get_cmd { /* Be careful adding new members here, this structure is allocated on stack! */ struct scst_user_scsi_cmd_reply_parse { - uint8_t queue_type; - uint8_t data_direction; - int16_t cdb_len; - uint32_t op_flags; - int32_t data_len; - int32_t bufflen; + uint8_t status; + union { + struct { + uint8_t queue_type; + uint8_t data_direction; + int16_t cdb_len; + uint32_t op_flags; + int32_t data_len; + int32_t bufflen; + }; + struct { + uint8_t sense_len; + aligned_u64 psense_buffer; + }; + }; }; /* Be careful adding new members here, this structure is allocated on stack! */ diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 980768e48..995778be6 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1252,6 +1252,9 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd, TRACE_ENTRY(); + if (preply->status != 0) + goto out_status; + if (unlikely(preply->queue_type > SCST_CMD_QUEUE_ACA)) goto out_inval; @@ -1297,9 +1300,40 @@ out_inval: (long long unsigned int)cmd->lun, cmd->cdb[0], cmd); PRINT_BUFFER("Invalid parse_reply", reply, sizeof(*reply)); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); - scst_set_cmd_abnormal_done_state(cmd); res = -EINVAL; + goto out_abnormal; + +out_hwerr_res_set: + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + +out_abnormal: + scst_set_cmd_abnormal_done_state(cmd); goto out_process; + +out_status: + TRACE_DBG("ucmd %p returned with error from user status %x", + ucmd, preply->status); + + if (preply->sense_len != 0) { + int sense_len; + + res = scst_alloc_sense(cmd, 0); + if (res != 0) + goto out_hwerr_res_set; + + sense_len = min_t(int, cmd->sense_buflen, preply->sense_len); + + res = copy_from_user(cmd->sense, + (void __user *)(unsigned long)preply->psense_buffer, + sense_len); + if (res < 0) { + PRINT_ERROR("%s", "Unable to get sense data"); + goto out_hwerr_res_set; + } + cmd->sense_valid_len = sense_len; + } + scst_set_cmd_error_status(cmd, preply->status); + goto out_abnormal; } static int dev_user_process_reply_on_free(struct scst_user_cmd *ucmd)