]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
target: Add MI_REPORT_TARGET_PGS ext. header + implict_trans_secs attribute
authorNicholas Bellinger <nab@linux-iscsi.org>
Thu, 17 May 2012 05:02:34 +0000 (22:02 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Thu, 17 May 2012 07:45:58 +0000 (00:45 -0700)
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>
drivers/target/target_core_alua.c
drivers/target/target_core_alua.h
drivers/target/target_core_configfs.c
include/target/target_core_base.h

index be7251ee8b3a3ce8c311851c3dea683d1b9152c1..e624b836469cdc48af94a51be106df42a85ab63f 100644 (file)
@@ -66,18 +66,24 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
        unsigned char *buf;
-       u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
-                                   Target port group descriptor */
+       u32 rd_len = 0, off;
+       int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
        /*
-        * Need at least 4 bytes of response data or else we can't
-        * even fit the return data length.
+        * Skip over RESERVED area to first Target port group descriptor
+        * depending on the PARAMETER DATA FORMAT type..
         */
-       if (cmd->data_length < 4) {
-               pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
-                       " too small\n", cmd->data_length);
+       if (ext_hdr != 0)
+               off = 8;
+       else
+               off = 4;
+
+       if (cmd->data_length < off) {
+               pr_warn("REPORT TARGET PORT GROUPS allocation length %u too"
+                       " small for %s header\n", cmd->data_length,
+                       (ext_hdr) ? "extended" : "normal");
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
                return -EINVAL;
        }
-
        buf = transport_kmap_data_sg(cmd);
 
        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)
        /*
         * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
         */
-       buf[0] = ((rd_len >> 24) & 0xff);
-       buf[1] = ((rd_len >> 16) & 0xff);
-       buf[2] = ((rd_len >> 8) & 0xff);
-       buf[3] = (rd_len & 0xff);
+       put_unaligned_be32(rd_len, &buf[0]);
 
+       /*
+        * Fill in the Extended header parameter data format if requested
+        */
+       if (ext_hdr != 0) {
+               buf[4] = 0x10;
+               /*
+                * Set the implict transition time (in seconds) for the application
+                * client to use as a base for it's transition timeout value.
+                *
+                * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN
+                * this CDB was received upon to determine this value individually
+                * for ALUA target port group.
+                */
+               port = cmd->se_lun->lun_sep;
+               tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+               if (tg_pt_gp_mem) {
+                       spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+                       tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
+                       if (tg_pt_gp)
+                               buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
+                       spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+               }
+       }
        transport_kunmap_data_sg(cmd);
 
        target_complete_cmd(cmd, GOOD);
@@ -1355,6 +1381,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
         */
        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;
+       tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
 
        if (def_group) {
                spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
@@ -1851,6 +1878,37 @@ ssize_t core_alua_store_trans_delay_msecs(
        return count;
 }
 
+ssize_t core_alua_show_implict_trans_secs(
+       struct t10_alua_tg_pt_gp *tg_pt_gp,
+       char *page)
+{
+       return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs);
+}
+
+ssize_t core_alua_store_implict_trans_secs(
+       struct t10_alua_tg_pt_gp *tg_pt_gp,
+       const char *page,
+       size_t count)
+{
+       unsigned long tmp;
+       int ret;
+
+       ret = strict_strtoul(page, 0, &tmp);
+       if (ret < 0) {
+               pr_err("Unable to extract implict_trans_secs\n");
+               return -EINVAL;
+       }
+       if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) {
+               pr_err("Passed implict_trans_secs: %lu, exceeds"
+                       " ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp,
+                       ALUA_MAX_IMPLICT_TRANS_SECS);
+               return  -EINVAL;
+       }
+       tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp;
+
+       return count;
+}
+
 ssize_t core_alua_show_preferred_bit(
        struct t10_alua_tg_pt_gp *tg_pt_gp,
        char *page)
index e2645432475286c3904aa646e10a6a5239694d8b..f920c170d47b1d02b8015ae6ecba7b013c436e69 100644 (file)
  */
 #define ALUA_DEFAULT_TRANS_DELAY_MSECS                 0
 #define ALUA_MAX_TRANS_DELAY_MSECS                     30000 /* 30 seconds */
+/*
+ * Used for the recommended application client implict transition timeout
+ * in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header.
+ */
+#define ALUA_DEFAULT_IMPLICT_TRANS_SECS                        0
+#define ALUA_MAX_IMPLICT_TRANS_SECS                    255
 /*
  * Used by core_alua_update_tpg_primary_metadata() and
  * core_alua_update_tpg_secondary_metadata()
@@ -107,6 +113,10 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
                                        char *);
 extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
                                        const char *, size_t);
+extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
+                                       char *);
+extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
+                                       const char *, size_t);
 extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
                                        char *);
 extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *,
index 931521cc4e4f7190766bea70735e7ee7624804ad..801efa8920464620ca8cdbc318d5c4865181c5c3 100644 (file)
@@ -2446,6 +2446,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
 
 SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
 
+/*
+ * implict_trans_secs
+ */
+static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs(
+       struct t10_alua_tg_pt_gp *tg_pt_gp,
+       char *page)
+{
+       return core_alua_show_implict_trans_secs(tg_pt_gp, page);
+}
+
+static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs(
+       struct t10_alua_tg_pt_gp *tg_pt_gp,
+       const char *page,
+       size_t count)
+{
+       return core_alua_store_implict_trans_secs(tg_pt_gp, page, count);
+}
+
+SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
+
 /*
  * preferred
  */
@@ -2570,6 +2590,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
        &target_core_alua_tg_pt_gp_alua_write_metadata.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_implict_trans_secs.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,
index 1fe9111f4dc1207a1c71c0059692eb8145ab9c24..dc35d8660aa68ba44f43a684f136e548bc54424f 100644 (file)
@@ -330,6 +330,7 @@ struct t10_alua_tg_pt_gp {
        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_implict_trans_secs;
        int     tg_pt_gp_pref;
        int     tg_pt_gp_write_metadata;
        /* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */