mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 21:26:31 +00:00
- Adds generation of INQUERY DATA HAS CHANGED UA for changed devices during automatic sessions reassignment
- Requeue global UAs on delivery failure added - Minor fixes and cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1031 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+11
-2
@@ -1677,12 +1677,15 @@ struct scst_tgt_dev {
|
||||
struct scst_session *sess; /* corresponding session */
|
||||
struct scst_acg_dev *acg_dev; /* corresponding acg_dev */
|
||||
|
||||
/* list entry in dev->dev_tgt_dev_list */
|
||||
/* List entry in dev->dev_tgt_dev_list */
|
||||
struct list_head dev_tgt_dev_list_entry;
|
||||
|
||||
/* internal tmp list entry */
|
||||
/* Internal tmp list entry */
|
||||
struct list_head extra_tgt_dev_list_entry;
|
||||
|
||||
/* Set if INQUIRY DATA HAS CHANGED UA is needed */
|
||||
unsigned int inq_changed_ua_needed:1;
|
||||
|
||||
/*
|
||||
* Stored Unit Attention sense and its length for possible
|
||||
* subsequent REQUEST SENSE. Both protected by tgt_dev_lock.
|
||||
@@ -3009,6 +3012,12 @@ int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
|
||||
void scst_set_sense(uint8_t *buffer, int len, bool d_sense,
|
||||
int key, int asc, int ascq);
|
||||
|
||||
/*
|
||||
* Returns true if the sense is valid and carrying a Unit Attention or
|
||||
* false otherwise.
|
||||
*/
|
||||
bool scst_is_ua_sense(const uint8_t *sense, int len);
|
||||
|
||||
/*
|
||||
* Returnes true if sense matches to (key, asc, ascq) and false otherwise.
|
||||
* Valid_mask is one or several SCST_SENSE_*_VALID constants setting valid
|
||||
|
||||
@@ -139,11 +139,6 @@ enum scst_cmd_queue_type {
|
||||
#define SCST_NO_SENSE(sense) ((sense != NULL) && \
|
||||
(((const uint8_t *)(sense))[2] == 0))
|
||||
|
||||
static inline int scst_is_ua_sense(const uint8_t *sense)
|
||||
{
|
||||
return SCST_SENSE_VALID(sense) && (sense[2] == UNIT_ATTENTION);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
** Sense data for the appropriate errors. Can be used with
|
||||
** scst_set_cmd_error()
|
||||
@@ -170,6 +165,7 @@ static inline int scst_is_ua_sense(const uint8_t *sense)
|
||||
#define scst_sense_cleared_by_another_ini_UA UNIT_ATTENTION, 0x2F, 0
|
||||
#define scst_sense_capacity_data_changed UNIT_ATTENTION, 0x2A, 0x9
|
||||
#define scst_sense_reported_luns_data_changed UNIT_ATTENTION, 0x3F, 0xE
|
||||
#define scst_sense_inquery_data_changed UNIT_ATTENTION, 0x3F, 0x3
|
||||
|
||||
/*************************************************************
|
||||
* SCSI opcodes not listed anywhere else
|
||||
|
||||
+85
-4
@@ -259,6 +259,31 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_analyze_sense);
|
||||
|
||||
bool scst_is_ua_sense(const uint8_t *sense, int len)
|
||||
{
|
||||
if (SCST_SENSE_VALID(sense))
|
||||
return scst_analyze_sense(sense, len,
|
||||
SCST_SENSE_KEY_VALID, UNIT_ATTENTION, 0, 0);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_is_ua_sense);
|
||||
|
||||
bool scst_is_ua_global(const uint8_t *sense, int len)
|
||||
{
|
||||
bool res;
|
||||
|
||||
/* Changing it don't forget to change scst_requeue_ua() as well!! */
|
||||
|
||||
if (scst_analyze_sense(sense, len, SCST_SENSE_ALL_VALID,
|
||||
SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed)))
|
||||
res = true;
|
||||
else
|
||||
res = false;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void scst_check_convert_sense(struct scst_cmd *cmd)
|
||||
{
|
||||
bool d_sense;
|
||||
@@ -702,6 +727,29 @@ out_free:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_aen_done);
|
||||
|
||||
void scst_requeue_ua(struct scst_cmd *cmd)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
|
||||
SCST_SENSE_ALL_VALID,
|
||||
SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
|
||||
TRACE_MGMT_DBG("Requeuing REPORTED LUNS DATA CHANGED UA "
|
||||
"for delivery failed cmd %p", cmd);
|
||||
mutex_lock(&scst_mutex);
|
||||
scst_queue_report_luns_changed_UA(cmd->sess,
|
||||
SCST_SET_UA_FLAG_AT_HEAD);
|
||||
mutex_unlock(&scst_mutex);
|
||||
} else {
|
||||
TRACE_MGMT_DBG("Requeuing UA for delivery failed cmd %p", cmd);
|
||||
scst_check_set_UA(cmd->tgt_dev, cmd->sense,
|
||||
cmd->sense_bufflen, SCST_SET_UA_FLAG_AT_HEAD);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
static void scst_check_reassign_sess(struct scst_session *sess)
|
||||
{
|
||||
@@ -711,7 +759,7 @@ static void scst_check_reassign_sess(struct scst_session *sess)
|
||||
struct list_head *shead;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
bool luns_changed = false;
|
||||
bool add_failed, something_freed;
|
||||
bool add_failed, something_freed, not_needed_freed = false;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -733,6 +781,8 @@ static void scst_check_reassign_sess(struct scst_session *sess)
|
||||
retry_add:
|
||||
add_failed = false;
|
||||
list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
unsigned int inq_changed_ua_needed = 0;
|
||||
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
shead = &sess->sess_tgt_dev_list_hash[i];
|
||||
|
||||
@@ -747,7 +797,8 @@ retry_add:
|
||||
(unsigned long long)tgt_dev->lun);
|
||||
tgt_dev->acg_dev = acg_dev;
|
||||
goto next;
|
||||
}
|
||||
} else if (tgt_dev->lun == acg_dev->lun)
|
||||
inq_changed_ua_needed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,11 +812,15 @@ retry_add:
|
||||
add_failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
tgt_dev->inq_changed_ua_needed = inq_changed_ua_needed ||
|
||||
not_needed_freed;
|
||||
next:
|
||||
continue;
|
||||
}
|
||||
|
||||
something_freed = false;
|
||||
not_needed_freed = true;
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
struct scst_tgt_dev *t;
|
||||
shead = &sess->sess_tgt_dev_list_hash[i];
|
||||
@@ -795,9 +850,35 @@ next:
|
||||
old_acg->acg_name, acg->acg_name);
|
||||
list_move_tail(&sess->acg_sess_list_entry, &acg->acg_sess_list);
|
||||
|
||||
if (luns_changed)
|
||||
if (luns_changed) {
|
||||
uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
|
||||
|
||||
scst_report_luns_changed_sess(sess);
|
||||
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
shead = &sess->sess_tgt_dev_list_hash[i];
|
||||
|
||||
list_for_each_entry(tgt_dev, shead,
|
||||
sess_tgt_dev_list_entry) {
|
||||
if (tgt_dev->inq_changed_ua_needed) {
|
||||
TRACE_MGMT_DBG("sess %p: Setting "
|
||||
"INQUIRY DATA HAS CHANGED UA "
|
||||
"(tgt_dev %p)", sess, tgt_dev);
|
||||
|
||||
tgt_dev->inq_changed_ua_needed = 0;
|
||||
|
||||
scst_set_sense(sense_buffer,
|
||||
sizeof(sense_buffer),
|
||||
tgt_dev->dev->d_sense,
|
||||
SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
|
||||
|
||||
scst_check_set_UA(tgt_dev, sense_buffer,
|
||||
sizeof(sense_buffer), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -4164,7 +4245,7 @@ static void scst_check_internal_sense(struct scst_device *dev, int result,
|
||||
SCST_LOAD_SENSE(scst_sense_reset_UA));
|
||||
scst_dev_check_set_UA(dev, NULL, sense, sense_len);
|
||||
} else if ((status_byte(result) == CHECK_CONDITION) &&
|
||||
SCST_SENSE_VALID(sense) && scst_is_ua_sense(sense))
|
||||
scst_is_ua_sense(sense, sense_len))
|
||||
scst_dev_check_set_UA(dev, NULL, sense, sense_len);
|
||||
|
||||
TRACE_EXIT();
|
||||
|
||||
@@ -434,6 +434,9 @@ void scst_process_reset(struct scst_device *dev,
|
||||
struct scst_session *originator, struct scst_cmd *exclude_cmd,
|
||||
struct scst_mgmt_cmd *mcmd, bool setUA);
|
||||
|
||||
bool scst_is_ua_global(const uint8_t *sense, int len);
|
||||
void scst_requeue_ua(struct scst_cmd *cmd);
|
||||
|
||||
static inline bool scst_is_ua_command(struct scst_cmd *cmd)
|
||||
{
|
||||
return (cmd->op_flags & SCST_SKIP_UA) == 0;
|
||||
|
||||
+22
-20
@@ -2425,7 +2425,7 @@ static int scst_check_sense(struct scst_cmd *cmd)
|
||||
cmd->sense_bufflen);
|
||||
|
||||
/* Check Unit Attention Sense Key */
|
||||
if (scst_is_ua_sense(cmd->sense)) {
|
||||
if (scst_is_ua_sense(cmd->sense, cmd->sense_bufflen)) {
|
||||
if (scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
|
||||
SCST_SENSE_ASC_VALID,
|
||||
0, SCST_SENSE_ASC_UA_RESET, 0)) {
|
||||
@@ -2653,8 +2653,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
|
||||
/* Check for MODE PARAMETERS CHANGED UA */
|
||||
if ((cmd->dev->scsi_dev != NULL) &&
|
||||
(cmd->status == SAM_STAT_CHECK_CONDITION) &&
|
||||
SCST_SENSE_VALID(cmd->sense) &&
|
||||
scst_is_ua_sense(cmd->sense) &&
|
||||
scst_is_ua_sense(cmd->sense, cmd->sense_bufflen) &&
|
||||
scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
|
||||
SCST_SENSE_ASCx_VALID,
|
||||
0, 0x2a, 0x01)) {
|
||||
@@ -2717,8 +2716,7 @@ static int scst_mode_select_checks(struct scst_cmd *cmd)
|
||||
scst_obtain_device_parameters(dev);
|
||||
}
|
||||
} else if ((cmd->status == SAM_STAT_CHECK_CONDITION) &&
|
||||
SCST_SENSE_VALID(cmd->sense) &&
|
||||
scst_is_ua_sense(cmd->sense) &&
|
||||
scst_is_ua_sense(cmd->sense, cmd->sense_bufflen) &&
|
||||
/* mode parameters changed */
|
||||
(scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
|
||||
SCST_SENSE_ASCx_VALID,
|
||||
@@ -3112,6 +3110,21 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) {
|
||||
if ((cmd->tgt_dev != NULL) &&
|
||||
scst_is_ua_sense(cmd->sense, cmd->sense_bufflen)) {
|
||||
/* This UA delivery failed, so we need to requeue it */
|
||||
if (scst_cmd_atomic(cmd) &&
|
||||
scst_is_ua_global(cmd->sense, cmd->sense_bufflen)) {
|
||||
TRACE_MGMT_DBG("Requeuing of global UA for "
|
||||
"failed cmd %p needs a thread", cmd);
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
scst_requeue_ua(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
atomic_dec(&sess->sess_cmd_count);
|
||||
|
||||
spin_lock_irq(&sess->sess_list_lock);
|
||||
@@ -3129,21 +3142,13 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
|
||||
scst_finish_cmd_mgmt(cmd);
|
||||
}
|
||||
|
||||
if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) {
|
||||
if ((cmd->tgt_dev != NULL) &&
|
||||
scst_is_ua_sense(cmd->sense)) {
|
||||
/* This UA delivery failed, so requeue it */
|
||||
TRACE_MGMT_DBG("Requeuing UA for delivery failed cmd "
|
||||
"%p", cmd);
|
||||
scst_check_set_UA(cmd->tgt_dev, cmd->sense,
|
||||
cmd->sense_bufflen, SCST_SET_UA_FLAG_AT_HEAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__scst_cmd_put(cmd);
|
||||
|
||||
res = SCST_CMD_STATE_RES_CONT_NEXT;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_HRES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -3170,10 +3175,9 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
|
||||
|
||||
scst_check_debug_sn(cmd);
|
||||
|
||||
if (cmd->dev->queue_alg ==
|
||||
SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) {
|
||||
if (cmd->dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) {
|
||||
/*
|
||||
* Not the best way, but well enough until there will be a
|
||||
* Not the best way, but good enough until there is a
|
||||
* possibility to specify queue type during pass-through
|
||||
* commands submission.
|
||||
*/
|
||||
@@ -3633,8 +3637,6 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
|
||||
case SCST_CMD_STATE_FINISHED:
|
||||
res = scst_finish_cmd(cmd);
|
||||
EXTRACHECKS_BUG_ON(res ==
|
||||
SCST_CMD_STATE_RES_NEED_THREAD);
|
||||
break;
|
||||
|
||||
case SCST_CMD_STATE_FINISHED_INTERNAL:
|
||||
|
||||
Reference in New Issue
Block a user