]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/target/target_core_alua.c
target: simplify alua support
[mirror_ubuntu-bionic-kernel.git] / drivers / target / target_core_alua.c
index 15c127b780d8494432a9f9ad51a313414cc5e60a..b3302a9200a27fc4c4049e0ecf8916e3de401d63 100644 (file)
@@ -522,40 +522,26 @@ static inline int core_alua_state_transition(
 }
 
 /*
- * Used for alua_type SPC_ALUA_PASSTHROUGH and SPC2_ALUA_DISABLED
- * in transport_cmd_sequencer().  This function is assigned to
- * struct t10_alua *->state_check() in core_setup_alua()
- */
-static int core_alua_state_check_nop(
-       struct se_cmd *cmd,
-       unsigned char *cdb,
-       u8 *alua_ascq)
-{
-       return 0;
-}
-
-/*
- * Used for alua_type SPC3_ALUA_EMULATED in transport_cmd_sequencer().
- * This function is assigned to struct t10_alua *->state_check() in
- * core_setup_alua()
- *
- * Also, this function can return three different return codes to
- * signal transport_generic_cmd_sequencer()
- *
  * return 1: Is used to signal LUN not accecsable, and check condition/not ready
  * return 0: Used to signal success
  * reutrn -1: Used to signal failure, and invalid cdb field
  */
-static int core_alua_state_check(
-       struct se_cmd *cmd,
-       unsigned char *cdb,
-       u8 *alua_ascq)
+int target_alua_state_check(struct se_cmd *cmd)
 {
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *cdb = cmd->t_task_cdb;
        struct se_lun *lun = cmd->se_lun;
        struct se_port *port = lun->lun_sep;
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
        int out_alua_state, nonop_delay_msecs;
+       u8 alua_ascq;
+       int ret;
+
+       if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
+               return 0;
+       if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+               return 0;
 
        if (!port)
                return 0;
@@ -564,11 +550,11 @@ static int core_alua_state_check(
         * access state: OFFLINE
         */
        if (atomic_read(&port->sep_tg_pt_secondary_offline)) {
-               *alua_ascq = ASCQ_04H_ALUA_OFFLINE;
                pr_debug("ALUA: Got secondary offline status for local"
                                " target port\n");
-               *alua_ascq = ASCQ_04H_ALUA_OFFLINE;
-               return 1;
+               alua_ascq = ASCQ_04H_ALUA_OFFLINE;
+               ret = 1;
+               goto out;
        }
         /*
         * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the
@@ -593,14 +579,18 @@ static int core_alua_state_check(
 
        switch (out_alua_state) {
        case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
-               return core_alua_state_nonoptimized(cmd, cdb,
-                                       nonop_delay_msecs, alua_ascq);
+               ret = core_alua_state_nonoptimized(cmd, cdb,
+                                       nonop_delay_msecs, &alua_ascq);
+               break;
        case ALUA_ACCESS_STATE_STANDBY:
-               return core_alua_state_standby(cmd, cdb, alua_ascq);
+               ret = core_alua_state_standby(cmd, cdb, &alua_ascq);
+               break;
        case ALUA_ACCESS_STATE_UNAVAILABLE:
-               return core_alua_state_unavailable(cmd, cdb, alua_ascq);
+               ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq);
+               break;
        case ALUA_ACCESS_STATE_TRANSITION:
-               return core_alua_state_transition(cmd, cdb, alua_ascq);
+               ret = core_alua_state_transition(cmd, cdb, &alua_ascq);
+               break;
        /*
         * OFFLINE is a secondary ALUA target port group access state, that is
         * handled above with struct se_port->sep_tg_pt_secondary_offline=1
@@ -609,10 +599,27 @@ static int core_alua_state_check(
        default:
                pr_err("Unknown ALUA access state: 0x%02x\n",
                                out_alua_state);
-               return -EINVAL;
+               ret = -EINVAL;
+               break;
        }
 
-       return 0;
+out:
+       if (ret > 0) {
+               /*
+                * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
+                * The ALUA additional sense code qualifier (ASCQ) is determined
+                * by the ALUA primary or secondary access state..
+                */
+               pr_debug("[%s]: ALUA TG Port not available, "
+                       "SenseKey: NOT_READY, ASC/ASCQ: "
+                       "0x04/0x%02x\n",
+                       cmd->se_tfo->get_fabric_name(), alua_ascq);
+
+               cmd->scsi_asc = 0x04;
+               cmd->scsi_ascq = alua_ascq;
+       }
+
+       return ret;
 }
 
 /*
@@ -1264,13 +1271,9 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 
 void core_alua_free_lu_gp_mem(struct se_device *dev)
 {
-       struct t10_alua *alua = &dev->t10_alua;
        struct t10_alua_lu_gp *lu_gp;
        struct t10_alua_lu_gp_member *lu_gp_mem;
 
-       if (alua->alua_type != SPC3_ALUA_EMULATED)
-               return;
-
        lu_gp_mem = dev->dev_alua_lu_gp_mem;
        if (!lu_gp_mem)
                return;
@@ -1538,13 +1541,9 @@ void core_alua_free_tg_pt_gp(
 
 void core_alua_free_tg_pt_gp_mem(struct se_port *port)
 {
-       struct t10_alua *alua = &port->sep_lun->lun_se_dev->t10_alua;
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 
-       if (alua->alua_type != SPC3_ALUA_EMULATED)
-               return;
-
        tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
        if (!tg_pt_gp_mem)
                return;
@@ -1636,14 +1635,10 @@ static void __core_alua_drop_tg_pt_gp_mem(
 ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page)
 {
        struct config_item *tg_pt_ci;
-       struct t10_alua *alua = &port->sep_lun->lun_se_dev->t10_alua;
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
        ssize_t len = 0;
 
-       if (alua->alua_type != SPC3_ALUA_EMULATED)
-               return len;
-
        tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
        if (!tg_pt_gp_mem)
                return len;
@@ -1686,13 +1681,9 @@ ssize_t core_alua_store_tg_pt_gp_info(
        tpg = port->sep_tpg;
        lun = port->sep_lun;
 
-       if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) {
-               pr_warn("SPC3_ALUA_EMULATED not enabled for"
-                       " %s/tpgt_%hu/%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg),
-                       tpg->se_tpg_tfo->tpg_get_tag(tpg),
-                       config_item_name(&lun->lun_group.cg_item));
-               return -EINVAL;
-       }
+       tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+       if (!tg_pt_gp_mem)
+               return 0;
 
        if (count > TG_PT_GROUP_NAME_BUF) {
                pr_err("ALUA Target Port Group alias too large!\n");
@@ -1715,13 +1706,6 @@ ssize_t core_alua_store_tg_pt_gp_info(
                if (!tg_pt_gp_new)
                        return -ENODEV;
        }
-       tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-       if (!tg_pt_gp_mem) {
-               if (tg_pt_gp_new)
-                       core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new);
-               pr_err("NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n");
-               return -EINVAL;
-       }
 
        spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
        tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
@@ -2050,26 +2034,9 @@ ssize_t core_alua_store_secondary_write_metadata(
 
 int core_setup_alua(struct se_device *dev)
 {
-       struct t10_alua *alua = &dev->t10_alua;
-       struct t10_alua_lu_gp_member *lu_gp_mem;
-
-       /*
-        * If this device is from Target_Core_Mod/pSCSI, use the ALUA logic
-        * of the Underlying SCSI hardware.  In Linux/SCSI terms, this can
-        * cause a problem because libata and some SATA RAID HBAs appear
-        * under Linux/SCSI, but emulate SCSI logic themselves.
-        */
-       if ((dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) ||
-           (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV &&
-            !dev->dev_attrib.emulate_alua)) {
-               pr_debug("%s: Using SPC_ALUA_PASSTHROUGH, no ALUA"
-                       " emulation\n", dev->transport->name);
-
-               alua->alua_type = SPC_ALUA_PASSTHROUGH;
-               alua->alua_state_check = &core_alua_state_check_nop;
-       } else if (dev->transport->get_device_rev(dev) >= SCSI_3) {
-               pr_debug("%s: Enabling ALUA Emulation for SPC-3"
-                       " device\n", dev->transport->name);
+       if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV &&
+           !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
+               struct t10_alua_lu_gp_member *lu_gp_mem;
 
                /*
                 * Associate this struct se_device with the default ALUA
@@ -2079,8 +2046,6 @@ int core_setup_alua(struct se_device *dev)
                if (IS_ERR(lu_gp_mem))
                        return PTR_ERR(lu_gp_mem);
 
-               alua->alua_type = SPC3_ALUA_EMULATED;
-               alua->alua_state_check = &core_alua_state_check;
                spin_lock(&lu_gp_mem->lu_gp_mem_lock);
                __core_alua_attach_lu_gp_mem(lu_gp_mem,
                                default_lu_gp);
@@ -2089,12 +2054,6 @@ int core_setup_alua(struct se_device *dev)
                pr_debug("%s: Adding to default ALUA LU Group:"
                        " core/alua/lu_gps/default_lu_gp\n",
                        dev->transport->name);
-       } else {
-               pr_debug("%s: Disabling ALUA Emulation for SPC-2"
-                       " device\n", dev->transport->name);
-
-               alua->alua_type = SPC2_ALUA_DISABLED;
-               alua->alua_state_check = &core_alua_state_check_nop;
        }
 
        return 0;