[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-scsi
Subject: [PATCH] [Target_Core_Mod/ALUA]: Add ALUA Transition state usage +
From: "Nicholas A. Bellinger" <nab () linux-iscsi ! org>
Date: 2009-08-31 8:24:37
Message-ID: 1251707077.4136.35.camel () haakon2 ! linux-iscsi ! org
[Download RAW message or body]
Greeting SCSI and multipath folks,
This patch updates lio-core-2.6.git code to support a optional millisecond delay of
ALUA primary and secondary access state transition via explict (via MO \
SET_TARGET_PORT_GROUPS) and implict (via configfs) ALUA operations.
This was something that Hannes had asked me doing about at LSF 09', and is now \
available in LIO v3.1, and is intended to be used for debugging scsi_dh_alua and \
other ALUA client side code during ALUA_ACCESS_STATE_TRANSITION.
This patch updates core_alua_do_transition_tg_pt() to set the current primary
target port group ALUA access state to ALUA_ACCESS_STATE_TRANSITION for the
passed t10_alua_tg_pt_gp_t, and then optionally wait for tg_pt_gp_trans_delay_msecs
before successfully completing the transition to the new ALUA primary access state.
By default, the transition delay is disabled in the ALUA_DEFAULT_TRANS_DELAY_MSECS
constant, and is intended to add debugging for initiator side ALUA transition
scenarios.
This patch adds a new configfs attribute for this delay in milliseconds located at:
/sys/kernel/config/target/core/$HBA/$DEV/alua/$TG_PT_GP_NAME/trans_delay_msecs
This patch also updates core_alua_set_tg_pt_secondary_state() to optionally
wait for the same target port group trans_delay_msecs value with the 'Offline'
ALUA secondary access state transition of the fabric dependent SCSI target port.
The userspace commit can be found here:
http://git.kernel.org/?p=linux/storage/lio/lio-utils.git;a=commitdiff;h=0b77cc113ef20e26fd58df8d8711a463a0b24070
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
---
drivers/target/target_core_alua.c | 57 +++++++++++++++++++++++++++++++--
drivers/target/target_core_configfs.c | 21 ++++++++++++
include/target/target_core_alua.h | 11 ++++++
include/target/target_core_base.h | 1 +
4 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index b970c50..0845436 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -625,12 +625,21 @@ int core_alua_do_transition_tg_pt(
se_port_t *port;
t10_alua_tg_pt_gp_member_t *mem;
int old_state = 0;
-
+ /*
+ * Save the old primary ALUA access state, and set the current state
+ * to ALUA_ACCESS_STATE_TRANSITION.
+ */
old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
- atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
+ atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
+ ALUA_ACCESS_STATE_TRANSITION);
tg_pt_gp->tg_pt_gp_alua_access_status = (explict) ?
ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
+ /*
+ * Check for the optional ALUA primary state transition delay
+ */
+ if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0)
+ msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs);
spin_lock(&tg_pt_gp->tg_pt_gp_lock);
list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list,
@@ -674,6 +683,10 @@ int core_alua_do_transition_tg_pt(
smp_mb__after_atomic_dec();
}
spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
+ /*
+ * Set the current primary ALUA access state to the requested new state
+ */
+ atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
printk(KERN_INFO "Successful %s ALUA transition TG PT Group: %s ID: %hu"
" from primary access state: %s to %s\n", (explict) ? "explict" :
@@ -806,6 +819,7 @@ int core_alua_set_tg_pt_secondary_state(
int offline)
{
struct t10_alua_tg_pt_gp_s *tg_pt_gp;
+ int trans_delay_msecs;
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
@@ -815,6 +829,7 @@ int core_alua_set_tg_pt_secondary_state(
" transition\n");
return -1;
}
+ trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs;
/*
* Set the secondary ALUA target port access state to OFFLINE
* or release the previously secondary state for se_port_t
@@ -827,13 +842,17 @@ int core_alua_set_tg_pt_secondary_state(
port->sep_tg_pt_secondary_stat = (explict) ?
ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
- spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
printk(KERN_INFO "Successful %s ALUA transition TG PT Group: %s ID: %hu"
" to secondary access state: %s\n", (explict) ? "explict" :
"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE");
+ spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+
+ if (trans_delay_msecs != 0)
+ msleep_interruptible(trans_delay_msecs);
+
return 0;
}
@@ -1106,6 +1125,7 @@ t10_alua_tg_pt_gp_t *core_alua_allocate_tg_pt_gp(
* Set the default Active/NonOptimized Delay in milliseconds
*/
tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
+ tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
if (def_group) {
spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
@@ -1573,6 +1593,37 @@ ssize_t core_alua_store_nonop_delay_msecs(
return count;
}
+ssize_t core_alua_show_trans_delay_msecs(
+ t10_alua_tg_pt_gp_t *tg_pt_gp,
+ char *page)
+{
+ return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_trans_delay_msecs);
+}
+
+ssize_t core_alua_store_trans_delay_msecs(
+ t10_alua_tg_pt_gp_t *tg_pt_gp,
+ const char *page,
+ size_t count)
+{
+ unsigned long tmp;
+ int ret;
+
+ ret = strict_strtoul(page, 0, &tmp);
+ if (ret < 0) {
+ printk(KERN_ERR "Unable to extract trans_delay_msecs\n");
+ return -EINVAL;
+ }
+ if (tmp > ALUA_MAX_TRANS_DELAY_MSECS) {
+ printk(KERN_ERR "Passed trans_delay_msecs: %lu, exceeds"
+ " ALUA_MAX_TRANS_DELAY_MSECS: %d\n", tmp,
+ ALUA_MAX_TRANS_DELAY_MSECS);
+ return -EINVAL;
+ }
+ tg_pt_gp->tg_pt_gp_trans_delay_msecs = (int)tmp;
+
+ return count;
+}
+
ssize_t core_alua_show_preferred_bit(
t10_alua_tg_pt_gp_t *tg_pt_gp,
char *page)
diff --git a/drivers/target/target_core_configfs.c \
b/drivers/target/target_core_configfs.c index 3fed78c..360fa92 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -2266,6 +2266,26 @@ static ssize_t \
target_core_alua_tg_pt_gp_store_attr_nonop_delay_msecs( \
SE_DEV_ALUA_TG_PT_ATTR(nonop_delay_msecs, S_IRUGO | S_IWUSR);
/*
+ * trans_delay_msecs
+ */
+static ssize_t target_core_alua_tg_pt_gp_show_attr_trans_delay_msecs(
+ struct t10_alua_tg_pt_gp_s *tg_pt_gp,
+ char *page)
+{
+ return core_alua_show_trans_delay_msecs(tg_pt_gp, page);
+}
+
+static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
+ struct t10_alua_tg_pt_gp_s *tg_pt_gp,
+ const char *page,
+ size_t count)
+{
+ return core_alua_store_trans_delay_msecs(tg_pt_gp, page, count);
+}
+
+SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
+
+/*
* preferred
*/
@@ -2387,6 +2407,7 @@ static struct configfs_attribute \
*target_core_alua_tg_pt_gp_attrs[] = { \
&target_core_alua_tg_pt_gp_alua_access_status.attr, \
&target_core_alua_tg_pt_gp_alua_access_type.attr, \
&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, \
+ &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, \
&target_core_alua_tg_pt_gp_preferred.attr, \
&target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, \
&target_core_alua_tg_pt_gp_members.attr,
diff --git a/include/target/target_core_alua.h b/include/target/target_core_alua.h
index 825c2a8..0229e18 100644
--- a/include/target/target_core_alua.h
+++ b/include/target/target_core_alua.h
@@ -45,6 +45,13 @@
*/
#define ALUA_DEFAULT_NONOP_DELAY_MSECS 100
#define ALUA_MAX_NONOP_DELAY_MSECS 10000 /* 10 seconds */
+/*
+ * Used for implict and explict ALUA transitional delay, that is disabled
+ * by default, and is intended to be used for debugging client side ALUA code.
+ */
+#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
+#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */
+
extern se_global_t *se_global;
@@ -104,6 +111,10 @@ extern ssize_t core_alua_show_nonop_delay_msecs(struct \
t10_alua_tg_pt_gp_s *, char *);
extern ssize_t core_alua_store_nonop_delay_msecs(struct t10_alua_tg_pt_gp_s *,
const char *, size_t);
+extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp_s *,
+ char *);
+extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp_s *,
+ const char *, size_t);
extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp_s *, char *);
extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp_s *,
const char *, size_t);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 3a97d1e..8bf7877 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -267,6 +267,7 @@ typedef struct t10_alua_tg_pt_gp_s {
int tg_pt_gp_alua_access_status;
int tg_pt_gp_alua_access_type;
int tg_pt_gp_nonop_delay_msecs;
+ int tg_pt_gp_trans_delay_msecs;
int tg_pt_gp_pref;
u32 tg_pt_gp_members;
atomic_t tg_pt_gp_alua_access_state;
--
1.5.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic