tcm_loop: Implement transport offline
authorHannes Reinecke <hare@suse.de>
Wed, 16 Oct 2013 07:12:53 +0000 (09:12 +0200)
committerNicholas Bellinger <nab@linux-iscsi.org>
Wed, 16 Oct 2013 22:41:26 +0000 (15:41 -0700)
Add attribute 'transport_status' to simulate link failure.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/loopback/tcm_loop.c
drivers/target/loopback/tcm_loop.h

index 21b49f3517235753318313c86b81aaae11ed9ee0..a00ad27940b77cb4cca53b6930e6a7541e7f2429 100644 (file)
@@ -178,7 +178,10 @@ static void tcm_loop_submission_work(struct work_struct *work)
                set_host_byte(sc, DID_NO_CONNECT);
                goto out_done;
        }
-
+       if (tl_tpg->tl_transport_status == TCM_TRANSPORT_OFFLINE) {
+               set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
+               goto out_done;
+       }
        tl_nexus = tl_hba->tl_nexus;
        if (!tl_nexus) {
                scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
@@ -1064,8 +1067,56 @@ check_newline:
 
 TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
 
+static ssize_t tcm_loop_tpg_show_transport_status(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
+                       struct tcm_loop_tpg, tl_se_tpg);
+       const char *status = NULL;
+       ssize_t ret = -EINVAL;
+
+       switch (tl_tpg->tl_transport_status) {
+       case TCM_TRANSPORT_ONLINE:
+               status = "online";
+               break;
+       case TCM_TRANSPORT_OFFLINE:
+               status = "offline";
+               break;
+       default:
+               break;
+       }
+
+       if (status)
+               ret = snprintf(page, PAGE_SIZE, "%s\n", status);
+
+       return ret;
+}
+
+static ssize_t tcm_loop_tpg_store_transport_status(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
+                       struct tcm_loop_tpg, tl_se_tpg);
+
+       if (!strncmp(page, "online", 6)) {
+               tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
+               return count;
+       }
+       if (!strncmp(page, "offline", 7)) {
+               tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE;
+               return count;
+       }
+       return -EINVAL;
+}
+
+TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
+
 static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
        &tcm_loop_tpg_nexus.attr,
+       &tcm_loop_tpg_transport_status.attr,
        NULL,
 };
 
index dd7a84ee78e1129db36e7ab625731666b05125ef..56528f7dafae6aa33c53c2cb7388140a6febbf50 100644 (file)
@@ -40,8 +40,12 @@ struct tcm_loop_nacl {
        struct se_node_acl se_node_acl;
 };
 
+#define TCM_TRANSPORT_ONLINE 0
+#define TCM_TRANSPORT_OFFLINE 1
+
 struct tcm_loop_tpg {
        unsigned short tl_tpgt;
+       unsigned short tl_transport_status;
        atomic_t tl_tpg_port_count;
        struct se_portal_group tl_se_tpg;
        struct tcm_loop_hba *tl_hba;