aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2012-05-17 01:02:34 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-05-17 03:45:58 -0400
commit5b9a4d7280e160982a8ea37bc03619f53b5c98b7 (patch)
tree3d7fbce10e7379097f34276b6a8a7d090d4dc813 /drivers/target
parentba539743b70cd160c84bab1c82910d0789b820f8 (diff)
target: Add MI_REPORT_TARGET_PGS ext. header + implict_trans_secs attribute
This patch adds support for ALUA MI_REPORT_TARGET_PGS extended header format defined within SPC-4. It changes target core ALUA emulation logic within target_emulate_report_target_port_groups() to support both the extended and original length only header formats. It includes adding a new 'implict_trans_secs' attribute for each ALUA target port group to control the value returned to the application client for an recommended implict translation timeout in seconds. By default this value is currently set to zero, and limited up to 255 by virtue of using a single byte in the extended header format. This value is used by target_emulate_report_target_port_groups() within the extended header logic to set IMPLICIT TRANSITION TIME as defined by spc4r30. Cc: Hannes Reinecke <hare@suse.de> Cc: Rob Evers <revers@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Roland Dreier <roland@purestorage.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_alua.c82
-rw-r--r--drivers/target/target_core_alua.h10
-rw-r--r--drivers/target/target_core_configfs.c21
3 files changed, 101 insertions, 12 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index be7251ee8b3a..e624b836469c 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -66,18 +66,24 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
66 struct t10_alua_tg_pt_gp *tg_pt_gp; 66 struct t10_alua_tg_pt_gp *tg_pt_gp;
67 struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 67 struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
68 unsigned char *buf; 68 unsigned char *buf;
69 u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first 69 u32 rd_len = 0, off;
70 Target port group descriptor */ 70 int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
71 /* 71 /*
72 * Need at least 4 bytes of response data or else we can't 72 * Skip over RESERVED area to first Target port group descriptor
73 * even fit the return data length. 73 * depending on the PARAMETER DATA FORMAT type..
74 */ 74 */
75 if (cmd->data_length < 4) { 75 if (ext_hdr != 0)
76 pr_warn("REPORT TARGET PORT GROUPS allocation length %u" 76 off = 8;
77 " too small\n", cmd->data_length); 77 else
78 off = 4;
79
80 if (cmd->data_length < off) {
81 pr_warn("REPORT TARGET PORT GROUPS allocation length %u too"
82 " small for %s header\n", cmd->data_length,
83 (ext_hdr) ? "extended" : "normal");
84 cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
78 return -EINVAL; 85 return -EINVAL;
79 } 86 }
80
81 buf = transport_kmap_data_sg(cmd); 87 buf = transport_kmap_data_sg(cmd);
82 88
83 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 89 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
@@ -158,11 +164,31 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
158 /* 164 /*
159 * Set the RETURN DATA LENGTH set in the header of the DataIN Payload 165 * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
160 */ 166 */
161 buf[0] = ((rd_len >> 24) & 0xff); 167 put_unaligned_be32(rd_len, &buf[0]);
162 buf[1] = ((rd_len >> 16) & 0xff);
163 buf[2] = ((rd_len >> 8) & 0xff);
164 buf[3] = (rd_len & 0xff);
165 168
169 /*
170 * Fill in the Extended header parameter data format if requested
171 */
172 if (ext_hdr != 0) {
173 buf[4] = 0x10;
174 /*
175 * Set the implict transition time (in seconds) for the application
176 * client to use as a base for it's transition timeout value.
177 *
178 * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN
179 * this CDB was received upon to determine this value individually
180 * for ALUA target port group.
181 */
182 port = cmd->se_lun->lun_sep;
183 tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
184 if (tg_pt_gp_mem) {
185 spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
186 tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
187 if (tg_pt_gp)
188 buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
189 spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
190 }
191 }
166 transport_kunmap_data_sg(cmd); 192 transport_kunmap_data_sg(cmd);
167 193
168 target_complete_cmd(cmd, GOOD); 194 target_complete_cmd(cmd, GOOD);
@@ -1355,6 +1381,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
1355 */ 1381 */
1356 tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS; 1382 tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
1357 tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS; 1383 tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
1384 tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
1358 1385
1359 if (def_group) { 1386 if (def_group) {
1360 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 1387 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
@@ -1851,6 +1878,37 @@ ssize_t core_alua_store_trans_delay_msecs(
1851 return count; 1878 return count;
1852} 1879}
1853 1880
1881ssize_t core_alua_show_implict_trans_secs(
1882 struct t10_alua_tg_pt_gp *tg_pt_gp,
1883 char *page)
1884{
1885 return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs);
1886}
1887
1888ssize_t core_alua_store_implict_trans_secs(
1889 struct t10_alua_tg_pt_gp *tg_pt_gp,
1890 const char *page,
1891 size_t count)
1892{
1893 unsigned long tmp;
1894 int ret;
1895
1896 ret = strict_strtoul(page, 0, &tmp);
1897 if (ret < 0) {
1898 pr_err("Unable to extract implict_trans_secs\n");
1899 return -EINVAL;
1900 }
1901 if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) {
1902 pr_err("Passed implict_trans_secs: %lu, exceeds"
1903 " ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp,
1904 ALUA_MAX_IMPLICT_TRANS_SECS);
1905 return -EINVAL;
1906 }
1907 tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp;
1908
1909 return count;
1910}
1911
1854ssize_t core_alua_show_preferred_bit( 1912ssize_t core_alua_show_preferred_bit(
1855 struct t10_alua_tg_pt_gp *tg_pt_gp, 1913 struct t10_alua_tg_pt_gp *tg_pt_gp,
1856 char *page) 1914 char *page)
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h
index e26454324752..f920c170d47b 100644
--- a/drivers/target/target_core_alua.h
+++ b/drivers/target/target_core_alua.h
@@ -52,6 +52,12 @@
52#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0 52#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
53#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */ 53#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */
54/* 54/*
55 * Used for the recommended application client implict transition timeout
56 * in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header.
57 */
58#define ALUA_DEFAULT_IMPLICT_TRANS_SECS 0
59#define ALUA_MAX_IMPLICT_TRANS_SECS 255
60/*
55 * Used by core_alua_update_tpg_primary_metadata() and 61 * Used by core_alua_update_tpg_primary_metadata() and
56 * core_alua_update_tpg_secondary_metadata() 62 * core_alua_update_tpg_secondary_metadata()
57 */ 63 */
@@ -107,6 +113,10 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
107 char *); 113 char *);
108extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *, 114extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
109 const char *, size_t); 115 const char *, size_t);
116extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
117 char *);
118extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
119 const char *, size_t);
110extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *, 120extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
111 char *); 121 char *);
112extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *, 122extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *,
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 931521cc4e4f..801efa892046 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -2447,6 +2447,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
2447SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR); 2447SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
2448 2448
2449/* 2449/*
2450 * implict_trans_secs
2451 */
2452static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs(
2453 struct t10_alua_tg_pt_gp *tg_pt_gp,
2454 char *page)
2455{
2456 return core_alua_show_implict_trans_secs(tg_pt_gp, page);
2457}
2458
2459static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs(
2460 struct t10_alua_tg_pt_gp *tg_pt_gp,
2461 const char *page,
2462 size_t count)
2463{
2464 return core_alua_store_implict_trans_secs(tg_pt_gp, page, count);
2465}
2466
2467SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
2468
2469/*
2450 * preferred 2470 * preferred
2451 */ 2471 */
2452 2472
@@ -2570,6 +2590,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
2570 &target_core_alua_tg_pt_gp_alua_write_metadata.attr, 2590 &target_core_alua_tg_pt_gp_alua_write_metadata.attr,
2571 &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, 2591 &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
2572 &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, 2592 &target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
2593 &target_core_alua_tg_pt_gp_implict_trans_secs.attr,
2573 &target_core_alua_tg_pt_gp_preferred.attr, 2594 &target_core_alua_tg_pt_gp_preferred.attr,
2574 &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, 2595 &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
2575 &target_core_alua_tg_pt_gp_members.attr, 2596 &target_core_alua_tg_pt_gp_members.attr,