Commit 5b9a4d7280e160982a8ea37bc03619f53b5c98b7

Authored by Nicholas Bellinger
1 parent ba539743b7

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>

Showing 4 changed files with 102 additions and 12 deletions Side-by-side Diff

drivers/target/target_core_alua.c
... ... @@ -66,18 +66,24 @@
66 66 struct t10_alua_tg_pt_gp *tg_pt_gp;
67 67 struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
68 68 unsigned char *buf;
69   - u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
70   - Target port group descriptor */
  69 + u32 rd_len = 0, off;
  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
73   - * even fit the return data length.
  72 + * Skip over RESERVED area to first Target port group descriptor
  73 + * depending on the PARAMETER DATA FORMAT type..
74 74 */
75   - if (cmd->data_length < 4) {
76   - pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
77   - " too small\n", cmd->data_length);
  75 + if (ext_hdr != 0)
  76 + off = 8;
  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 85 return -EINVAL;
79 86 }
80   -
81 87 buf = transport_kmap_data_sg(cmd);
82 88  
83 89 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
84 90  
... ... @@ -158,11 +164,31 @@
158 164 /*
159 165 * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
160 166 */
161   - buf[0] = ((rd_len >> 24) & 0xff);
162   - buf[1] = ((rd_len >> 16) & 0xff);
163   - buf[2] = ((rd_len >> 8) & 0xff);
164   - buf[3] = (rd_len & 0xff);
  167 + put_unaligned_be32(rd_len, &buf[0]);
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 192 transport_kunmap_data_sg(cmd);
167 193  
168 194 target_complete_cmd(cmd, GOOD);
... ... @@ -1355,6 +1381,7 @@
1355 1381 */
1356 1382 tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
1357 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 1386 if (def_group) {
1360 1387 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
... ... @@ -1847,6 +1874,37 @@
1847 1874 return -EINVAL;
1848 1875 }
1849 1876 tg_pt_gp->tg_pt_gp_trans_delay_msecs = (int)tmp;
  1877 +
  1878 + return count;
  1879 +}
  1880 +
  1881 +ssize_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 +
  1888 +ssize_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;
1850 1908  
1851 1909 return count;
1852 1910 }
drivers/target/target_core_alua.h
... ... @@ -52,6 +52,12 @@
52 52 #define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
53 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 61 * Used by core_alua_update_tpg_primary_metadata() and
56 62 * core_alua_update_tpg_secondary_metadata()
57 63 */
... ... @@ -106,6 +112,10 @@
106 112 extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
107 113 char *);
108 114 extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
  115 + const char *, size_t);
  116 +extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
  117 + char *);
  118 +extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
109 119 const char *, size_t);
110 120 extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
111 121 char *);
drivers/target/target_core_configfs.c
... ... @@ -2447,6 +2447,26 @@
2447 2447 SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
2448 2448  
2449 2449 /*
  2450 + * implict_trans_secs
  2451 + */
  2452 +static 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 +
  2459 +static 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 +
  2467 +SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
  2468 +
  2469 +/*
2450 2470 * preferred
2451 2471 */
2452 2472  
... ... @@ -2570,6 +2590,7 @@
2570 2590 &target_core_alua_tg_pt_gp_alua_write_metadata.attr,
2571 2591 &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
2572 2592 &target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
  2593 + &target_core_alua_tg_pt_gp_implict_trans_secs.attr,
2573 2594 &target_core_alua_tg_pt_gp_preferred.attr,
2574 2595 &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
2575 2596 &target_core_alua_tg_pt_gp_members.attr,
include/target/target_core_base.h
... ... @@ -330,6 +330,7 @@
330 330 int tg_pt_gp_alua_access_type;
331 331 int tg_pt_gp_nonop_delay_msecs;
332 332 int tg_pt_gp_trans_delay_msecs;
  333 + int tg_pt_gp_implict_trans_secs;
333 334 int tg_pt_gp_pref;
334 335 int tg_pt_gp_write_metadata;
335 336 /* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */