From 0fd97ccf45be26fb01b3a412f1f6c6b5044b2f16 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 8 Oct 2012 00:03:19 -0400 Subject: target: kill struct se_subsystem_dev Simplify the code a lot by killing the superflous struct se_subsystem_dev. Instead se_device is allocated early on by the backend driver, which allocates it as part of its own per-device structure, borrowing the scheme that is for example used for inode allocation. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h index 7b54893..dd7a84e 100644 --- a/drivers/target/loopback/tcm_loop.h +++ b/drivers/target/loopback/tcm_loop.h @@ -53,7 +53,6 @@ struct tcm_loop_hba { struct se_hba_s *se_hba; struct se_lun *tl_hba_lun; struct se_port *tl_hba_lun_sep; - struct se_device_s *se_dev_hba_ptr; struct tcm_loop_nexus *tl_nexus; struct device dev; struct Scsi_Host *sh; diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 9a5f9a7..15c127b 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -61,7 +61,7 @@ struct t10_alua_lu_gp *default_lu_gp; */ int target_emulate_report_target_port_groups(struct se_cmd *cmd) { - struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct se_port *port; struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; @@ -86,8 +86,8 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) } buf = transport_kmap_data_sg(cmd); - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); - list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, + spin_lock(&dev->t10_alua.tg_pt_gps_lock); + list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, tg_pt_gp_list) { /* * Check if the Target port group and Target port descriptor list @@ -160,7 +160,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) } spin_unlock(&tg_pt_gp->tg_pt_gp_lock); } - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); /* * Set the RETURN DATA LENGTH set in the header of the DataIN Payload */ @@ -203,7 +203,6 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) int target_emulate_set_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct se_port *port, *l_port = cmd->se_lun->lun_sep; struct se_node_acl *nacl = cmd->se_sess->se_node_acl; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; @@ -303,9 +302,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * Locate the matching target port group ID from * the global tg_pt_gp list */ - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, - &su_dev->t10_alua.tg_pt_gps_list, + &dev->t10_alua.tg_pt_gps_list, tg_pt_gp_list) { if (!tg_pt_gp->tg_pt_gp_valid_id) continue; @@ -315,18 +314,18 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_inc(); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); rc = core_alua_do_port_transition(tg_pt_gp, dev, l_port, nacl, alua_access_state, 1); - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_dec(); break; } - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); /* * If not matching target port group ID can be located * throw an exception with ASCQ: INVALID_PARAMETER_LIST @@ -758,8 +757,7 @@ static int core_alua_update_tpg_primary_metadata( int primary_state, unsigned char *md_buf) { - struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; - struct t10_wwn *wwn = &su_dev->t10_wwn; + struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; char path[ALUA_METADATA_PATH_LEN]; int len; @@ -899,7 +897,6 @@ int core_alua_do_port_transition( { struct se_device *dev; struct se_port *port; - struct se_subsystem_dev *su_dev; struct se_node_acl *nacl; struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; @@ -949,14 +946,13 @@ int core_alua_do_port_transition( lu_gp_mem_list) { dev = lu_gp_mem->lu_gp_mem_dev; - su_dev = dev->se_sub_dev; atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt); smp_mb__after_atomic_inc(); spin_unlock(&lu_gp->lu_gp_lock); - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, - &su_dev->t10_alua.tg_pt_gps_list, + &dev->t10_alua.tg_pt_gps_list, tg_pt_gp_list) { if (!tg_pt_gp->tg_pt_gp_valid_id) @@ -981,7 +977,7 @@ int core_alua_do_port_transition( } atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_inc(); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); /* * core_alua_do_transition_tg_pt() will always return * success. @@ -989,11 +985,11 @@ int core_alua_do_port_transition( core_alua_do_transition_tg_pt(tg_pt_gp, port, nacl, md_buf, new_state, explict); - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_dec(); } - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); spin_lock(&lu_gp->lu_gp_lock); atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt); @@ -1268,8 +1264,7 @@ 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 se_subsystem_dev *su_dev = dev->se_sub_dev; - struct t10_alua *alua = &su_dev->t10_alua; + struct t10_alua *alua = &dev->t10_alua; struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp_member *lu_gp_mem; @@ -1358,10 +1353,8 @@ void __core_alua_drop_lu_gp_mem( spin_unlock(&lu_gp->lu_gp_lock); } -struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( - struct se_subsystem_dev *su_dev, - const char *name, - int def_group) +struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, + const char *name, int def_group) { struct t10_alua_tg_pt_gp *tg_pt_gp; @@ -1375,7 +1368,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); - tg_pt_gp->tg_pt_gp_su_dev = su_dev; + tg_pt_gp->tg_pt_gp_dev = dev; tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN; atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, ALUA_ACCESS_STATE_ACTIVE_OPTMIZED); @@ -1392,14 +1385,14 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( 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); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); tg_pt_gp->tg_pt_gp_id = - su_dev->t10_alua.alua_tg_pt_gps_counter++; + dev->t10_alua.alua_tg_pt_gps_counter++; tg_pt_gp->tg_pt_gp_valid_id = 1; - su_dev->t10_alua.alua_tg_pt_gps_count++; + dev->t10_alua.alua_tg_pt_gps_count++; list_add_tail(&tg_pt_gp->tg_pt_gp_list, - &su_dev->t10_alua.tg_pt_gps_list); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + &dev->t10_alua.tg_pt_gps_list); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); } return tg_pt_gp; @@ -1409,9 +1402,10 @@ int core_alua_set_tg_pt_gp_id( struct t10_alua_tg_pt_gp *tg_pt_gp, u16 tg_pt_gp_id) { - struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; + struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; struct t10_alua_tg_pt_gp *tg_pt_gp_tmp; u16 tg_pt_gp_id_tmp; + /* * The tg_pt_gp->tg_pt_gp_id may only be set once.. */ @@ -1421,19 +1415,19 @@ int core_alua_set_tg_pt_gp_id( return -EINVAL; } - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); - if (su_dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { + spin_lock(&dev->t10_alua.tg_pt_gps_lock); + if (dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { pr_err("Maximum ALUA alua_tg_pt_gps_count:" " 0x0000ffff reached\n"); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); return -ENOSPC; } again: tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id : - su_dev->t10_alua.alua_tg_pt_gps_counter++; + dev->t10_alua.alua_tg_pt_gps_counter++; - list_for_each_entry(tg_pt_gp_tmp, &su_dev->t10_alua.tg_pt_gps_list, + list_for_each_entry(tg_pt_gp_tmp, &dev->t10_alua.tg_pt_gps_list, tg_pt_gp_list) { if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) { if (!tg_pt_gp_id) @@ -1441,7 +1435,7 @@ again: pr_err("ALUA Target Port Group ID: %hu already" " exists, ignoring request\n", tg_pt_gp_id); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); return -EINVAL; } } @@ -1449,9 +1443,9 @@ again: tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp; tg_pt_gp->tg_pt_gp_valid_id = 1; list_add_tail(&tg_pt_gp->tg_pt_gp_list, - &su_dev->t10_alua.tg_pt_gps_list); - su_dev->t10_alua.alua_tg_pt_gps_count++; - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + &dev->t10_alua.tg_pt_gps_list); + dev->t10_alua.alua_tg_pt_gps_count++; + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); return 0; } @@ -1480,8 +1474,9 @@ struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( void core_alua_free_tg_pt_gp( struct t10_alua_tg_pt_gp *tg_pt_gp) { - struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; + struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; + /* * Once we have reached this point, config_item_put() has already * been called from target_core_alua_drop_tg_pt_gp(). @@ -1490,10 +1485,11 @@ void core_alua_free_tg_pt_gp( * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS * can be made while we are releasing struct t10_alua_tg_pt_gp. */ - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_del(&tg_pt_gp->tg_pt_gp_list); - su_dev->t10_alua.alua_tg_pt_gps_counter--; - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + dev->t10_alua.alua_tg_pt_gps_counter--; + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); + /* * Allow a struct t10_alua_tg_pt_gp_member * referenced by * core_alua_get_tg_pt_gp_by_name() in @@ -1502,6 +1498,7 @@ void core_alua_free_tg_pt_gp( */ while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt)) cpu_relax(); + /* * Release reference to struct t10_alua_tg_pt_gp from all associated * struct se_port. @@ -1525,9 +1522,9 @@ void core_alua_free_tg_pt_gp( * default_tg_pt_gp. */ spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - if (tg_pt_gp != su_dev->t10_alua.default_tg_pt_gp) { + if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) { __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, - su_dev->t10_alua.default_tg_pt_gp); + dev->t10_alua.default_tg_pt_gp); } else tg_pt_gp_mem->tg_pt_gp = NULL; spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); @@ -1541,8 +1538,7 @@ void core_alua_free_tg_pt_gp( void core_alua_free_tg_pt_gp_mem(struct se_port *port) { - struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; - struct t10_alua *alua = &su_dev->t10_alua; + 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; @@ -1574,25 +1570,24 @@ void core_alua_free_tg_pt_gp_mem(struct se_port *port) } static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( - struct se_subsystem_dev *su_dev, - const char *name) + struct se_device *dev, const char *name) { struct t10_alua_tg_pt_gp *tg_pt_gp; struct config_item *ci; - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); - list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, + spin_lock(&dev->t10_alua.tg_pt_gps_lock); + list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, tg_pt_gp_list) { if (!tg_pt_gp->tg_pt_gp_valid_id) continue; ci = &tg_pt_gp->tg_pt_gp_group.cg_item; if (!strcmp(config_item_name(ci), name)) { atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); return tg_pt_gp; } } - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); return NULL; } @@ -1600,11 +1595,11 @@ static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( static void core_alua_put_tg_pt_gp_from_name( struct t10_alua_tg_pt_gp *tg_pt_gp) { - struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; + struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; - spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_lock(&dev->t10_alua.tg_pt_gps_lock); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); - spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); } /* @@ -1640,9 +1635,8 @@ 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 se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; struct config_item *tg_pt_ci; - struct t10_alua *alua = &su_dev->t10_alua; + 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; @@ -1683,7 +1677,7 @@ ssize_t core_alua_store_tg_pt_gp_info( { struct se_portal_group *tpg; struct se_lun *lun; - struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; + struct se_device *dev = port->sep_lun->lun_se_dev; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; unsigned char buf[TG_PT_GROUP_NAME_BUF]; @@ -1692,7 +1686,7 @@ ssize_t core_alua_store_tg_pt_gp_info( tpg = port->sep_tpg; lun = port->sep_lun; - if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { + 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), @@ -1716,7 +1710,7 @@ ssize_t core_alua_store_tg_pt_gp_info( * struct t10_alua_tg_pt_gp. This reference is released with * core_alua_put_tg_pt_gp_from_name() below. */ - tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(su_dev, + tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(dev, strstrip(buf)); if (!tg_pt_gp_new) return -ENODEV; @@ -1750,7 +1744,7 @@ ssize_t core_alua_store_tg_pt_gp_info( __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, - su_dev->t10_alua.default_tg_pt_gp); + dev->t10_alua.default_tg_pt_gp); spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); return count; @@ -2054,32 +2048,29 @@ ssize_t core_alua_store_secondary_write_metadata( return count; } -int core_setup_alua(struct se_device *dev, int force_pt) +int core_setup_alua(struct se_device *dev) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; - struct t10_alua *alua = &su_dev->t10_alua; + 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->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) && - !(dev->se_sub_dev->se_dev_attrib.emulate_alua)) || force_pt) { - alua->alua_type = SPC_ALUA_PASSTHROUGH; - alua->alua_state_check = &core_alua_state_check_nop; + 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); - return 0; - } - /* - * If SPC-3 or above is reported by real or emulated struct se_device, - * use emulated ALUA. - */ - if (dev->transport->get_device_rev(dev) >= SCSI_3) { + + 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); + /* * Associate this struct se_device with the default ALUA * LUN Group. @@ -2099,10 +2090,11 @@ int core_setup_alua(struct se_device *dev, int force_pt) " core/alua/lu_gps/default_lu_gp\n", dev->transport->name); } else { - alua->alua_type = SPC2_ALUA_DISABLED; - alua->alua_state_check = &core_alua_state_check_nop; 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; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index f920c17..5019157 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -91,7 +91,7 @@ extern void __core_alua_drop_lu_gp_mem(struct t10_alua_lu_gp_member *, struct t10_alua_lu_gp *); extern void core_alua_drop_lu_gp_dev(struct se_device *); extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( - struct se_subsystem_dev *, const char *, int); + struct se_device *, const char *, int); extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16); extern struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( struct se_port *); @@ -131,6 +131,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, char *); extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, const char *, size_t); -extern int core_setup_alua(struct se_device *, int); +extern int core_setup_alua(struct se_device *); #endif /* TARGET_CORE_ALUA_H */ diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index c123327..7272016 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -565,21 +565,8 @@ static ssize_t target_core_dev_show_attr_##_name( \ struct se_dev_attrib *da, \ char *page) \ { \ - struct se_device *dev; \ - struct se_subsystem_dev *se_dev = da->da_sub_dev; \ - ssize_t rb; \ - \ - spin_lock(&se_dev->se_dev_lock); \ - dev = se_dev->se_dev_ptr; \ - if (!dev) { \ - spin_unlock(&se_dev->se_dev_lock); \ - return -ENODEV; \ - } \ - rb = snprintf(page, PAGE_SIZE, "%u\n", \ - (u32)dev->se_sub_dev->se_dev_attrib._name); \ - spin_unlock(&se_dev->se_dev_lock); \ - \ - return rb; \ + return snprintf(page, PAGE_SIZE, "%u\n", \ + (u32)da->da_dev->dev_attrib._name); \ } #define DEF_DEV_ATTRIB_STORE(_name) \ @@ -588,26 +575,16 @@ static ssize_t target_core_dev_store_attr_##_name( \ const char *page, \ size_t count) \ { \ - struct se_device *dev; \ - struct se_subsystem_dev *se_dev = da->da_sub_dev; \ unsigned long val; \ int ret; \ \ - spin_lock(&se_dev->se_dev_lock); \ - dev = se_dev->se_dev_ptr; \ - if (!dev) { \ - spin_unlock(&se_dev->se_dev_lock); \ - return -ENODEV; \ - } \ ret = strict_strtoul(page, 0, &val); \ if (ret < 0) { \ - spin_unlock(&se_dev->se_dev_lock); \ pr_err("strict_strtoul() failed with" \ " ret: %d\n", ret); \ return -EINVAL; \ } \ - ret = se_dev_set_##_name(dev, (u32)val); \ - spin_unlock(&se_dev->se_dev_lock); \ + ret = se_dev_set_##_name(da->da_dev, (u32)val); \ \ return (!ret) ? count : -EINVAL; \ } @@ -764,13 +741,6 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial( struct t10_wwn *t10_wwn, char *page) { - struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; - struct se_device *dev; - - dev = se_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - return sprintf(page, "T10 VPD Unit Serial Number: %s\n", &t10_wwn->unit_serial[0]); } @@ -780,8 +750,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( const char *page, size_t count) { - struct se_subsystem_dev *su_dev = t10_wwn->t10_sub_dev; - struct se_device *dev; + struct se_device *dev = t10_wwn->t10_dev; unsigned char buf[INQUIRY_VPD_SERIAL_LEN]; /* @@ -794,7 +763,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( * it is doing 'the right thing' wrt a world wide unique * VPD Unit Serial Number that OS dependent multipath can depend on. */ - if (su_dev->su_dev_flags & SDF_FIRMWARE_VPD_UNIT_SERIAL) { + if (dev->dev_flags & DF_FIRMWARE_VPD_UNIT_SERIAL) { pr_err("Underlying SCSI device firmware provided VPD" " Unit Serial, ignoring request\n"); return -EOPNOTSUPP; @@ -811,15 +780,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( * (underneath the initiator side OS dependent multipath code) * could cause negative effects. */ - dev = su_dev->se_dev_ptr; - if (dev) { - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { - pr_err("Unable to set VPD Unit Serial while" - " active %d $FABRIC_MOD exports exist\n", - atomic_read(&dev->dev_export_obj.obj_access_count)); - return -EINVAL; - } + if (dev->export_count) { + pr_err("Unable to set VPD Unit Serial while" + " active %d $FABRIC_MOD exports exist\n", + dev->export_count); + return -EINVAL; } + /* * This currently assumes ASCII encoding for emulated VPD Unit Serial. * @@ -828,12 +795,12 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( */ memset(buf, 0, INQUIRY_VPD_SERIAL_LEN); snprintf(buf, INQUIRY_VPD_SERIAL_LEN, "%s", page); - snprintf(su_dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, + snprintf(dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, "%s", strstrip(buf)); - su_dev->su_dev_flags |= SDF_EMULATED_VPD_UNIT_SERIAL; + dev->dev_flags |= DF_EMULATED_VPD_UNIT_SERIAL; pr_debug("Target_Core_ConfigFS: Set emulated VPD Unit Serial:" - " %s\n", su_dev->t10_wwn.unit_serial); + " %s\n", dev->t10_wwn.unit_serial); return count; } @@ -847,16 +814,10 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier( struct t10_wwn *t10_wwn, char *page) { - struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; - struct se_device *dev; struct t10_vpd *vpd; unsigned char buf[VPD_TMP_BUF_SIZE]; ssize_t len = 0; - dev = se_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - memset(buf, 0, VPD_TMP_BUF_SIZE); spin_lock(&t10_wwn->t10_vpd_lock); @@ -894,16 +855,10 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \ struct t10_wwn *t10_wwn, \ char *page) \ { \ - struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; \ - struct se_device *dev; \ struct t10_vpd *vpd; \ unsigned char buf[VPD_TMP_BUF_SIZE]; \ ssize_t len = 0; \ \ - dev = se_dev->se_dev_ptr; \ - if (!dev) \ - return -ENODEV; \ - \ spin_lock(&t10_wwn->t10_vpd_lock); \ list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { \ if (vpd->association != _assoc) \ @@ -1003,7 +958,7 @@ static struct config_item_type target_core_dev_wwn_cit = { /* Start functions for struct config_item_type target_core_dev_pr_cit */ -CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_subsystem_dev); +CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device); #define SE_DEV_PR_ATTR(_name, _mode) \ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ __CONFIGFS_EATTR(_name, _mode, \ @@ -1071,23 +1026,17 @@ static ssize_t target_core_dev_pr_show_spc2_res( return *len; } -static ssize_t target_core_dev_pr_show_attr_res_holder( - struct se_subsystem_dev *su_dev, - char *page) +static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev, + char *page) { ssize_t len = 0; - if (!su_dev->se_dev_ptr) - return -ENODEV; - - switch (su_dev->t10_pr.res_type) { + switch (dev->t10_pr.res_type) { case SPC3_PERSISTENT_RESERVATIONS: - target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr, - page, &len); + target_core_dev_pr_show_spc3_res(dev, page, &len); break; case SPC2_RESERVATIONS: - target_core_dev_pr_show_spc2_res(su_dev->se_dev_ptr, - page, &len); + target_core_dev_pr_show_spc2_res(dev, page, &len); break; case SPC_PASSTHROUGH: len += sprintf(page+len, "Passthrough\n"); @@ -1102,22 +1051,13 @@ static ssize_t target_core_dev_pr_show_attr_res_holder( SE_DEV_PR_ATTR_RO(res_holder); -/* - * res_pr_all_tgt_pts - */ static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - struct se_device *dev; struct t10_pr_registration *pr_reg; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return len; spin_lock(&dev->dev_reservation_lock); @@ -1144,20 +1084,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); -/* - * res_pr_generation - */ static ssize_t target_core_dev_pr_show_attr_res_pr_generation( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - if (!su_dev->se_dev_ptr) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return 0; - return sprintf(page, "0x%08x\n", su_dev->t10_pr.pr_generation); + return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation); } SE_DEV_PR_ATTR_RO(res_pr_generation); @@ -1166,10 +1099,8 @@ SE_DEV_PR_ATTR_RO(res_pr_generation); * res_pr_holder_tg_port */ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - struct se_device *dev; struct se_node_acl *se_nacl; struct se_lun *lun; struct se_portal_group *se_tpg; @@ -1177,11 +1108,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( struct target_core_fabric_ops *tfo; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return len; spin_lock(&dev->dev_reservation_lock); @@ -1211,12 +1138,8 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port); -/* - * res_pr_registered_i_pts - */ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { struct target_core_fabric_ops *tfo; struct t10_pr_registration *pr_reg; @@ -1225,16 +1148,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( ssize_t len = 0; int reg_count = 0, prf_isid; - if (!su_dev->se_dev_ptr) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return len; len += sprintf(page+len, "SPC-3 PR Registrations:\n"); - spin_lock(&su_dev->t10_pr.registration_lock); - list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, + spin_lock(&dev->t10_pr.registration_lock); + list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { memset(buf, 0, 384); @@ -1254,7 +1174,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( len += sprintf(page+len, "%s", buf); reg_count++; } - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); if (!reg_count) len += sprintf(page+len, "None\n"); @@ -1264,22 +1184,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts); -/* - * res_pr_type - */ static ssize_t target_core_dev_pr_show_attr_res_pr_type( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - struct se_device *dev; struct t10_pr_registration *pr_reg; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return len; spin_lock(&dev->dev_reservation_lock); @@ -1298,19 +1209,12 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type( SE_DEV_PR_ATTR_RO(res_pr_type); -/* - * res_type - */ static ssize_t target_core_dev_pr_show_attr_res_type( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { ssize_t len = 0; - if (!su_dev->se_dev_ptr) - return -ENODEV; - - switch (su_dev->t10_pr.res_type) { + switch (dev->t10_pr.res_type) { case SPC3_PERSISTENT_RESERVATIONS: len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); break; @@ -1330,22 +1234,14 @@ static ssize_t target_core_dev_pr_show_attr_res_type( SE_DEV_PR_ATTR_RO(res_type); -/* - * res_aptpl_active - */ - static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - if (!su_dev->se_dev_ptr) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return 0; return sprintf(page, "APTPL Bit Status: %s\n", - (su_dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled"); + (dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled"); } SE_DEV_PR_ATTR_RO(res_aptpl_active); @@ -1354,13 +1250,9 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active); * res_aptpl_metadata */ static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - if (!su_dev->se_dev_ptr) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return 0; return sprintf(page, "Ready to process PR APTPL metadata..\n"); @@ -1392,11 +1284,10 @@ static match_table_t tokens = { }; static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( - struct se_subsystem_dev *su_dev, + struct se_device *dev, const char *page, size_t count) { - struct se_device *dev; unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; unsigned char *t_fabric = NULL, *t_port = NULL; char *orig, *ptr, *arg_p, *opts; @@ -1408,14 +1299,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( u16 port_rpti = 0, tpgt = 0; u8 type = 0, scope; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return 0; - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_debug("Unable to process APTPL metadata while" " active fabric exports exist\n"); return -EINVAL; @@ -1558,7 +1445,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( goto out; } - ret = core_scsi3_alloc_aptpl_registration(&su_dev->t10_pr, sa_res_key, + ret = core_scsi3_alloc_aptpl_registration(&dev->t10_pr, sa_res_key, i_port, isid, mapped_lun, t_port, tpgt, target_lun, res_holder, all_tg_pt, type); out: @@ -1573,7 +1460,7 @@ out: SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR); -CONFIGFS_EATTR_OPS(target_core_dev_pr, se_subsystem_dev, se_dev_pr_group); +CONFIGFS_EATTR_OPS(target_core_dev_pr, se_device, dev_pr_group); static struct configfs_attribute *target_core_dev_pr_attrs[] = { &target_core_dev_pr_res_holder.attr, @@ -1605,18 +1492,14 @@ static struct config_item_type target_core_dev_pr_cit = { static ssize_t target_core_show_dev_info(void *p, char *page) { - struct se_subsystem_dev *se_dev = p; - struct se_hba *hba = se_dev->se_dev_hba; - struct se_subsystem_api *t = hba->transport; + struct se_device *dev = p; + struct se_subsystem_api *t = dev->transport; int bl = 0; ssize_t read_bytes = 0; - if (!se_dev->se_dev_ptr) - return -ENODEV; - - transport_dump_dev_state(se_dev->se_dev_ptr, page, &bl); + transport_dump_dev_state(dev, page, &bl); read_bytes += bl; - read_bytes += t->show_configfs_dev_params(hba, se_dev, page+read_bytes); + read_bytes += t->show_configfs_dev_params(dev, page+read_bytes); return read_bytes; } @@ -1633,17 +1516,10 @@ static ssize_t target_core_store_dev_control( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = p; - struct se_hba *hba = se_dev->se_dev_hba; - struct se_subsystem_api *t = hba->transport; + struct se_device *dev = p; + struct se_subsystem_api *t = dev->transport; - if (!se_dev->se_dev_su_ptr) { - pr_err("Unable to locate struct se_subsystem_dev>se" - "_dev_su_ptr\n"); - return -EINVAL; - } - - return t->set_configfs_dev_params(hba, se_dev, page, count); + return t->set_configfs_dev_params(dev, page, count); } static struct target_core_configfs_attribute target_core_attr_dev_control = { @@ -1656,12 +1532,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_control = { static ssize_t target_core_show_dev_alias(void *p, char *page) { - struct se_subsystem_dev *se_dev = p; + struct se_device *dev = p; - if (!(se_dev->su_dev_flags & SDF_USING_ALIAS)) + if (!(dev->dev_flags & DF_USING_ALIAS)) return 0; - return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_alias); + return snprintf(page, PAGE_SIZE, "%s\n", dev->dev_alias); } static ssize_t target_core_store_dev_alias( @@ -1669,8 +1545,8 @@ static ssize_t target_core_store_dev_alias( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = p; - struct se_hba *hba = se_dev->se_dev_hba; + struct se_device *dev = p; + struct se_hba *hba = dev->se_hba; ssize_t read_bytes; if (count > (SE_DEV_ALIAS_LEN-1)) { @@ -1680,19 +1556,18 @@ static ssize_t target_core_store_dev_alias( return -EINVAL; } - read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN, - "%s", page); + read_bytes = snprintf(&dev->dev_alias[0], SE_DEV_ALIAS_LEN, "%s", page); if (!read_bytes) return -EINVAL; - if (se_dev->se_dev_alias[read_bytes - 1] == '\n') - se_dev->se_dev_alias[read_bytes - 1] = '\0'; + if (dev->dev_alias[read_bytes - 1] == '\n') + dev->dev_alias[read_bytes - 1] = '\0'; - se_dev->su_dev_flags |= SDF_USING_ALIAS; + dev->dev_flags |= DF_USING_ALIAS; pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&se_dev->se_dev_group.cg_item), - se_dev->se_dev_alias); + config_item_name(&dev->dev_group.cg_item), + dev->dev_alias); return read_bytes; } @@ -1707,12 +1582,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_alias = { static ssize_t target_core_show_dev_udev_path(void *p, char *page) { - struct se_subsystem_dev *se_dev = p; + struct se_device *dev = p; - if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) + if (!(dev->dev_flags & DF_USING_UDEV_PATH)) return 0; - return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_udev_path); + return snprintf(page, PAGE_SIZE, "%s\n", dev->udev_path); } static ssize_t target_core_store_dev_udev_path( @@ -1720,8 +1595,8 @@ static ssize_t target_core_store_dev_udev_path( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = p; - struct se_hba *hba = se_dev->se_dev_hba; + struct se_device *dev = p; + struct se_hba *hba = dev->se_hba; ssize_t read_bytes; if (count > (SE_UDEV_PATH_LEN-1)) { @@ -1731,19 +1606,19 @@ static ssize_t target_core_store_dev_udev_path( return -EINVAL; } - read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN, + read_bytes = snprintf(&dev->udev_path[0], SE_UDEV_PATH_LEN, "%s", page); if (!read_bytes) return -EINVAL; - if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n') - se_dev->se_dev_udev_path[read_bytes - 1] = '\0'; + if (dev->udev_path[read_bytes - 1] == '\n') + dev->udev_path[read_bytes - 1] = '\0'; - se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; + dev->dev_flags |= DF_USING_UDEV_PATH; pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&se_dev->se_dev_group.cg_item), - se_dev->se_dev_udev_path); + config_item_name(&dev->dev_group.cg_item), + dev->udev_path); return read_bytes; } @@ -1761,11 +1636,9 @@ static ssize_t target_core_store_dev_enable( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = p; - struct se_device *dev; - struct se_hba *hba = se_dev->se_dev_hba; - struct se_subsystem_api *t = hba->transport; + struct se_device *dev = p; char *ptr; + int ret; ptr = strstr(page, "1"); if (!ptr) { @@ -1773,25 +1646,10 @@ static ssize_t target_core_store_dev_enable( " is \"1\"\n"); return -EINVAL; } - if (se_dev->se_dev_ptr) { - pr_err("se_dev->se_dev_ptr already set for storage" - " object\n"); - return -EEXIST; - } - - if (t->check_configfs_dev_params(hba, se_dev) < 0) - return -EINVAL; - - dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); - if (IS_ERR(dev)) - return PTR_ERR(dev); - else if (!dev) - return -EINVAL; - - se_dev->se_dev_ptr = dev; - pr_debug("Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:" - " %p\n", se_dev->se_dev_ptr); + ret = target_configure_device(dev); + if (ret) + return ret; return count; } @@ -1805,18 +1663,13 @@ static struct target_core_configfs_attribute target_core_attr_dev_enable = { static ssize_t target_core_show_alua_lu_gp(void *p, char *page) { - struct se_device *dev; - struct se_subsystem_dev *su_dev = p; + struct se_device *dev = p; struct config_item *lu_ci; struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp_member *lu_gp_mem; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) + if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) return len; lu_gp_mem = dev->dev_alua_lu_gp_mem; @@ -1843,22 +1696,17 @@ static ssize_t target_core_store_alua_lu_gp( const char *page, size_t count) { - struct se_device *dev; - struct se_subsystem_dev *su_dev = p; - struct se_hba *hba = su_dev->se_dev_hba; + struct se_device *dev = p; + struct se_hba *hba = dev->se_hba; struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL; struct t10_alua_lu_gp_member *lu_gp_mem; unsigned char buf[LU_GROUP_NAME_BUF]; int move = 0; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { + if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { pr_warn("SPC3_ALUA_EMULATED not enabled for %s/%s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item)); + config_item_name(&dev->dev_group.cg_item)); return -EINVAL; } if (count > LU_GROUP_NAME_BUF) { @@ -1902,7 +1750,7 @@ static ssize_t target_core_store_alua_lu_gp( " from ALUA LU Group: core/alua/lu_gps/%s, ID:" " %hu\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item), + config_item_name(&dev->dev_group.cg_item), config_item_name(&lu_gp->lu_gp_group.cg_item), lu_gp->lu_gp_id); @@ -1927,7 +1775,7 @@ static ssize_t target_core_store_alua_lu_gp( " core/alua/lu_gps/%s, ID: %hu\n", (move) ? "Moving" : "Adding", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item), + config_item_name(&dev->dev_group.cg_item), config_item_name(&lu_gp_new->lu_gp_group.cg_item), lu_gp_new->lu_gp_id); @@ -1955,69 +1803,44 @@ static struct configfs_attribute *lio_core_dev_attrs[] = { static void target_core_dev_release(struct config_item *item) { - struct se_subsystem_dev *se_dev = container_of(to_config_group(item), - struct se_subsystem_dev, se_dev_group); - struct se_hba *hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); - struct se_subsystem_api *t = hba->transport; - struct config_group *dev_cg = &se_dev->se_dev_group; + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); kfree(dev_cg->default_groups); - /* - * This pointer will set when the storage is enabled with: - *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable` - */ - if (se_dev->se_dev_ptr) { - pr_debug("Target_Core_ConfigFS: Calling se_free_" - "virtual_device() for se_dev_ptr: %p\n", - se_dev->se_dev_ptr); - - se_free_virtual_device(se_dev->se_dev_ptr, hba); - } else { - /* - * Release struct se_subsystem_dev->se_dev_su_ptr.. - */ - pr_debug("Target_Core_ConfigFS: Calling t->free_" - "device() for se_dev_su_ptr: %p\n", - se_dev->se_dev_su_ptr); - - t->free_device(se_dev->se_dev_su_ptr); - } - - pr_debug("Target_Core_ConfigFS: Deallocating se_subsystem" - "_dev_t: %p\n", se_dev); - kfree(se_dev); + target_free_device(dev); } static ssize_t target_core_dev_show(struct config_item *item, struct configfs_attribute *attr, char *page) { - struct se_subsystem_dev *se_dev = container_of( - to_config_group(item), struct se_subsystem_dev, - se_dev_group); + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); struct target_core_configfs_attribute *tc_attr = container_of( attr, struct target_core_configfs_attribute, attr); if (!tc_attr->show) return -EINVAL; - return tc_attr->show(se_dev, page); + return tc_attr->show(dev, page); } static ssize_t target_core_dev_store(struct config_item *item, struct configfs_attribute *attr, const char *page, size_t count) { - struct se_subsystem_dev *se_dev = container_of( - to_config_group(item), struct se_subsystem_dev, - se_dev_group); + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); struct target_core_configfs_attribute *tc_attr = container_of( attr, struct target_core_configfs_attribute, attr); if (!tc_attr->store) return -EINVAL; - return tc_attr->store(se_dev, page, count); + return tc_attr->store(dev, page, count); } static struct configfs_item_operations target_core_dev_item_ops = { @@ -2107,7 +1930,6 @@ static ssize_t target_core_alua_lu_gp_show_attr_members( { struct se_device *dev; struct se_hba *hba; - struct se_subsystem_dev *su_dev; struct t10_alua_lu_gp_member *lu_gp_mem; ssize_t len = 0, cur_len; unsigned char buf[LU_GROUP_NAME_BUF]; @@ -2117,12 +1939,11 @@ static ssize_t target_core_alua_lu_gp_show_attr_members( spin_lock(&lu_gp->lu_gp_lock); list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { dev = lu_gp_mem->lu_gp_mem_dev; - su_dev = dev->se_sub_dev; - hba = su_dev->se_dev_hba; + hba = dev->se_hba; cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item)); + config_item_name(&dev->dev_group.cg_item)); cur_len++; /* Extra byte for NULL terminator */ if ((cur_len + len) > PAGE_SIZE) { @@ -2260,7 +2081,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( const char *page, size_t count) { - struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; + struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; unsigned long tmp; int new_state, ret; @@ -2284,7 +2105,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( return -EINVAL; } - ret = core_alua_do_port_transition(tg_pt_gp, su_dev->se_dev_ptr, + ret = core_alua_do_port_transition(tg_pt_gp, dev, NULL, NULL, new_state, 0); return (!ret) ? count : -EINVAL; } @@ -2620,11 +2441,10 @@ static struct config_group *target_core_alua_create_tg_pt_gp( struct t10_alua *alua = container_of(group, struct t10_alua, alua_tg_pt_gps_group); struct t10_alua_tg_pt_gp *tg_pt_gp; - struct se_subsystem_dev *su_dev = alua->t10_sub_dev; struct config_group *alua_tg_pt_gp_cg = NULL; struct config_item *alua_tg_pt_gp_ci = NULL; - tg_pt_gp = core_alua_allocate_tg_pt_gp(su_dev, name, 0); + tg_pt_gp = core_alua_allocate_tg_pt_gp(alua->t10_dev, name, 0); if (!tg_pt_gp) return NULL; @@ -2721,10 +2541,10 @@ static struct config_group *target_core_make_subdev( const char *name) { struct t10_alua_tg_pt_gp *tg_pt_gp; - struct se_subsystem_dev *se_dev; struct se_subsystem_api *t; struct config_item *hba_ci = &group->cg_item; struct se_hba *hba = item_to_hba(hba_ci); + struct se_device *dev; struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; struct config_group *dev_stat_grp = NULL; int errno = -ENOMEM, ret; @@ -2737,120 +2557,80 @@ static struct config_group *target_core_make_subdev( */ t = hba->transport; - se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL); - if (!se_dev) { - pr_err("Unable to allocate memory for" - " struct se_subsystem_dev\n"); - goto unlock; - } - INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); - spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); - INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); - INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list); - spin_lock_init(&se_dev->t10_pr.registration_lock); - spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock); - INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list); - spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock); - spin_lock_init(&se_dev->se_dev_lock); - se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; - se_dev->t10_wwn.t10_sub_dev = se_dev; - se_dev->t10_alua.t10_sub_dev = se_dev; - se_dev->se_dev_attrib.da_sub_dev = se_dev; - - se_dev->se_dev_hba = hba; - dev_cg = &se_dev->se_dev_group; + dev = target_alloc_device(hba, name); + if (!dev) + goto out_unlock; + + dev_cg = &dev->dev_group; dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, GFP_KERNEL); if (!dev_cg->default_groups) - goto out; - /* - * Set se_dev_su_ptr from struct se_subsystem_api returned void ptr - * for ->allocate_virtdevice() - * - * se_dev->se_dev_ptr will be set after ->create_virtdev() - * has been called successfully in the next level up in the - * configfs tree for device object's struct config_group. - */ - se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, name); - if (!se_dev->se_dev_su_ptr) { - pr_err("Unable to locate subsystem dependent pointer" - " from allocate_virtdevice()\n"); - goto out; - } + goto out_free_device; - config_group_init_type_name(&se_dev->se_dev_group, name, - &target_core_dev_cit); - config_group_init_type_name(&se_dev->se_dev_attrib.da_group, "attrib", + config_group_init_type_name(dev_cg, name, &target_core_dev_cit); + config_group_init_type_name(&dev->dev_attrib.da_group, "attrib", &target_core_dev_attrib_cit); - config_group_init_type_name(&se_dev->se_dev_pr_group, "pr", + config_group_init_type_name(&dev->dev_pr_group, "pr", &target_core_dev_pr_cit); - config_group_init_type_name(&se_dev->t10_wwn.t10_wwn_group, "wwn", + config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", &target_core_dev_wwn_cit); - config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, + config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, "alua", &target_core_alua_tg_pt_gps_cit); - config_group_init_type_name(&se_dev->dev_stat_grps.stat_group, + config_group_init_type_name(&dev->dev_stat_grps.stat_group, "statistics", &target_core_stat_cit); - dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; - dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; - dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; - dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; - dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group; + dev_cg->default_groups[0] = &dev->dev_attrib.da_group; + dev_cg->default_groups[1] = &dev->dev_pr_group; + dev_cg->default_groups[2] = &dev->t10_wwn.t10_wwn_group; + dev_cg->default_groups[3] = &dev->t10_alua.alua_tg_pt_gps_group; + dev_cg->default_groups[4] = &dev->dev_stat_grps.stat_group; dev_cg->default_groups[5] = NULL; /* * Add core/$HBA/$DEV/alua/default_tg_pt_gp */ - tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); + tg_pt_gp = core_alua_allocate_tg_pt_gp(dev, "default_tg_pt_gp", 1); if (!tg_pt_gp) - goto out; + goto out_free_dev_cg_default_groups; + dev->t10_alua.default_tg_pt_gp = tg_pt_gp; - tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group; + tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, GFP_KERNEL); if (!tg_pt_gp_cg->default_groups) { pr_err("Unable to allocate tg_pt_gp_cg->" "default_groups\n"); - goto out; + goto out_free_tg_pt_gp; } config_group_init_type_name(&tg_pt_gp->tg_pt_gp_group, "default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit); tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; tg_pt_gp_cg->default_groups[1] = NULL; - se_dev->t10_alua.default_tg_pt_gp = tg_pt_gp; /* * Add core/$HBA/$DEV/statistics/ default groups */ - dev_stat_grp = &se_dev->dev_stat_grps.stat_group; + dev_stat_grp = &dev->dev_stat_grps.stat_group; dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, GFP_KERNEL); if (!dev_stat_grp->default_groups) { pr_err("Unable to allocate dev_stat_grp->default_groups\n"); - goto out; + goto out_free_tg_pt_gp_cg_default_groups; } - target_stat_setup_dev_default_groups(se_dev); - - pr_debug("Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" - " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); + target_stat_setup_dev_default_groups(dev); mutex_unlock(&hba->hba_access_mutex); - return &se_dev->se_dev_group; -out: - if (se_dev->t10_alua.default_tg_pt_gp) { - core_alua_free_tg_pt_gp(se_dev->t10_alua.default_tg_pt_gp); - se_dev->t10_alua.default_tg_pt_gp = NULL; - } - if (dev_stat_grp) - kfree(dev_stat_grp->default_groups); - if (tg_pt_gp_cg) - kfree(tg_pt_gp_cg->default_groups); - if (dev_cg) - kfree(dev_cg->default_groups); - if (se_dev->se_dev_su_ptr) - t->free_device(se_dev->se_dev_su_ptr); - kfree(se_dev); -unlock: + return dev_cg; + +out_free_tg_pt_gp_cg_default_groups: + kfree(tg_pt_gp_cg->default_groups); +out_free_tg_pt_gp: + core_alua_free_tg_pt_gp(tg_pt_gp); +out_free_dev_cg_default_groups: + kfree(dev_cg->default_groups); +out_free_device: + target_free_device(dev); +out_unlock: mutex_unlock(&hba->hba_access_mutex); return ERR_PTR(errno); } @@ -2859,18 +2639,19 @@ static void target_core_drop_subdev( struct config_group *group, struct config_item *item) { - struct se_subsystem_dev *se_dev = container_of(to_config_group(item), - struct se_subsystem_dev, se_dev_group); + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); struct se_hba *hba; struct config_item *df_item; - struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp; + struct config_group *tg_pt_gp_cg, *dev_stat_grp; int i; - hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); + hba = item_to_hba(&dev->se_hba->hba_group.cg_item); mutex_lock(&hba->hba_access_mutex); - dev_stat_grp = &se_dev->dev_stat_grps.stat_group; + dev_stat_grp = &dev->dev_stat_grps.stat_group; for (i = 0; dev_stat_grp->default_groups[i]; i++) { df_item = &dev_stat_grp->default_groups[i]->cg_item; dev_stat_grp->default_groups[i] = NULL; @@ -2878,7 +2659,7 @@ static void target_core_drop_subdev( } kfree(dev_stat_grp->default_groups); - tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group; + tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; tg_pt_gp_cg->default_groups[i] = NULL; @@ -2889,17 +2670,15 @@ static void target_core_drop_subdev( * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp * directly from target_core_alua_tg_pt_gp_release(). */ - se_dev->t10_alua.default_tg_pt_gp = NULL; + dev->t10_alua.default_tg_pt_gp = NULL; - dev_cg = &se_dev->se_dev_group; for (i = 0; dev_cg->default_groups[i]; i++) { df_item = &dev_cg->default_groups[i]->cg_item; dev_cg->default_groups[i] = NULL; config_item_put(df_item); } /* - * The releasing of se_dev and associated se_dev->se_dev_ptr is done - * from target_core_dev_item_ops->release() ->target_core_dev_release(). + * se_dev is released from target_core_dev_item_ops->release() */ config_item_put(item); mutex_unlock(&hba->hba_access_mutex); @@ -2962,13 +2741,10 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba, return -EINVAL; } - spin_lock(&hba->device_lock); - if (!list_empty(&hba->hba_dev_list)) { + if (hba->dev_count) { pr_err("Unable to set hba_mode with active devices\n"); - spin_unlock(&hba->device_lock); return -EINVAL; } - spin_unlock(&hba->device_lock); ret = transport->pmode_enable_hba(hba, mode_flag); if (ret < 0) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 9abef9f..b27c75a 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -50,11 +50,7 @@ #include "target_core_pr.h" #include "target_core_ua.h" -static void se_dev_start(struct se_device *dev); -static void se_dev_stop(struct se_device *dev); - static struct se_hba *lun0_hba; -static struct se_subsystem_dev *lun0_su_dev; /* not static, needed by tpg.c */ struct se_device *g_lun0_dev; @@ -136,15 +132,6 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) se_cmd->orig_fe_lun = 0; se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; } - /* - * Determine if the struct se_lun is online. - * FIXME: Check for LUN_RESET + UNIT Attention - */ - if (se_dev_check_online(se_lun->lun_se_dev) != 0) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -ENODEV; - } /* Directly associate cmd with se_dev */ se_cmd->se_dev = se_lun->lun_se_dev; @@ -202,14 +189,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return -ENODEV; } - /* - * Determine if the struct se_lun is online. - * FIXME: Check for LUN_RESET + UNIT Attention - */ - if (se_dev_check_online(se_lun->lun_se_dev) != 0) { - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -ENODEV; - } /* Directly associate cmd with se_dev */ se_cmd->se_dev = se_lun->lun_se_dev; @@ -565,7 +544,6 @@ static void core_export_port( struct se_port *port, struct se_lun *lun) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem = NULL; spin_lock(&dev->se_port_lock); @@ -578,7 +556,7 @@ static void core_export_port( list_add_tail(&port->sep_list, &dev->dev_sep_list); spin_unlock(&dev->se_port_lock); - if (su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if (dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port); if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) { pr_err("Unable to allocate t10_alua_tg_pt" @@ -587,7 +565,7 @@ static void core_export_port( } spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, - su_dev->t10_alua.default_tg_pt_gp); + dev->t10_alua.default_tg_pt_gp); spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); pr_debug("%s/%s: Adding to default ALUA Target Port" " Group: alua/default_tg_pt_gp\n", @@ -625,6 +603,7 @@ int core_dev_export( struct se_portal_group *tpg, struct se_lun *lun) { + struct se_hba *hba = dev->se_hba; struct se_port *port; port = core_alloc_port(dev); @@ -632,9 +611,11 @@ int core_dev_export( return PTR_ERR(port); lun->lun_se_dev = dev; - se_dev_start(dev); - atomic_inc(&dev->dev_export_obj.obj_access_count); + spin_lock(&hba->device_lock); + dev->export_count++; + spin_unlock(&hba->device_lock); + core_export_port(dev, tpg, port, lun); return 0; } @@ -644,6 +625,7 @@ void core_dev_unexport( struct se_portal_group *tpg, struct se_lun *lun) { + struct se_hba *hba = dev->se_hba; struct se_port *port = lun->lun_sep; spin_lock(&lun->lun_sep_lock); @@ -654,11 +636,13 @@ void core_dev_unexport( spin_unlock(&lun->lun_sep_lock); spin_lock(&dev->se_port_lock); - atomic_dec(&dev->dev_export_obj.obj_access_count); core_release_port(dev, port); spin_unlock(&dev->se_port_lock); - se_dev_stop(dev); + spin_lock(&hba->device_lock); + dev->export_count--; + spin_unlock(&hba->device_lock); + lun->lun_se_dev = NULL; } @@ -725,127 +709,17 @@ done: return 0; } -/* se_release_device_for_hba(): - * - * - */ -void se_release_device_for_hba(struct se_device *dev) -{ - struct se_hba *hba = dev->se_hba; - - if ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) || - (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) || - (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN) || - (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_ACTIVATED) || - (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_DEACTIVATED)) - se_dev_stop(dev); - - if (dev->dev_ptr) { - destroy_workqueue(dev->tmr_wq); - if (dev->transport->free_device) - dev->transport->free_device(dev->dev_ptr); - } - - spin_lock(&hba->device_lock); - list_del(&dev->dev_list); - hba->dev_count--; - spin_unlock(&hba->device_lock); - - core_scsi3_free_all_registrations(dev); - se_release_vpd_for_dev(dev); - - kfree(dev); -} - -void se_release_vpd_for_dev(struct se_device *dev) +static void se_release_vpd_for_dev(struct se_device *dev) { struct t10_vpd *vpd, *vpd_tmp; - spin_lock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock); + spin_lock(&dev->t10_wwn.t10_vpd_lock); list_for_each_entry_safe(vpd, vpd_tmp, - &dev->se_sub_dev->t10_wwn.t10_vpd_list, vpd_list) { + &dev->t10_wwn.t10_vpd_list, vpd_list) { list_del(&vpd->vpd_list); kfree(vpd); } - spin_unlock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock); -} - -/* se_free_virtual_device(): - * - * Used for IBLOCK, RAMDISK, and FILEIO Transport Drivers. - */ -int se_free_virtual_device(struct se_device *dev, struct se_hba *hba) -{ - if (!list_empty(&dev->dev_sep_list)) - dump_stack(); - - core_alua_free_lu_gp_mem(dev); - se_release_device_for_hba(dev); - - return 0; -} - -static void se_dev_start(struct se_device *dev) -{ - struct se_hba *hba = dev->se_hba; - - spin_lock(&hba->device_lock); - atomic_inc(&dev->dev_obj.obj_access_count); - if (atomic_read(&dev->dev_obj.obj_access_count) == 1) { - if (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) { - dev->dev_status &= ~TRANSPORT_DEVICE_DEACTIVATED; - dev->dev_status |= TRANSPORT_DEVICE_ACTIVATED; - } else if (dev->dev_status & - TRANSPORT_DEVICE_OFFLINE_DEACTIVATED) { - dev->dev_status &= - ~TRANSPORT_DEVICE_OFFLINE_DEACTIVATED; - dev->dev_status |= TRANSPORT_DEVICE_OFFLINE_ACTIVATED; - } - } - spin_unlock(&hba->device_lock); -} - -static void se_dev_stop(struct se_device *dev) -{ - struct se_hba *hba = dev->se_hba; - - spin_lock(&hba->device_lock); - atomic_dec(&dev->dev_obj.obj_access_count); - if (atomic_read(&dev->dev_obj.obj_access_count) == 0) { - if (dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) { - dev->dev_status &= ~TRANSPORT_DEVICE_ACTIVATED; - dev->dev_status |= TRANSPORT_DEVICE_DEACTIVATED; - } else if (dev->dev_status & - TRANSPORT_DEVICE_OFFLINE_ACTIVATED) { - dev->dev_status &= ~TRANSPORT_DEVICE_OFFLINE_ACTIVATED; - dev->dev_status |= TRANSPORT_DEVICE_OFFLINE_DEACTIVATED; - } - } - spin_unlock(&hba->device_lock); -} - -int se_dev_check_online(struct se_device *dev) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&dev->dev_status_lock, flags); - ret = ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) || - (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED)) ? 0 : 1; - spin_unlock_irqrestore(&dev->dev_status_lock, flags); - - return ret; -} - -int se_dev_check_shutdown(struct se_device *dev) -{ - int ret; - - spin_lock_irq(&dev->dev_status_lock); - ret = (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN); - spin_unlock_irq(&dev->dev_status_lock); - - return ret; + spin_unlock(&dev->t10_wwn.t10_vpd_lock); } static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) @@ -866,72 +740,13 @@ static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) return aligned_max_sectors; } -void se_dev_set_default_attribs( - struct se_device *dev, - struct se_dev_limits *dev_limits) -{ - struct queue_limits *limits = &dev_limits->limits; - - dev->se_sub_dev->se_dev_attrib.emulate_dpo = DA_EMULATE_DPO; - dev->se_sub_dev->se_dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE; - dev->se_sub_dev->se_dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ; - dev->se_sub_dev->se_dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; - dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; - dev->se_sub_dev->se_dev_attrib.emulate_tas = DA_EMULATE_TAS; - dev->se_sub_dev->se_dev_attrib.emulate_tpu = DA_EMULATE_TPU; - dev->se_sub_dev->se_dev_attrib.emulate_tpws = DA_EMULATE_TPWS; - dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; - dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA; - dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; - dev->se_sub_dev->se_dev_attrib.is_nonrot = DA_IS_NONROT; - dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; - /* - * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK - * iblock_create_virtdevice() from struct queue_limits values - * if blk_queue_discard()==1 - */ - dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT; - dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = - DA_MAX_UNMAP_BLOCK_DESC_COUNT; - dev->se_sub_dev->se_dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; - dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = - DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; - /* - * block_size is based on subsystem plugin dependent requirements. - */ - dev->se_sub_dev->se_dev_attrib.hw_block_size = limits->logical_block_size; - dev->se_sub_dev->se_dev_attrib.block_size = limits->logical_block_size; - /* - * Align max_hw_sectors down to PAGE_SIZE I/O transfers - */ - limits->max_hw_sectors = se_dev_align_max_sectors(limits->max_hw_sectors, - limits->logical_block_size); - dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors; - - /* - * Set fabric_max_sectors, which is reported in block limits - * VPD page (B0h). - */ - dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; - /* - * Set optimal_sectors from fabric_max_sectors, which can be - * lowered via configfs. - */ - dev->se_sub_dev->se_dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; - /* - * queue_depth is based on subsystem plugin dependent requirements. - */ - dev->se_sub_dev->se_dev_attrib.hw_queue_depth = dev_limits->hw_queue_depth; - dev->se_sub_dev->se_dev_attrib.queue_depth = dev_limits->queue_depth; -} - int se_dev_set_max_unmap_lba_count( struct se_device *dev, u32 max_unmap_lba_count) { - dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = max_unmap_lba_count; + dev->dev_attrib.max_unmap_lba_count = max_unmap_lba_count; pr_debug("dev[%p]: Set max_unmap_lba_count: %u\n", - dev, dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count); + dev, dev->dev_attrib.max_unmap_lba_count); return 0; } @@ -939,10 +754,10 @@ int se_dev_set_max_unmap_block_desc_count( struct se_device *dev, u32 max_unmap_block_desc_count) { - dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = + dev->dev_attrib.max_unmap_block_desc_count = max_unmap_block_desc_count; pr_debug("dev[%p]: Set max_unmap_block_desc_count: %u\n", - dev, dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count); + dev, dev->dev_attrib.max_unmap_block_desc_count); return 0; } @@ -950,9 +765,9 @@ int se_dev_set_unmap_granularity( struct se_device *dev, u32 unmap_granularity) { - dev->se_sub_dev->se_dev_attrib.unmap_granularity = unmap_granularity; + dev->dev_attrib.unmap_granularity = unmap_granularity; pr_debug("dev[%p]: Set unmap_granularity: %u\n", - dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity); + dev, dev->dev_attrib.unmap_granularity); return 0; } @@ -960,9 +775,9 @@ int se_dev_set_unmap_granularity_alignment( struct se_device *dev, u32 unmap_granularity_alignment) { - dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment; + dev->dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment; pr_debug("dev[%p]: Set unmap_granularity_alignment: %u\n", - dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment); + dev, dev->dev_attrib.unmap_granularity_alignment); return 0; } @@ -993,9 +808,9 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) pr_err("emulate_fua_write not supported for pSCSI\n"); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag; + dev->dev_attrib.emulate_fua_write = flag; pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n", - dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_write); + dev, dev->dev_attrib.emulate_fua_write); return 0; } @@ -1025,9 +840,9 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) pr_err("emulate_write_cache not supported for pSCSI\n"); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag; + dev->dev_attrib.emulate_write_cache = flag; pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n", - dev, dev->se_sub_dev->se_dev_attrib.emulate_write_cache); + dev, dev->dev_attrib.emulate_write_cache); return 0; } @@ -1038,16 +853,15 @@ int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag) return -EINVAL; } - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_err("dev[%p]: Unable to change SE Device" - " UA_INTRLCK_CTRL while dev_export_obj: %d count" - " exists\n", dev, - atomic_read(&dev->dev_export_obj.obj_access_count)); + " UA_INTRLCK_CTRL while export_count is %d\n", + dev, dev->export_count); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = flag; + dev->dev_attrib.emulate_ua_intlck_ctrl = flag; pr_debug("dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n", - dev, dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl); + dev, dev->dev_attrib.emulate_ua_intlck_ctrl); return 0; } @@ -1059,15 +873,15 @@ int se_dev_set_emulate_tas(struct se_device *dev, int flag) return -EINVAL; } - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_err("dev[%p]: Unable to change SE Device TAS while" - " dev_export_obj: %d count exists\n", dev, - atomic_read(&dev->dev_export_obj.obj_access_count)); + " export_count is %d\n", + dev, dev->export_count); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.emulate_tas = flag; + dev->dev_attrib.emulate_tas = flag; pr_debug("dev[%p]: SE Device TASK_ABORTED status bit: %s\n", - dev, (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? "Enabled" : "Disabled"); + dev, (dev->dev_attrib.emulate_tas) ? "Enabled" : "Disabled"); return 0; } @@ -1082,12 +896,12 @@ int se_dev_set_emulate_tpu(struct se_device *dev, int flag) * We expect this value to be non-zero when generic Block Layer * Discard supported is detected iblock_create_virtdevice(). */ - if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + if (flag && !dev->dev_attrib.max_unmap_block_desc_count) { pr_err("Generic Block Discard not supported\n"); return -ENOSYS; } - dev->se_sub_dev->se_dev_attrib.emulate_tpu = flag; + dev->dev_attrib.emulate_tpu = flag; pr_debug("dev[%p]: SE Device Thin Provisioning UNMAP bit: %d\n", dev, flag); return 0; @@ -1103,12 +917,12 @@ int se_dev_set_emulate_tpws(struct se_device *dev, int flag) * We expect this value to be non-zero when generic Block Layer * Discard supported is detected iblock_create_virtdevice(). */ - if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + if (flag && !dev->dev_attrib.max_unmap_block_desc_count) { pr_err("Generic Block Discard not supported\n"); return -ENOSYS; } - dev->se_sub_dev->se_dev_attrib.emulate_tpws = flag; + dev->dev_attrib.emulate_tpws = flag; pr_debug("dev[%p]: SE Device Thin Provisioning WRITE_SAME: %d\n", dev, flag); return 0; @@ -1120,9 +934,9 @@ int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) pr_err("Illegal value %d\n", flag); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = flag; + dev->dev_attrib.enforce_pr_isids = flag; pr_debug("dev[%p]: SE Device enforce_pr_isids bit: %s\n", dev, - (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled"); + (dev->dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled"); return 0; } @@ -1132,7 +946,7 @@ int se_dev_set_is_nonrot(struct se_device *dev, int flag) printk(KERN_ERR "Illegal value %d\n", flag); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.is_nonrot = flag; + dev->dev_attrib.is_nonrot = flag; pr_debug("dev[%p]: SE Device is_nonrot bit: %d\n", dev, flag); return 0; @@ -1145,7 +959,7 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag) " reordering not implemented\n", dev); return -ENOSYS; } - dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = flag; + dev->dev_attrib.emulate_rest_reord = flag; pr_debug("dev[%p]: SE Device emulate_rest_reord: %d\n", dev, flag); return 0; } @@ -1155,10 +969,10 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag) */ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) { - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_err("dev[%p]: Unable to change SE Device TCQ while" - " dev_export_obj: %d count exists\n", dev, - atomic_read(&dev->dev_export_obj.obj_access_count)); + " export_count is %d\n", + dev, dev->export_count); return -EINVAL; } if (!queue_depth) { @@ -1168,26 +982,26 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) } if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) { + if (queue_depth > dev->dev_attrib.hw_queue_depth) { pr_err("dev[%p]: Passed queue_depth: %u" " exceeds TCM/SE_Device TCQ: %u\n", dev, queue_depth, - dev->se_sub_dev->se_dev_attrib.hw_queue_depth); + dev->dev_attrib.hw_queue_depth); return -EINVAL; } } else { - if (queue_depth > dev->se_sub_dev->se_dev_attrib.queue_depth) { - if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) { + if (queue_depth > dev->dev_attrib.queue_depth) { + if (queue_depth > dev->dev_attrib.hw_queue_depth) { pr_err("dev[%p]: Passed queue_depth:" " %u exceeds TCM/SE_Device MAX" " TCQ: %u\n", dev, queue_depth, - dev->se_sub_dev->se_dev_attrib.hw_queue_depth); + dev->dev_attrib.hw_queue_depth); return -EINVAL; } } } - dev->se_sub_dev->se_dev_attrib.queue_depth = dev->queue_depth = queue_depth; + dev->dev_attrib.queue_depth = dev->queue_depth = queue_depth; pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n", dev, queue_depth); return 0; @@ -1195,10 +1009,10 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) { - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_err("dev[%p]: Unable to change SE Device" - " fabric_max_sectors while dev_export_obj: %d count exists\n", - dev, atomic_read(&dev->dev_export_obj.obj_access_count)); + " fabric_max_sectors while export_count is %d\n", + dev, dev->export_count); return -EINVAL; } if (!fabric_max_sectors) { @@ -1213,11 +1027,11 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) return -EINVAL; } if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - if (fabric_max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) { + if (fabric_max_sectors > dev->dev_attrib.hw_max_sectors) { pr_err("dev[%p]: Passed fabric_max_sectors: %u" " greater than TCM/SE_Device max_sectors:" " %u\n", dev, fabric_max_sectors, - dev->se_sub_dev->se_dev_attrib.hw_max_sectors); + dev->dev_attrib.hw_max_sectors); return -EINVAL; } } else { @@ -1233,9 +1047,9 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() */ fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, - dev->se_sub_dev->se_dev_attrib.block_size); + dev->dev_attrib.block_size); - dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors; + dev->dev_attrib.fabric_max_sectors = fabric_max_sectors; pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", dev, fabric_max_sectors); return 0; @@ -1243,10 +1057,10 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) { - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_err("dev[%p]: Unable to change SE Device" - " optimal_sectors while dev_export_obj: %d count exists\n", - dev, atomic_read(&dev->dev_export_obj.obj_access_count)); + " optimal_sectors while export_count is %d\n", + dev, dev->export_count); return -EINVAL; } if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { @@ -1254,14 +1068,14 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) " changed for TCM/pSCSI\n", dev); return -EINVAL; } - if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.fabric_max_sectors) { + if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { pr_err("dev[%p]: Passed optimal_sectors %u cannot be" " greater than fabric_max_sectors: %u\n", dev, - optimal_sectors, dev->se_sub_dev->se_dev_attrib.fabric_max_sectors); + optimal_sectors, dev->dev_attrib.fabric_max_sectors); return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.optimal_sectors = optimal_sectors; + dev->dev_attrib.optimal_sectors = optimal_sectors; pr_debug("dev[%p]: SE Device optimal_sectors changed to %u\n", dev, optimal_sectors); return 0; @@ -1269,10 +1083,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) int se_dev_set_block_size(struct se_device *dev, u32 block_size) { - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { + if (dev->export_count) { pr_err("dev[%p]: Unable to change SE Device block_size" - " while dev_export_obj: %d count exists\n", dev, - atomic_read(&dev->dev_export_obj.obj_access_count)); + " while export_count is %d\n", + dev, dev->export_count); return -EINVAL; } @@ -1293,7 +1107,7 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size) return -EINVAL; } - dev->se_sub_dev->se_dev_attrib.block_size = block_size; + dev->dev_attrib.block_size = block_size; pr_debug("dev[%p]: SE Device block_size changed to %u\n", dev, block_size); return 0; @@ -1307,12 +1121,6 @@ struct se_lun *core_dev_add_lun( struct se_lun *lun_p; int rc; - if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) { - pr_err("Unable to export struct se_device while dev_access_obj: %d\n", - atomic_read(&dev->dev_access_obj.obj_access_count)); - return ERR_PTR(-EACCES); - } - lun_p = core_tpg_pre_addlun(tpg, lun); if (IS_ERR(lun_p)) return lun_p; @@ -1568,12 +1376,220 @@ void core_dev_free_initiator_node_lun_acl( kfree(lacl); } +static void scsi_dump_inquiry(struct se_device *dev) +{ + struct t10_wwn *wwn = &dev->t10_wwn; + char buf[17]; + int i, device_type; + /* + * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer + */ + for (i = 0; i < 8; i++) + if (wwn->vendor[i] >= 0x20) + buf[i] = wwn->vendor[i]; + else + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Vendor: %s\n", buf); + + for (i = 0; i < 16; i++) + if (wwn->model[i] >= 0x20) + buf[i] = wwn->model[i]; + else + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Model: %s\n", buf); + + for (i = 0; i < 4; i++) + if (wwn->revision[i] >= 0x20) + buf[i] = wwn->revision[i]; + else + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Revision: %s\n", buf); + + device_type = dev->transport->get_device_type(dev); + pr_debug(" Type: %s ", scsi_device_type(device_type)); + pr_debug(" ANSI SCSI revision: %02x\n", + dev->transport->get_device_rev(dev)); +} + +struct se_device *target_alloc_device(struct se_hba *hba, const char *name) +{ + struct se_device *dev; + + dev = hba->transport->alloc_device(hba, name); + if (!dev) + return NULL; + + dev->se_hba = hba; + dev->transport = hba->transport; + + INIT_LIST_HEAD(&dev->dev_list); + INIT_LIST_HEAD(&dev->dev_sep_list); + INIT_LIST_HEAD(&dev->dev_tmr_list); + INIT_LIST_HEAD(&dev->delayed_cmd_list); + INIT_LIST_HEAD(&dev->state_list); + INIT_LIST_HEAD(&dev->qf_cmd_list); + spin_lock_init(&dev->stats_lock); + spin_lock_init(&dev->execute_task_lock); + spin_lock_init(&dev->delayed_cmd_lock); + spin_lock_init(&dev->dev_reservation_lock); + spin_lock_init(&dev->se_port_lock); + spin_lock_init(&dev->se_tmr_lock); + spin_lock_init(&dev->qf_cmd_lock); + atomic_set(&dev->dev_ordered_id, 0); + INIT_LIST_HEAD(&dev->t10_wwn.t10_vpd_list); + spin_lock_init(&dev->t10_wwn.t10_vpd_lock); + INIT_LIST_HEAD(&dev->t10_pr.registration_list); + INIT_LIST_HEAD(&dev->t10_pr.aptpl_reg_list); + spin_lock_init(&dev->t10_pr.registration_lock); + spin_lock_init(&dev->t10_pr.aptpl_reg_lock); + INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list); + spin_lock_init(&dev->t10_alua.tg_pt_gps_lock); + + dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; + dev->t10_wwn.t10_dev = dev; + dev->t10_alua.t10_dev = dev; + + dev->dev_attrib.da_dev = dev; + dev->dev_attrib.emulate_dpo = DA_EMULATE_DPO; + dev->dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE; + dev->dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ; + dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; + dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; + dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; + dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; + dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; + dev->dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; + dev->dev_attrib.emulate_alua = DA_EMULATE_ALUA; + dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; + dev->dev_attrib.is_nonrot = DA_IS_NONROT; + dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; + dev->dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT; + dev->dev_attrib.max_unmap_block_desc_count = + DA_MAX_UNMAP_BLOCK_DESC_COUNT; + dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; + dev->dev_attrib.unmap_granularity_alignment = + DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; + dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; + dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; + + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH; + else + dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED; + + return dev; +} + +int target_configure_device(struct se_device *dev) +{ + struct se_hba *hba = dev->se_hba; + int ret; + + if (dev->dev_flags & DF_CONFIGURED) { + pr_err("se_dev->se_dev_ptr already set for storage" + " object\n"); + return -EEXIST; + } + + ret = dev->transport->configure_device(dev); + if (ret) + goto out; + dev->dev_flags |= DF_CONFIGURED; + + /* + * XXX: there is not much point to have two different values here.. + */ + dev->dev_attrib.block_size = dev->dev_attrib.hw_block_size; + dev->dev_attrib.queue_depth = dev->dev_attrib.hw_queue_depth; + + /* + * Align max_hw_sectors down to PAGE_SIZE I/O transfers + */ + dev->dev_attrib.hw_max_sectors = + se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, + dev->dev_attrib.hw_block_size); + + dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); + dev->creation_time = get_jiffies_64(); + + core_setup_reservations(dev); + + ret = core_setup_alua(dev); + if (ret) + goto out; + + /* + * Startup the struct se_device processing thread + */ + dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1, + dev->transport->name); + if (!dev->tmr_wq) { + pr_err("Unable to create tmr workqueue for %s\n", + dev->transport->name); + ret = -ENOMEM; + goto out_free_alua; + } + + /* + * Setup work_queue for QUEUE_FULL + */ + INIT_WORK(&dev->qf_work_queue, target_qf_do_work); + + /* + * Preload the initial INQUIRY const values if we are doing + * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI + * passthrough because this is being provided by the backend LLD. + */ + if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { + strncpy(&dev->t10_wwn.vendor[0], "LIO-ORG", 8); + strncpy(&dev->t10_wwn.model[0], + dev->transport->inquiry_prod, 16); + strncpy(&dev->t10_wwn.revision[0], + dev->transport->inquiry_rev, 4); + } + + scsi_dump_inquiry(dev); + + spin_lock(&hba->device_lock); + hba->dev_count++; + spin_unlock(&hba->device_lock); + return 0; + +out_free_alua: + core_alua_free_lu_gp_mem(dev); +out: + se_release_vpd_for_dev(dev); + return ret; +} + +void target_free_device(struct se_device *dev) +{ + struct se_hba *hba = dev->se_hba; + + WARN_ON(!list_empty(&dev->dev_sep_list)); + + if (dev->dev_flags & DF_CONFIGURED) { + destroy_workqueue(dev->tmr_wq); + + spin_lock(&hba->device_lock); + hba->dev_count--; + spin_unlock(&hba->device_lock); + } + + core_alua_free_lu_gp_mem(dev); + core_scsi3_free_all_registrations(dev); + se_release_vpd_for_dev(dev); + + dev->transport->free_device(dev); +} + int core_dev_setup_virtual_lun0(void) { struct se_hba *hba; struct se_device *dev; - struct se_subsystem_dev *se_dev = NULL; - struct se_subsystem_api *t; char buf[16]; int ret; @@ -1581,60 +1597,28 @@ int core_dev_setup_virtual_lun0(void) if (IS_ERR(hba)) return PTR_ERR(hba); - lun0_hba = hba; - t = hba->transport; - - se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL); - if (!se_dev) { - pr_err("Unable to allocate memory for" - " struct se_subsystem_dev\n"); + dev = target_alloc_device(hba, "virt_lun0"); + if (!dev) { ret = -ENOMEM; - goto out; + goto out_free_hba; } - INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); - spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); - INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); - INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list); - spin_lock_init(&se_dev->t10_pr.registration_lock); - spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock); - INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list); - spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock); - spin_lock_init(&se_dev->se_dev_lock); - se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; - se_dev->t10_wwn.t10_sub_dev = se_dev; - se_dev->t10_alua.t10_sub_dev = se_dev; - se_dev->se_dev_attrib.da_sub_dev = se_dev; - se_dev->se_dev_hba = hba; - - se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, "virt_lun0"); - if (!se_dev->se_dev_su_ptr) { - pr_err("Unable to locate subsystem dependent pointer" - " from allocate_virtdevice()\n"); - ret = -ENOMEM; - goto out; - } - lun0_su_dev = se_dev; memset(buf, 0, 16); sprintf(buf, "rd_pages=8"); - t->set_configfs_dev_params(hba, se_dev, buf, sizeof(buf)); + hba->transport->set_configfs_dev_params(dev, buf, sizeof(buf)); - dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); - if (IS_ERR(dev)) { - ret = PTR_ERR(dev); - goto out; - } - se_dev->se_dev_ptr = dev; - g_lun0_dev = dev; + ret = target_configure_device(dev); + if (ret) + goto out_free_se_dev; + lun0_hba = hba; + g_lun0_dev = dev; return 0; -out: - lun0_su_dev = NULL; - kfree(se_dev); - if (lun0_hba) { - core_delete_hba(lun0_hba); - lun0_hba = NULL; - } + +out_free_se_dev: + target_free_device(dev); +out_free_hba: + core_delete_hba(hba); return ret; } @@ -1642,14 +1626,11 @@ out: void core_dev_release_virtual_lun0(void) { struct se_hba *hba = lun0_hba; - struct se_subsystem_dev *su_dev = lun0_su_dev; if (!hba) return; if (g_lun0_dev) - se_free_virtual_device(g_lun0_dev, hba); - - kfree(su_dev); + target_free_device(g_lun0_dev); core_delete_hba(hba); } diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index bca737b..aa67313 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -734,14 +734,12 @@ static int target_fabric_port_link( struct config_item *se_dev_ci) { struct config_item *tpg_ci; - struct se_device *dev; struct se_lun *lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group); struct se_lun *lun_p; struct se_portal_group *se_tpg; - struct se_subsystem_dev *se_dev = container_of( - to_config_group(se_dev_ci), struct se_subsystem_dev, - se_dev_group); + struct se_device *dev = + container_of(to_config_group(se_dev_ci), struct se_device, dev_group); struct target_fabric_configfs *tf; int ret; @@ -755,14 +753,6 @@ static int target_fabric_port_link( return -EEXIST; } - dev = se_dev->se_dev_ptr; - if (!dev) { - pr_err("Unable to locate struct se_device pointer from" - " %s\n", config_item_name(se_dev_ci)); - ret = -ENODEV; - goto out; - } - lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun); if (IS_ERR(lun_p)) { pr_err("core_dev_add_lun() failed\n"); diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 0360383..a89d80d 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -41,7 +41,10 @@ #include "target_core_file.h" -static struct se_subsystem_api fileio_template; +static inline struct fd_dev *FD_DEV(struct se_device *dev) +{ + return container_of(dev, struct fd_dev, dev); +} /* fd_attach_hba(): (Part of se_subsystem_api_t template) * @@ -82,7 +85,7 @@ static void fd_detach_hba(struct se_hba *hba) hba->hba_ptr = NULL; } -static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name) +static struct se_device *fd_alloc_device(struct se_hba *hba, const char *name) { struct fd_dev *fd_dev; struct fd_host *fd_host = hba->hba_ptr; @@ -97,34 +100,28 @@ static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name) pr_debug("FILEIO: Allocated fd_dev for %p\n", name); - return fd_dev; + return &fd_dev->dev; } -/* fd_create_virtdevice(): (Part of se_subsystem_api_t template) - * - * - */ -static struct se_device *fd_create_virtdevice( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - void *p) +static int fd_configure_device(struct se_device *dev) { - struct se_device *dev; - struct se_dev_limits dev_limits; - struct queue_limits *limits; - struct fd_dev *fd_dev = p; - struct fd_host *fd_host = hba->hba_ptr; + struct fd_dev *fd_dev = FD_DEV(dev); + struct fd_host *fd_host = dev->se_hba->hba_ptr; struct file *file; struct inode *inode = NULL; - int dev_flags = 0, flags, ret = -EINVAL; + int flags, ret = -EINVAL; - memset(&dev_limits, 0, sizeof(struct se_dev_limits)); + if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) { + pr_err("Missing fd_dev_name=\n"); + return -EINVAL; + } /* * Use O_DSYNC by default instead of O_SYNC to forgo syncing * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; + /* * Optionally allow fd_buffered_io=1 to be enabled for people * who want use the fs buffer cache as an WriteCache mechanism. @@ -154,22 +151,17 @@ static struct se_device *fd_create_virtdevice( */ inode = file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { - struct request_queue *q; + struct request_queue *q = bdev_get_queue(inode->i_bdev); unsigned long long dev_size; - /* - * Setup the local scope queue_limits from struct request_queue->limits - * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. - */ - q = bdev_get_queue(inode->i_bdev); - limits = &dev_limits.limits; - limits->logical_block_size = bdev_logical_block_size(inode->i_bdev); - limits->max_hw_sectors = queue_max_hw_sectors(q); - limits->max_sectors = queue_max_sectors(q); + + dev->dev_attrib.hw_block_size = + bdev_logical_block_size(inode->i_bdev); + dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); + /* * Determine the number of bytes from i_size_read() minus * one (1) logical sector from underlying struct block_device */ - fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); dev_size = (i_size_read(file->f_mapping->host) - fd_dev->fd_block_size); @@ -185,26 +177,18 @@ static struct se_device *fd_create_virtdevice( goto fail; } - limits = &dev_limits.limits; - limits->logical_block_size = FD_BLOCKSIZE; - limits->max_hw_sectors = FD_MAX_SECTORS; - limits->max_sectors = FD_MAX_SECTORS; - fd_dev->fd_block_size = FD_BLOCKSIZE; + dev->dev_attrib.hw_block_size = FD_BLOCKSIZE; + dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS; } - dev_limits.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; - dev_limits.queue_depth = FD_DEVICE_QUEUE_DEPTH; + fd_dev->fd_block_size = dev->dev_attrib.hw_block_size; - dev = transport_add_device_to_core_hba(hba, &fileio_template, - se_dev, dev_flags, fd_dev, - &dev_limits, "FILEIO", FD_VERSION); - if (!dev) - goto fail; + dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" " with FDBD_HAS_BUFFERED_IO_WCE\n"); - dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1; + dev->dev_attrib.emulate_write_cache = 1; } fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; @@ -214,22 +198,18 @@ static struct se_device *fd_create_virtdevice( " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, fd_dev->fd_dev_name, fd_dev->fd_dev_size); - return dev; + return 0; fail: if (fd_dev->fd_file) { filp_close(fd_dev->fd_file, NULL); fd_dev->fd_file = NULL; } - return ERR_PTR(ret); + return ret; } -/* fd_free_device(): (Part of se_subsystem_api_t template) - * - * - */ -static void fd_free_device(void *p) +static void fd_free_device(struct se_device *dev) { - struct fd_dev *fd_dev = p; + struct fd_dev *fd_dev = FD_DEV(dev); if (fd_dev->fd_file) { filp_close(fd_dev->fd_file, NULL); @@ -243,13 +223,12 @@ static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents) { struct se_device *se_dev = cmd->se_dev; - struct fd_dev *dev = se_dev->dev_ptr; + struct fd_dev *dev = FD_DEV(se_dev); struct file *fd = dev->fd_file; struct scatterlist *sg; struct iovec *iov; mm_segment_t old_fs; - loff_t pos = (cmd->t_task_lba * - se_dev->se_sub_dev->se_dev_attrib.block_size); + loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size); int ret = 0, i; iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL); @@ -296,13 +275,12 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents) { struct se_device *se_dev = cmd->se_dev; - struct fd_dev *dev = se_dev->dev_ptr; + struct fd_dev *dev = FD_DEV(se_dev); struct file *fd = dev->fd_file; struct scatterlist *sg; struct iovec *iov; mm_segment_t old_fs; - loff_t pos = (cmd->t_task_lba * - se_dev->se_sub_dev->se_dev_attrib.block_size); + loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size); int ret, i = 0; iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL); @@ -334,7 +312,7 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, static int fd_execute_sync_cache(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct fd_dev *fd_dev = dev->dev_ptr; + struct fd_dev *fd_dev = FD_DEV(dev); int immed = (cmd->t_task_cdb[1] & 0x2); loff_t start, end; int ret; @@ -353,7 +331,7 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) start = 0; end = LLONG_MAX; } else { - start = cmd->t_task_lba * dev->se_sub_dev->se_dev_attrib.block_size; + start = cmd->t_task_lba * dev->dev_attrib.block_size; if (cmd->data_length) end = start + cmd->data_length; else @@ -399,11 +377,11 @@ static int fd_execute_rw(struct se_cmd *cmd) * Allow this to happen independent of WCE=0 setting. */ if (ret > 0 && - dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && + dev->dev_attrib.emulate_fua_write > 0 && (cmd->se_cmd_flags & SCF_FUA)) { - struct fd_dev *fd_dev = dev->dev_ptr; + struct fd_dev *fd_dev = FD_DEV(dev); loff_t start = cmd->t_task_lba * - dev->se_sub_dev->se_dev_attrib.block_size; + dev->dev_attrib.block_size; loff_t end = start + cmd->data_length; vfs_fsync_range(fd_dev->fd_file, start, end, 1); @@ -430,12 +408,10 @@ static match_table_t tokens = { {Opt_err, NULL} }; -static ssize_t fd_set_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - const char *page, ssize_t count) +static ssize_t fd_set_configfs_dev_params(struct se_device *dev, + const char *page, ssize_t count) { - struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; + struct fd_dev *fd_dev = FD_DEV(dev); char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; int ret = 0, arg, token; @@ -502,24 +478,9 @@ out: return (!ret) ? count : ret; } -static ssize_t fd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev) -{ - struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; - - if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) { - pr_err("Missing fd_dev_name=\n"); - return -EINVAL; - } - - return 0; -} - -static ssize_t fd_show_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - char *b) +static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b) { - struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; + struct fd_dev *fd_dev = FD_DEV(dev); ssize_t bl = 0; bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); @@ -550,7 +511,7 @@ static u32 fd_get_device_type(struct se_device *dev) static sector_t fd_get_blocks(struct se_device *dev) { - struct fd_dev *fd_dev = dev->dev_ptr; + struct fd_dev *fd_dev = FD_DEV(dev); struct file *f = fd_dev->fd_file; struct inode *i = f->f_mapping->host; unsigned long long dev_size; @@ -564,7 +525,7 @@ static sector_t fd_get_blocks(struct se_device *dev) else dev_size = fd_dev->fd_dev_size; - return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size); + return div_u64(dev_size, dev->dev_attrib.block_size); } static struct spc_ops fd_spc_ops = { @@ -579,15 +540,16 @@ static int fd_parse_cdb(struct se_cmd *cmd) static struct se_subsystem_api fileio_template = { .name = "fileio", + .inquiry_prod = "FILEIO", + .inquiry_rev = FD_VERSION, .owner = THIS_MODULE, .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, .attach_hba = fd_attach_hba, .detach_hba = fd_detach_hba, - .allocate_virtdevice = fd_allocate_virtdevice, - .create_virtdevice = fd_create_virtdevice, + .alloc_device = fd_alloc_device, + .configure_device = fd_configure_device, .free_device = fd_free_device, .parse_cdb = fd_parse_cdb, - .check_configfs_dev_params = fd_check_configfs_dev_params, .set_configfs_dev_params = fd_set_configfs_dev_params, .show_configfs_dev_params = fd_show_configfs_dev_params, .get_device_rev = fd_get_device_rev, diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h index 876ae53..bc02b01 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h @@ -17,6 +17,8 @@ #define FDBD_HAS_BUFFERED_IO_WCE 0x04 struct fd_dev { + struct se_device dev; + u32 fbd_flags; unsigned char fd_dev_name[FD_MAX_DEV_NAME]; /* Unique Ramdisk Device ID in Ramdisk HBA */ diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index 3dd1bd4..048b7b4 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c @@ -113,7 +113,6 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags) return ERR_PTR(-ENOMEM); } - INIT_LIST_HEAD(&hba->hba_dev_list); spin_lock_init(&hba->device_lock); mutex_init(&hba->hba_access_mutex); @@ -152,8 +151,7 @@ out_free_hba: int core_delete_hba(struct se_hba *hba) { - if (!list_empty(&hba->hba_dev_list)) - dump_stack(); + WARN_ON(hba->dev_count); hba->transport->detach_hba(hba); diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 57d7674..dd6cd92 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -50,6 +50,12 @@ #define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */ #define IBLOCK_BIO_POOL_SIZE 128 +static inline struct iblock_dev *IBLOCK_DEV(struct se_device *dev) +{ + return container_of(dev, struct iblock_dev, dev); +} + + static struct se_subsystem_api iblock_template; static void iblock_bio_done(struct bio *, int); @@ -70,7 +76,7 @@ static void iblock_detach_hba(struct se_hba *hba) { } -static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name) +static struct se_device *iblock_alloc_device(struct se_hba *hba, const char *name) { struct iblock_dev *ib_dev = NULL; @@ -82,40 +88,28 @@ static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name) pr_debug( "IBLOCK: Allocated ib_dev for %s\n", name); - return ib_dev; + return &ib_dev->dev; } -static struct se_device *iblock_create_virtdevice( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - void *p) +static int iblock_configure_device(struct se_device *dev) { - struct iblock_dev *ib_dev = p; - struct se_device *dev; - struct se_dev_limits dev_limits; - struct block_device *bd = NULL; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct request_queue *q; - struct queue_limits *limits; - u32 dev_flags = 0; + struct block_device *bd = NULL; fmode_t mode; - int ret = -EINVAL; + int ret = -ENOMEM; - if (!ib_dev) { - pr_err("Unable to locate struct iblock_dev parameter\n"); - return ERR_PTR(ret); + if (!(ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH)) { + pr_err("Missing udev_path= parameters for IBLOCK\n"); + return -EINVAL; } - memset(&dev_limits, 0, sizeof(struct se_dev_limits)); ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0); if (!ib_dev->ibd_bio_set) { - pr_err("IBLOCK: Unable to create bioset()\n"); - return ERR_PTR(-ENOMEM); + pr_err("IBLOCK: Unable to create bioset\n"); + goto out; } - pr_debug("IBLOCK: Created bio_set()\n"); - /* - * iblock_check_configfs_dev_params() ensures that ib_dev->ibd_udev_path - * must already have been set in order for echo 1 > $HBA/$DEV/enable to run. - */ + pr_debug( "IBLOCK: Claiming struct block_device: %s\n", ib_dev->ibd_udev_path); @@ -126,27 +120,15 @@ static struct se_device *iblock_create_virtdevice( bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); if (IS_ERR(bd)) { ret = PTR_ERR(bd); - goto failed; + goto out_free_bioset; } - /* - * Setup the local scope queue_limits from struct request_queue->limits - * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. - */ - q = bdev_get_queue(bd); - limits = &dev_limits.limits; - limits->logical_block_size = bdev_logical_block_size(bd); - limits->max_hw_sectors = UINT_MAX; - limits->max_sectors = UINT_MAX; - dev_limits.hw_queue_depth = q->nr_requests; - dev_limits.queue_depth = q->nr_requests; - ib_dev->ibd_bd = bd; - dev = transport_add_device_to_core_hba(hba, - &iblock_template, se_dev, dev_flags, ib_dev, - &dev_limits, "IBLOCK", IBLOCK_VERSION); - if (!dev) - goto failed; + q = bdev_get_queue(bd); + + dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); + dev->dev_attrib.hw_max_sectors = UINT_MAX; + dev->dev_attrib.hw_queue_depth = q->nr_requests; /* * Check if the underlying struct block_device request_queue supports @@ -154,15 +136,16 @@ static struct se_device *iblock_create_virtdevice( * in ATA and we need to set TPE=1 */ if (blk_queue_discard(q)) { - dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = + dev->dev_attrib.max_unmap_lba_count = q->limits.max_discard_sectors; + /* * Currently hardcoded to 1 in Linux/SCSI code.. */ - dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1; - dev->se_sub_dev->se_dev_attrib.unmap_granularity = + dev->dev_attrib.max_unmap_block_desc_count = 1; + dev->dev_attrib.unmap_granularity = q->limits.discard_granularity >> 9; - dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = + dev->dev_attrib.unmap_granularity_alignment = q->limits.discard_alignment; pr_debug("IBLOCK: BLOCK Discard support available," @@ -170,22 +153,19 @@ static struct se_device *iblock_create_virtdevice( } if (blk_queue_nonrot(q)) - dev->se_sub_dev->se_dev_attrib.is_nonrot = 1; - - return dev; + dev->dev_attrib.is_nonrot = 1; + return 0; -failed: - if (ib_dev->ibd_bio_set) { - bioset_free(ib_dev->ibd_bio_set); - ib_dev->ibd_bio_set = NULL; - } - ib_dev->ibd_bd = NULL; - return ERR_PTR(ret); +out_free_bioset: + bioset_free(ib_dev->ibd_bio_set); + ib_dev->ibd_bio_set = NULL; +out: + return ret; } -static void iblock_free_device(void *p) +static void iblock_free_device(struct se_device *dev) { - struct iblock_dev *ib_dev = p; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); if (ib_dev->ibd_bd != NULL) blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); @@ -203,12 +183,12 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( bdev_logical_block_size(bd)) - 1); u32 block_size = bdev_logical_block_size(bd); - if (block_size == dev->se_sub_dev->se_dev_attrib.block_size) + if (block_size == dev->dev_attrib.block_size) return blocks_long; switch (block_size) { case 4096: - switch (dev->se_sub_dev->se_dev_attrib.block_size) { + switch (dev->dev_attrib.block_size) { case 2048: blocks_long <<= 1; break; @@ -222,7 +202,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( } break; case 2048: - switch (dev->se_sub_dev->se_dev_attrib.block_size) { + switch (dev->dev_attrib.block_size) { case 4096: blocks_long >>= 1; break; @@ -237,7 +217,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( } break; case 1024: - switch (dev->se_sub_dev->se_dev_attrib.block_size) { + switch (dev->dev_attrib.block_size) { case 4096: blocks_long >>= 2; break; @@ -252,7 +232,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( } break; case 512: - switch (dev->se_sub_dev->se_dev_attrib.block_size) { + switch (dev->dev_attrib.block_size) { case 4096: blocks_long >>= 3; break; @@ -299,7 +279,7 @@ static void iblock_end_io_flush(struct bio *bio, int err) */ static int iblock_execute_sync_cache(struct se_cmd *cmd) { - struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr; + struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int immed = (cmd->t_task_cdb[1] & 0x2); struct bio *bio; @@ -322,7 +302,7 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) static int iblock_execute_unmap(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct iblock_dev *ibd = dev->dev_ptr; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); unsigned char *buf, *ptr = NULL; sector_t lba; int size; @@ -349,7 +329,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) else size = bd_dl; - if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = -EINVAL; goto err; @@ -366,7 +346,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) pr_debug("UNMAP: Using lba: %llu and range: %u\n", (unsigned long long)lba, range); - if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) { + if (range > dev->dev_attrib.max_unmap_lba_count) { cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = -EINVAL; goto err; @@ -378,7 +358,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) goto err; } - ret = blkdev_issue_discard(ibd->ibd_bd, lba, range, + ret = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, GFP_KERNEL, 0); if (ret < 0) { pr_err("blkdev_issue_discard() failed: %d\n", @@ -399,10 +379,10 @@ err: static int iblock_execute_write_same(struct se_cmd *cmd) { - struct iblock_dev *ibd = cmd->se_dev->dev_ptr; + struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int ret; - ret = blkdev_issue_discard(ibd->ibd_bd, cmd->t_task_lba, + ret = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba, spc_get_write_same_sectors(cmd), GFP_KERNEL, 0); if (ret < 0) { @@ -425,11 +405,10 @@ static match_table_t tokens = { {Opt_err, NULL} }; -static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba, - struct se_subsystem_dev *se_dev, - const char *page, ssize_t count) +static ssize_t iblock_set_configfs_dev_params(struct se_device *dev, + const char *page, ssize_t count) { - struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; int ret = 0, token; @@ -491,43 +470,26 @@ out: return (!ret) ? count : ret; } -static ssize_t iblock_check_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev) -{ - struct iblock_dev *ibd = se_dev->se_dev_su_ptr; - - if (!(ibd->ibd_flags & IBDF_HAS_UDEV_PATH)) { - pr_err("Missing udev_path= parameters for IBLOCK\n"); - return -EINVAL; - } - - return 0; -} - -static ssize_t iblock_show_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - char *b) +static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b) { - struct iblock_dev *ibd = se_dev->se_dev_su_ptr; - struct block_device *bd = ibd->ibd_bd; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bd = ib_dev->ibd_bd; char buf[BDEVNAME_SIZE]; ssize_t bl = 0; if (bd) bl += sprintf(b + bl, "iBlock device: %s", bdevname(bd, buf)); - if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH) + if (ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH) bl += sprintf(b + bl, " UDEV PATH: %s", - ibd->ibd_udev_path); - bl += sprintf(b + bl, " readonly: %d\n", ibd->ibd_readonly); + ib_dev->ibd_udev_path); + bl += sprintf(b + bl, " readonly: %d\n", ib_dev->ibd_readonly); bl += sprintf(b + bl, " "); if (bd) { bl += sprintf(b + bl, "Major: %d Minor: %d %s\n", MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ? - "" : (bd->bd_holder == ibd) ? + "" : (bd->bd_holder == ib_dev) ? "CLAIMED: IBLOCK" : "CLAIMED: OS"); } else { bl += sprintf(b + bl, "Major: 0 Minor: 0\n"); @@ -556,7 +518,7 @@ static void iblock_complete_cmd(struct se_cmd *cmd) static struct bio * iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) { - struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr; + struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); struct bio *bio; /* @@ -611,8 +573,8 @@ static int iblock_execute_rw(struct se_cmd *cmd) * Force data to disk if we pretend to not have a volatile * write cache, or the initiator set the Force Unit Access bit. */ - if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 || - (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && + if (dev->dev_attrib.emulate_write_cache == 0 || + (dev->dev_attrib.emulate_fua_write > 0 && (cmd->se_cmd_flags & SCF_FUA))) rw = WRITE_FUA; else @@ -625,17 +587,17 @@ static int iblock_execute_rw(struct se_cmd *cmd) * Convert the blocksize advertised to the initiator to the 512 byte * units unconditionally used by the Linux block layer. */ - if (dev->se_sub_dev->se_dev_attrib.block_size == 4096) + if (dev->dev_attrib.block_size == 4096) block_lba = (cmd->t_task_lba << 3); - else if (dev->se_sub_dev->se_dev_attrib.block_size == 2048) + else if (dev->dev_attrib.block_size == 2048) block_lba = (cmd->t_task_lba << 2); - else if (dev->se_sub_dev->se_dev_attrib.block_size == 1024) + else if (dev->dev_attrib.block_size == 1024) block_lba = (cmd->t_task_lba << 1); - else if (dev->se_sub_dev->se_dev_attrib.block_size == 512) + else if (dev->dev_attrib.block_size == 512) block_lba = cmd->t_task_lba; else { pr_err("Unsupported SCSI -> BLOCK LBA conversion:" - " %u\n", dev->se_sub_dev->se_dev_attrib.block_size); + " %u\n", dev->dev_attrib.block_size); cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -ENOSYS; } @@ -714,8 +676,8 @@ static u32 iblock_get_device_type(struct se_device *dev) static sector_t iblock_get_blocks(struct se_device *dev) { - struct iblock_dev *ibd = dev->dev_ptr; - struct block_device *bd = ibd->ibd_bd; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bd = ib_dev->ibd_bd; struct request_queue *q = bdev_get_queue(bd); return iblock_emulate_read_cap_with_block_size(dev, bd, q); @@ -761,15 +723,16 @@ static int iblock_parse_cdb(struct se_cmd *cmd) static struct se_subsystem_api iblock_template = { .name = "iblock", + .inquiry_prod = "IBLOCK", + .inquiry_rev = IBLOCK_VERSION, .owner = THIS_MODULE, .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, .attach_hba = iblock_attach_hba, .detach_hba = iblock_detach_hba, - .allocate_virtdevice = iblock_allocate_virtdevice, - .create_virtdevice = iblock_create_virtdevice, + .alloc_device = iblock_alloc_device, + .configure_device = iblock_configure_device, .free_device = iblock_free_device, .parse_cdb = iblock_parse_cdb, - .check_configfs_dev_params = iblock_check_configfs_dev_params, .set_configfs_dev_params = iblock_set_configfs_dev_params, .show_configfs_dev_params = iblock_show_configfs_dev_params, .get_device_rev = iblock_get_device_rev, diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h index 533627a..01c2afd 100644 --- a/drivers/target/target_core_iblock.h +++ b/drivers/target/target_core_iblock.h @@ -14,6 +14,7 @@ struct iblock_req { #define IBDF_HAS_UDEV_PATH 0x01 struct iblock_dev { + struct se_device dev; unsigned char ibd_udev_path[SE_UDEV_PATH_LEN]; u32 ibd_flags; struct bio_set *ibd_bio_set; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 0fd4282..5854ed6 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -20,12 +20,6 @@ int core_dev_export(struct se_device *, struct se_portal_group *, void core_dev_unexport(struct se_device *, struct se_portal_group *, struct se_lun *); int target_report_luns(struct se_cmd *); -void se_release_device_for_hba(struct se_device *); -void se_release_vpd_for_dev(struct se_device *); -int se_free_virtual_device(struct se_device *, struct se_hba *); -int se_dev_check_online(struct se_device *); -int se_dev_check_shutdown(struct se_device *); -void se_dev_set_default_attribs(struct se_device *, struct se_dev_limits *); int se_dev_set_task_timeout(struct se_device *, u32); int se_dev_set_max_unmap_lba_count(struct se_device *, u32); int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); @@ -60,6 +54,9 @@ void core_dev_free_initiator_node_lun_acl(struct se_portal_group *, struct se_lun_acl *lacl); int core_dev_setup_virtual_lun0(void); void core_dev_release_virtual_lun0(void); +struct se_device *target_alloc_device(struct se_hba *hba, const char *name); +int target_configure_device(struct se_device *dev); +void target_free_device(struct se_device *); /* target_core_hba.c */ struct se_hba *core_alloc_hba(const char *, u32, u32); @@ -106,9 +103,10 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); int transport_clear_lun_from_sessions(struct se_lun *); void transport_send_task_abort(struct se_cmd *); int target_cmd_size_check(struct se_cmd *cmd, unsigned int size); +void target_qf_do_work(struct work_struct *work); /* target_core_stat.c */ -void target_stat_setup_dev_default_groups(struct se_subsystem_dev *); +void target_stat_setup_dev_default_groups(struct se_device *); void target_stat_setup_port_default_groups(struct se_lun *); void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *); diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 8c323a9..2b28989 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -103,7 +103,7 @@ static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type) spin_unlock(&dev->dev_reservation_lock); return -EINVAL; } - if (!(dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID)) { + if (!(dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID)) { spin_unlock(&dev->dev_reservation_lock); return 0; } @@ -120,10 +120,10 @@ static void core_scsi3_put_pr_reg(struct t10_pr_registration *); static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) { struct se_session *se_sess = cmd->se_sess; - struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; - struct t10_reservation *pr_tmpl = &su_dev->t10_pr; - int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS); + struct t10_reservation *pr_tmpl = &dev->t10_pr; + int crh = (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS); int conflict = 0; if (!crh) @@ -223,10 +223,10 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) goto out_unlock; dev->dev_reserved_node_acl = NULL; - dev->dev_flags &= ~DF_SPC2_RESERVATIONS; - if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) { + dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS; + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { dev->dev_res_bin_isid = 0; - dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID; + dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID; } tpg = sess->se_tpg; pr_debug("SCSI-2 Released reservation for %s LUN: %u ->" @@ -292,10 +292,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) } dev->dev_reserved_node_acl = sess->se_node_acl; - dev->dev_flags |= DF_SPC2_RESERVATIONS; + dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS; if (sess->sess_bin_isid != 0) { dev->dev_res_bin_isid = sess->sess_bin_isid; - dev->dev_flags |= DF_SPC2_RESERVATIONS_WITH_ISID; + dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID; } pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u" " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), @@ -333,7 +333,7 @@ static int core_scsi3_pr_seq_non_holder( /* * A legacy SPC-2 reservation is being held. */ - if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) + if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return core_scsi2_reservation_seq_non_holder(cmd, cdb, pr_reg_type); @@ -565,8 +565,8 @@ static int core_scsi3_pr_seq_non_holder( static u32 core_scsi3_pr_generation(struct se_device *dev) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; u32 prg; + /* * PRGeneration field shall contain the value of a 32-bit wrapping * counter mainted by the device server. @@ -577,7 +577,7 @@ static u32 core_scsi3_pr_generation(struct se_device *dev) * See spc4r17 section 6.3.12 READ_KEYS service action */ spin_lock(&dev->dev_reservation_lock); - prg = su_dev->t10_pr.pr_generation++; + prg = dev->t10_pr.pr_generation++; spin_unlock(&dev->dev_reservation_lock); return prg; @@ -596,7 +596,7 @@ static int core_scsi3_pr_reservation_check( /* * A legacy SPC-2 reservation is being held. */ - if (dev->dev_flags & DF_SPC2_RESERVATIONS) + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return core_scsi2_reservation_check(cmd, pr_reg_type); spin_lock(&dev->dev_reservation_lock); @@ -636,7 +636,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( int all_tg_pt, int aptpl) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct t10_pr_registration *pr_reg; pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC); @@ -645,7 +644,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( return NULL; } - pr_reg->pr_aptpl_buf = kzalloc(su_dev->t10_pr.pr_aptpl_buf_len, + pr_reg->pr_aptpl_buf = kzalloc(dev->t10_pr.pr_aptpl_buf_len, GFP_ATOMIC); if (!pr_reg->pr_aptpl_buf) { pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n"); @@ -929,7 +928,7 @@ static int __core_scsi3_check_aptpl_registration( struct se_dev_entry *deve) { struct t10_pr_registration *pr_reg, *pr_reg_tmp; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char i_port[PR_APTPL_MAX_IPORT_LEN]; unsigned char t_port[PR_APTPL_MAX_TPORT_LEN]; u16 tpgt; @@ -996,11 +995,10 @@ int core_scsi3_check_aptpl_registration( struct se_lun *lun, struct se_lun_acl *lun_acl) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct se_node_acl *nacl = lun_acl->se_lun_nacl; struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) return 0; return __core_scsi3_check_aptpl_registration(dev, tpg, lun, @@ -1051,10 +1049,9 @@ static void __core_scsi3_add_registration( int register_type, int register_move) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; /* * Increment PRgeneration counter for struct se_device upon a successful @@ -1066,7 +1063,7 @@ static void __core_scsi3_add_registration( * for the REGISTER. */ pr_reg->pr_res_generation = (register_move) ? - su_dev->t10_pr.pr_generation++ : + dev->t10_pr.pr_generation++ : core_scsi3_pr_generation(dev); spin_lock(&pr_tmpl->registration_lock); @@ -1135,7 +1132,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( struct se_node_acl *nacl, unsigned char *isid) { - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp; struct se_portal_group *tpg; @@ -1160,7 +1157,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( * for fabric modules (iSCSI) requiring them. */ if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) { - if (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) + if (dev->dev_attrib.enforce_pr_isids) continue; } atomic_inc(&pr_reg->pr_res_holders); @@ -1274,7 +1271,7 @@ static void __core_scsi3_free_registration( { struct target_core_fabric_ops *tfo = pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; int prf_isid; @@ -1335,7 +1332,7 @@ void core_scsi3_free_pr_reg_from_nacl( struct se_device *dev, struct se_node_acl *nacl) { - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; /* * If the passed se_node_acl matches the reservation holder, @@ -1365,7 +1362,7 @@ void core_scsi3_free_pr_reg_from_nacl( void core_scsi3_free_all_registrations( struct se_device *dev) { - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; spin_lock(&dev->dev_reservation_lock); @@ -1899,7 +1896,6 @@ static int __core_scsi3_update_aptpl_buf( { struct se_lun *lun; struct se_portal_group *tpg; - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct t10_pr_registration *pr_reg; unsigned char tmp[512], isid_buf[32]; ssize_t len = 0; @@ -1917,8 +1913,8 @@ static int __core_scsi3_update_aptpl_buf( /* * Walk the registration list.. */ - spin_lock(&su_dev->t10_pr.registration_lock); - list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, + spin_lock(&dev->t10_pr.registration_lock); + list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { tmp[0] = '\0'; @@ -1963,7 +1959,7 @@ static int __core_scsi3_update_aptpl_buf( if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { pr_err("Unable to update renaming" " APTPL metadata\n"); - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); return -EMSGSIZE; } len += sprintf(buf+len, "%s", tmp); @@ -1981,13 +1977,13 @@ static int __core_scsi3_update_aptpl_buf( if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { pr_err("Unable to update renaming" " APTPL metadata\n"); - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); return -EMSGSIZE; } len += sprintf(buf+len, "%s", tmp); reg_count++; } - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); if (!reg_count) len += sprintf(buf+len, "No Registrations or Reservations"); @@ -2019,7 +2015,7 @@ static int __core_scsi3_write_aptpl_to_file( unsigned char *buf, u32 pr_aptpl_buf_len) { - struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; + struct t10_wwn *wwn = &dev->t10_wwn; struct file *file; struct iovec iov[1]; mm_segment_t old_fs; @@ -2120,7 +2116,7 @@ static int core_scsi3_emulate_pro_register( struct se_lun *se_lun = cmd->se_lun; struct se_portal_group *se_tpg; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; /* Used for APTPL metadata w/ UNREGISTER */ unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; @@ -2434,7 +2430,7 @@ static int core_scsi3_pro_reserve( struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_res_holder; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; int ret, prf_isid; @@ -2667,7 +2663,7 @@ static int core_scsi3_emulate_pro_release( struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; int ret, all_reg = 0; if (!se_sess || !se_lun) { @@ -2836,7 +2832,7 @@ static int core_scsi3_emulate_pro_clear( struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; struct se_session *se_sess = cmd->se_sess; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; u32 pr_res_mapped_lun = 0; int calling_it_nexus = 0; @@ -3006,7 +3002,7 @@ static int core_scsi3_pro_preempt( struct se_session *se_sess = cmd->se_sess; LIST_HEAD(preempt_and_abort_list); struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; u32 pr_res_mapped_lun = 0; int all_reg = 0, calling_it_nexus = 0, released_regs = 0; int prh_type = 0, prh_scope = 0, ret; @@ -3358,7 +3354,7 @@ static int core_scsi3_emulate_pro_register_and_move( struct se_portal_group *se_tpg, *dest_se_tpg = NULL; struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops; struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; unsigned char *initiator_str; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; @@ -3823,7 +3819,7 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) * initiator or service action and shall terminate with a RESERVATION * CONFLICT status. */ - if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { + if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) { pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); @@ -3959,8 +3955,7 @@ out: */ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) { - struct se_device *se_dev = cmd->se_dev; - struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; unsigned char *buf; u32 add_len = 0, off = 8; @@ -3973,13 +3968,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) } buf = transport_kmap_data_sg(cmd); - buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); - buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); - buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); - buf[3] = (su_dev->t10_pr.pr_generation & 0xff); + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); + buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); - spin_lock(&su_dev->t10_pr.registration_lock); - list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, + spin_lock(&dev->t10_pr.registration_lock); + list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { /* * Check for overflow of 8byte PRI READ_KEYS payload and @@ -3999,7 +3994,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) add_len += 8; } - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); buf[4] = ((add_len >> 24) & 0xff); buf[5] = ((add_len >> 16) & 0xff); @@ -4018,8 +4013,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) */ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) { - struct se_device *se_dev = cmd->se_dev; - struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; unsigned char *buf; u64 pr_res_key; @@ -4033,13 +4027,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) } buf = transport_kmap_data_sg(cmd); - buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); - buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); - buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); - buf[3] = (su_dev->t10_pr.pr_generation & 0xff); + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); + buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); - spin_lock(&se_dev->dev_reservation_lock); - pr_reg = se_dev->dev_pr_res_holder; + spin_lock(&dev->dev_reservation_lock); + pr_reg = dev->dev_pr_res_holder; if (pr_reg) { /* * Set the hardcoded Additional Length @@ -4090,7 +4084,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) } err: - spin_unlock(&se_dev->dev_reservation_lock); + spin_unlock(&dev->dev_reservation_lock); transport_kunmap_data_sg(cmd); return 0; @@ -4104,7 +4098,7 @@ err: static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; u16 add_len = 8; /* Hardcoded to 8. */ @@ -4159,12 +4153,11 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) */ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) { - struct se_device *se_dev = cmd->se_dev; + struct se_device *dev = cmd->se_dev; struct se_node_acl *se_nacl; - struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; struct se_portal_group *se_tpg; struct t10_pr_registration *pr_reg, *pr_reg_tmp; - struct t10_reservation *pr_tmpl = &se_dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; u32 off = 8; /* off into first Full Status descriptor */ @@ -4179,10 +4172,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) buf = transport_kmap_data_sg(cmd); - buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); - buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); - buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); - buf[3] = (su_dev->t10_pr.pr_generation & 0xff); + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); + buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); spin_lock(&pr_tmpl->registration_lock); list_for_each_entry_safe(pr_reg, pr_reg_tmp, @@ -4316,7 +4309,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) * initiator or service action and shall terminate with a RESERVATION * CONFLICT status. */ - if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { + if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) { pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); @@ -4363,30 +4356,25 @@ static int core_pt_seq_non_holder( return 0; } -int core_setup_reservations(struct se_device *dev, int force_pt) +void core_setup_reservations(struct se_device *dev) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; - struct t10_reservation *rest = &su_dev->t10_pr; + struct t10_reservation *rest = &dev->t10_pr; + /* * If this device is from Target_Core_Mod/pSCSI, use the reservations * 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 to emulate reservations themselves. */ - if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) && - !(dev->se_sub_dev->se_dev_attrib.emulate_reservations)) || force_pt) { + if ((dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) || + (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV && + !dev->dev_attrib.emulate_reservations)) { rest->res_type = SPC_PASSTHROUGH; rest->pr_ops.t10_reservation_check = &core_pt_reservation_check; rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder; pr_debug("%s: Using SPC_PASSTHROUGH, no reservation" " emulation\n", dev->transport->name); - return 0; - } - /* - * If SPC-3 or above is reported by real or emulated struct se_device, - * use emulated Persistent Reservations. - */ - if (dev->transport->get_device_rev(dev) >= SCSI_3) { + } else if (dev->transport->get_device_rev(dev) >= SCSI_3) { rest->res_type = SPC3_PERSISTENT_RESERVATIONS; rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check; rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder; @@ -4400,6 +4388,4 @@ int core_setup_reservations(struct se_device *dev, int force_pt) pr_debug("%s: Using SPC2_RESERVATIONS emulation\n", dev->transport->name); } - - return 0; } diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index af6c460..7845143 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -63,6 +63,6 @@ extern unsigned char *core_scsi3_pr_dump_type(int); extern int target_scsi3_emulate_pr_in(struct se_cmd *); extern int target_scsi3_emulate_pr_out(struct se_cmd *); -extern int core_setup_reservations(struct se_device *, int); +extern void core_setup_reservations(struct se_device *); #endif /* TARGET_CORE_PR_H */ diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 617c086..b296508 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -53,6 +53,11 @@ #define ISPRINT(a) ((a >= ' ') && (a <= '~')) +static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev) +{ + return container_of(dev, struct pscsi_dev_virt, dev); +} + static struct se_subsystem_api pscsi_template; static int pscsi_execute_cmd(struct se_cmd *cmd); @@ -219,7 +224,7 @@ pscsi_get_inquiry_vpd_serial(struct scsi_device *sdev, struct t10_wwn *wwn) snprintf(&wwn->unit_serial[0], INQUIRY_VPD_SERIAL_LEN, "%s", &buf[4]); - wwn->t10_sub_dev->su_dev_flags |= SDF_FIRMWARE_VPD_UNIT_SERIAL; + wwn->t10_dev->dev_flags |= DF_FIRMWARE_VPD_UNIT_SERIAL; kfree(buf); return 0; @@ -299,23 +304,13 @@ out: kfree(buf); } -/* pscsi_add_device_to_list(): - * - * - */ -static struct se_device *pscsi_add_device_to_list( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - struct pscsi_dev_virt *pdv, - struct scsi_device *sd, - int dev_flags) +static int pscsi_add_device_to_list(struct se_device *dev, + struct scsi_device *sd) { - struct se_device *dev; - struct se_dev_limits dev_limits; - struct request_queue *q; - struct queue_limits *limits; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); + struct request_queue *q = sd->request_queue; - memset(&dev_limits, 0, sizeof(struct se_dev_limits)); + pdv->pdv_sd = sd; if (!sd->queue_depth) { sd->queue_depth = PSCSI_DEFAULT_QUEUEDEPTH; @@ -324,54 +319,27 @@ static struct se_device *pscsi_add_device_to_list( " queue_depth to %d\n", sd->channel, sd->id, sd->lun, sd->queue_depth); } - /* - * Setup the local scope queue_limits from struct request_queue->limits - * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. - */ - q = sd->request_queue; - limits = &dev_limits.limits; - limits->logical_block_size = sd->sector_size; - limits->max_hw_sectors = min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q)); - limits->max_sectors = min_t(int, sd->host->max_sectors, queue_max_sectors(q)); - dev_limits.hw_queue_depth = sd->queue_depth; - dev_limits.queue_depth = sd->queue_depth; + + dev->dev_attrib.hw_block_size = sd->sector_size; + dev->dev_attrib.hw_max_sectors = + min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q)); + dev->dev_attrib.hw_queue_depth = sd->queue_depth; + /* * Setup our standard INQUIRY info into se_dev->t10_wwn */ - pscsi_set_inquiry_info(sd, &se_dev->t10_wwn); - - /* - * Set the pointer pdv->pdv_sd to from passed struct scsi_device, - * which has already been referenced with Linux SCSI code with - * scsi_device_get() in this file's pscsi_create_virtdevice(). - * - * The passthrough operations called by the transport_add_device_* - * function below will require this pointer to be set for passthroug - * ops. - * - * For the shutdown case in pscsi_free_device(), this struct - * scsi_device reference is released with Linux SCSI code - * scsi_device_put() and the pdv->pdv_sd cleared. - */ - pdv->pdv_sd = sd; - dev = transport_add_device_to_core_hba(hba, &pscsi_template, - se_dev, dev_flags, pdv, - &dev_limits, NULL, NULL); - if (!dev) { - pdv->pdv_sd = NULL; - return NULL; - } + pscsi_set_inquiry_info(sd, &dev->t10_wwn); /* * Locate VPD WWN Information used for various purposes within * the Storage Engine. */ - if (!pscsi_get_inquiry_vpd_serial(sd, &se_dev->t10_wwn)) { + if (!pscsi_get_inquiry_vpd_serial(sd, &dev->t10_wwn)) { /* * If VPD Unit Serial returned GOOD status, try * VPD Device Identification page (0x83). */ - pscsi_get_inquiry_vpd_device_ident(sd, &se_dev->t10_wwn); + pscsi_get_inquiry_vpd_device_ident(sd, &dev->t10_wwn); } /* @@ -379,10 +347,11 @@ static struct se_device *pscsi_add_device_to_list( */ if (sd->type == TYPE_TAPE) pscsi_tape_read_blocksize(dev, sd); - return dev; + return 0; } -static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name) +static struct se_device *pscsi_alloc_device(struct se_hba *hba, + const char *name) { struct pscsi_dev_virt *pdv; @@ -391,139 +360,125 @@ static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name) pr_err("Unable to allocate memory for struct pscsi_dev_virt\n"); return NULL; } - pdv->pdv_se_hba = hba; pr_debug("PSCSI: Allocated pdv: %p for %s\n", pdv, name); - return pdv; + return &pdv->dev; } /* * Called with struct Scsi_Host->host_lock called. */ -static struct se_device *pscsi_create_type_disk( - struct scsi_device *sd, - struct pscsi_dev_virt *pdv, - struct se_subsystem_dev *se_dev, - struct se_hba *hba) +static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) __releases(sh->host_lock) { - struct se_device *dev; - struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct Scsi_Host *sh = sd->host; struct block_device *bd; - u32 dev_flags = 0; + int ret; if (scsi_device_get(sd)) { pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", sh->host_no, sd->channel, sd->id, sd->lun); spin_unlock_irq(sh->host_lock); - return NULL; + return -EIO; } spin_unlock_irq(sh->host_lock); /* * Claim exclusive struct block_device access to struct scsi_device * for TYPE_DISK using supplied udev_path */ - bd = blkdev_get_by_path(se_dev->se_dev_udev_path, + bd = blkdev_get_by_path(dev->udev_path, FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv); if (IS_ERR(bd)) { pr_err("pSCSI: blkdev_get_by_path() failed\n"); scsi_device_put(sd); - return NULL; + return PTR_ERR(bd); } pdv->pdv_bd = bd; - dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags); - if (!dev) { + ret = pscsi_add_device_to_list(dev, sd); + if (ret) { blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); scsi_device_put(sd); - return NULL; + return ret; } + pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n", phv->phv_host_id, sh->host_no, sd->channel, sd->id, sd->lun); - - return dev; + return 0; } /* * Called with struct Scsi_Host->host_lock called. */ -static struct se_device *pscsi_create_type_rom( - struct scsi_device *sd, - struct pscsi_dev_virt *pdv, - struct se_subsystem_dev *se_dev, - struct se_hba *hba) +static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd) __releases(sh->host_lock) { - struct se_device *dev; - struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; struct Scsi_Host *sh = sd->host; - u32 dev_flags = 0; + int ret; if (scsi_device_get(sd)) { pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", sh->host_no, sd->channel, sd->id, sd->lun); spin_unlock_irq(sh->host_lock); - return NULL; + return -EIO; } spin_unlock_irq(sh->host_lock); - dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags); - if (!dev) { + ret = pscsi_add_device_to_list(dev, sd); + if (ret) { scsi_device_put(sd); - return NULL; + return ret; } pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, sd->channel, sd->id, sd->lun); - return dev; + return 0; } /* - *Called with struct Scsi_Host->host_lock called. + * Called with struct Scsi_Host->host_lock called. */ -static struct se_device *pscsi_create_type_other( - struct scsi_device *sd, - struct pscsi_dev_virt *pdv, - struct se_subsystem_dev *se_dev, - struct se_hba *hba) +static int pscsi_create_type_other(struct se_device *dev, + struct scsi_device *sd) __releases(sh->host_lock) { - struct se_device *dev; - struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; struct Scsi_Host *sh = sd->host; - u32 dev_flags = 0; + int ret; spin_unlock_irq(sh->host_lock); - dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags); - if (!dev) - return NULL; + ret = pscsi_add_device_to_list(dev, sd); + if (ret) + return ret; pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, sd->channel, sd->id, sd->lun); - - return dev; + return 0; } -static struct se_device *pscsi_create_virtdevice( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - void *p) +int pscsi_configure_device(struct se_device *dev) { - struct pscsi_dev_virt *pdv = p; - struct se_device *dev; + struct se_hba *hba = dev->se_hba; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct scsi_device *sd; - struct pscsi_hba_virt *phv = hba->hba_ptr; + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; struct Scsi_Host *sh = phv->phv_lld_host; int legacy_mode_enable = 0; + int ret; - if (!pdv) { - pr_err("Unable to locate struct pscsi_dev_virt" - " parameter\n"); - return ERR_PTR(-EINVAL); + if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) || + !(pdv->pdv_flags & PDF_HAS_TARGET_ID) || + !(pdv->pdv_flags & PDF_HAS_LUN_ID)) { + pr_err("Missing scsi_channel_id=, scsi_target_id= and" + " scsi_lun_id= parameters\n"); + return -EINVAL; } + /* * If not running in PHV_LLD_SCSI_HOST_NO mode, locate the * struct Scsi_Host we will need to bring the TCM/pSCSI object online @@ -532,16 +487,16 @@ static struct se_device *pscsi_create_virtdevice( if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) { pr_err("pSCSI: Unable to locate struct" " Scsi_Host for PHV_LLD_SCSI_HOST_NO\n"); - return ERR_PTR(-ENODEV); + return -ENODEV; } /* * For the newer PHV_VIRTUAL_HOST_ID struct scsi_device * reference, we enforce that udev_path has been set */ - if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) { + if (!(dev->dev_flags & DF_USING_UDEV_PATH)) { pr_err("pSCSI: udev_path attribute has not" " been set before ENABLE=1\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } /* * If no scsi_host_id= was passed for PHV_VIRTUAL_HOST_ID, @@ -549,17 +504,14 @@ static struct se_device *pscsi_create_virtdevice( * and enable for PHV_LLD_SCSI_HOST_NO mode. */ if (!(pdv->pdv_flags & PDF_HAS_VIRT_HOST_ID)) { - spin_lock(&hba->device_lock); - if (!list_empty(&hba->hba_dev_list)) { + if (hba->dev_count) { pr_err("pSCSI: Unable to set hba_mode" " with active devices\n"); - spin_unlock(&hba->device_lock); - return ERR_PTR(-EEXIST); + return -EEXIST; } - spin_unlock(&hba->device_lock); if (pscsi_pmode_enable_hba(hba, 1) != 1) - return ERR_PTR(-ENODEV); + return -ENODEV; legacy_mode_enable = 1; hba->hba_flags |= HBA_FLAGS_PSCSI_MODE; @@ -569,14 +521,14 @@ static struct se_device *pscsi_create_virtdevice( if (IS_ERR(sh)) { pr_err("pSCSI: Unable to locate" " pdv_host_id: %d\n", pdv->pdv_host_id); - return ERR_CAST(sh); + return PTR_ERR(sh); } } } else { if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) { pr_err("pSCSI: PHV_VIRTUAL_HOST_ID set while" " struct Scsi_Host exists\n"); - return ERR_PTR(-EEXIST); + return -EEXIST; } } @@ -593,17 +545,17 @@ static struct se_device *pscsi_create_virtdevice( */ switch (sd->type) { case TYPE_DISK: - dev = pscsi_create_type_disk(sd, pdv, se_dev, hba); + ret = pscsi_create_type_disk(dev, sd); break; case TYPE_ROM: - dev = pscsi_create_type_rom(sd, pdv, se_dev, hba); + ret = pscsi_create_type_rom(dev, sd); break; default: - dev = pscsi_create_type_other(sd, pdv, se_dev, hba); + ret = pscsi_create_type_other(dev, sd); break; } - if (!dev) { + if (ret) { if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) scsi_host_put(sh); else if (legacy_mode_enable) { @@ -611,9 +563,9 @@ static struct se_device *pscsi_create_virtdevice( hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; } pdv->pdv_sd = NULL; - return ERR_PTR(-ENODEV); + return ret; } - return dev; + return 0; } spin_unlock_irq(sh->host_lock); @@ -627,17 +579,13 @@ static struct se_device *pscsi_create_virtdevice( hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; } - return ERR_PTR(-ENODEV); + return -ENODEV; } -/* pscsi_free_device(): (Part of se_subsystem_api_t template) - * - * - */ -static void pscsi_free_device(void *p) +static void pscsi_free_device(struct se_device *dev) { - struct pscsi_dev_virt *pdv = p; - struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; struct scsi_device *sd = pdv->pdv_sd; if (sd) { @@ -670,7 +618,7 @@ static void pscsi_free_device(void *p) static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, unsigned char *sense_buffer) { - struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct scsi_device *sd = pdv->pdv_sd; int result; struct pscsi_plugin_task *pt = cmd->priv; @@ -770,13 +718,11 @@ static match_table_t tokens = { {Opt_err, NULL} }; -static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba, - struct se_subsystem_dev *se_dev, - const char *page, - ssize_t count) +static ssize_t pscsi_set_configfs_dev_params(struct se_device *dev, + const char *page, ssize_t count) { - struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr; - struct pscsi_hba_virt *phv = hba->hba_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; char *orig, *ptr, *opts; substring_t args[MAX_OPT_ARGS]; int ret = 0, arg, token; @@ -841,29 +787,10 @@ out: return (!ret) ? count : ret; } -static ssize_t pscsi_check_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev) -{ - struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr; - - if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) || - !(pdv->pdv_flags & PDF_HAS_TARGET_ID) || - !(pdv->pdv_flags & PDF_HAS_LUN_ID)) { - pr_err("Missing scsi_channel_id=, scsi_target_id= and" - " scsi_lun_id= parameters\n"); - return -EINVAL; - } - - return 0; -} - -static ssize_t pscsi_show_configfs_dev_params(struct se_hba *hba, - struct se_subsystem_dev *se_dev, - char *b) +static ssize_t pscsi_show_configfs_dev_params(struct se_device *dev, char *b) { - struct pscsi_hba_virt *phv = hba->hba_ptr; - struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr; + struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct scsi_device *sd = pdv->pdv_sd; unsigned char host_id[16]; ssize_t bl; @@ -933,7 +860,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, enum dma_data_direction data_direction, struct bio **hbio) { - struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct bio *bio = NULL, *tbio = NULL; struct page *page; struct scatterlist *sg; @@ -1104,7 +1031,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; enum dma_data_direction data_direction = cmd->data_direction; - struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct pscsi_plugin_task *pt; struct request *req; struct bio *hbio; @@ -1191,7 +1118,7 @@ fail: */ static u32 pscsi_get_device_rev(struct se_device *dev) { - struct pscsi_dev_virt *pdv = dev->dev_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct scsi_device *sd = pdv->pdv_sd; return (sd->scsi_level - 1) ? sd->scsi_level - 1 : 1; @@ -1203,7 +1130,7 @@ static u32 pscsi_get_device_rev(struct se_device *dev) */ static u32 pscsi_get_device_type(struct se_device *dev) { - struct pscsi_dev_virt *pdv = dev->dev_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct scsi_device *sd = pdv->pdv_sd; return sd->type; @@ -1211,7 +1138,7 @@ static u32 pscsi_get_device_type(struct se_device *dev) static sector_t pscsi_get_blocks(struct se_device *dev) { - struct pscsi_dev_virt *pdv = dev->dev_ptr; + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); if (pdv->pdv_bd && pdv->pdv_bd->bd_part) return pdv->pdv_bd->bd_part->nr_sects; @@ -1259,12 +1186,11 @@ static struct se_subsystem_api pscsi_template = { .attach_hba = pscsi_attach_hba, .detach_hba = pscsi_detach_hba, .pmode_enable_hba = pscsi_pmode_enable_hba, - .allocate_virtdevice = pscsi_allocate_virtdevice, - .create_virtdevice = pscsi_create_virtdevice, + .alloc_device = pscsi_alloc_device, + .configure_device = pscsi_configure_device, .free_device = pscsi_free_device, .transport_complete = pscsi_transport_complete, .parse_cdb = pscsi_parse_cdb, - .check_configfs_dev_params = pscsi_check_configfs_dev_params, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, .get_device_rev = pscsi_get_device_rev, diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h index bc1e5e11..1bd757d 100644 --- a/drivers/target/target_core_pscsi.h +++ b/drivers/target/target_core_pscsi.h @@ -37,6 +37,7 @@ struct pscsi_plugin_task { #define PDF_HAS_VIRT_HOST_ID 0x20 struct pscsi_dev_virt { + struct se_device dev; int pdv_flags; int pdv_host_id; int pdv_channel_id; @@ -44,7 +45,6 @@ struct pscsi_dev_virt { int pdv_lun_id; struct block_device *pdv_bd; struct scsi_device *pdv_sd; - struct se_hba *pdv_se_hba; } ____cacheline_aligned; typedef enum phv_modes { diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index d00bbe3..d083f39 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -41,7 +41,10 @@ #include "target_core_rd.h" -static struct se_subsystem_api rd_mcp_template; +static inline struct rd_dev *RD_DEV(struct se_device *dev) +{ + return container_of(dev, struct rd_dev, dev); +} /* rd_attach_hba(): (Part of se_subsystem_api_t template) * @@ -196,7 +199,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev) return 0; } -static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name) +static struct se_device *rd_alloc_device(struct se_hba *hba, const char *name) { struct rd_dev *rd_dev; struct rd_host *rd_host = hba->hba_ptr; @@ -209,39 +212,27 @@ static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name) rd_dev->rd_host = rd_host; - return rd_dev; + return &rd_dev->dev; } -static struct se_device *rd_create_virtdevice(struct se_hba *hba, - struct se_subsystem_dev *se_dev, void *p) +static int rd_configure_device(struct se_device *dev) { - struct se_device *dev; - struct se_dev_limits dev_limits; - struct rd_dev *rd_dev = p; - struct rd_host *rd_host = hba->hba_ptr; - int dev_flags = 0, ret; - char prod[16], rev[4]; + struct rd_dev *rd_dev = RD_DEV(dev); + struct rd_host *rd_host = dev->se_hba->hba_ptr; + int ret; - memset(&dev_limits, 0, sizeof(struct se_dev_limits)); + if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) { + pr_debug("Missing rd_pages= parameter\n"); + return -EINVAL; + } ret = rd_build_device_space(rd_dev); if (ret < 0) goto fail; - snprintf(prod, 16, "RAMDISK-MCP"); - snprintf(rev, 4, "%s", RD_MCP_VERSION); - - dev_limits.limits.logical_block_size = RD_BLOCKSIZE; - dev_limits.limits.max_hw_sectors = UINT_MAX; - dev_limits.limits.max_sectors = UINT_MAX; - dev_limits.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH; - dev_limits.queue_depth = RD_DEVICE_QUEUE_DEPTH; - - dev = transport_add_device_to_core_hba(hba, - &rd_mcp_template, se_dev, dev_flags, rd_dev, - &dev_limits, prod, rev); - if (!dev) - goto fail; + dev->dev_attrib.hw_block_size = RD_BLOCKSIZE; + dev->dev_attrib.hw_max_sectors = UINT_MAX; + dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH; rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++; @@ -251,16 +242,16 @@ static struct se_device *rd_create_virtdevice(struct se_hba *hba, rd_dev->sg_table_count, (unsigned long)(rd_dev->rd_page_count * PAGE_SIZE)); - return dev; + return 0; fail: rd_release_device_space(rd_dev); - return ERR_PTR(ret); + return ret; } -static void rd_free_device(void *p) +static void rd_free_device(struct se_device *dev) { - struct rd_dev *rd_dev = p; + struct rd_dev *rd_dev = RD_DEV(dev); rd_release_device_space(rd_dev); kfree(rd_dev); @@ -290,7 +281,7 @@ static int rd_execute_rw(struct se_cmd *cmd) u32 sgl_nents = cmd->t_data_nents; enum dma_data_direction data_direction = cmd->data_direction; struct se_device *se_dev = cmd->se_dev; - struct rd_dev *dev = se_dev->dev_ptr; + struct rd_dev *dev = RD_DEV(se_dev); struct rd_dev_sg_table *table; struct scatterlist *rd_sg; struct sg_mapping_iter m; @@ -300,7 +291,7 @@ static int rd_execute_rw(struct se_cmd *cmd) u32 src_len; u64 tmp; - tmp = cmd->t_task_lba * se_dev->se_sub_dev->se_dev_attrib.block_size; + tmp = cmd->t_task_lba * se_dev->dev_attrib.block_size; rd_offset = do_div(tmp, PAGE_SIZE); rd_page = tmp; rd_size = cmd->data_length; @@ -378,13 +369,10 @@ static match_table_t tokens = { {Opt_err, NULL} }; -static ssize_t rd_set_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - const char *page, - ssize_t count) +static ssize_t rd_set_configfs_dev_params(struct se_device *dev, + const char *page, ssize_t count) { - struct rd_dev *rd_dev = se_dev->se_dev_su_ptr; + struct rd_dev *rd_dev = RD_DEV(dev); char *orig, *ptr, *opts; substring_t args[MAX_OPT_ARGS]; int ret = 0, arg, token; @@ -417,24 +405,10 @@ static ssize_t rd_set_configfs_dev_params( return (!ret) ? count : ret; } -static ssize_t rd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev) +static ssize_t rd_show_configfs_dev_params(struct se_device *dev, char *b) { - struct rd_dev *rd_dev = se_dev->se_dev_su_ptr; - - if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) { - pr_debug("Missing rd_pages= parameter\n"); - return -EINVAL; - } + struct rd_dev *rd_dev = RD_DEV(dev); - return 0; -} - -static ssize_t rd_show_configfs_dev_params( - struct se_hba *hba, - struct se_subsystem_dev *se_dev, - char *b) -{ - struct rd_dev *rd_dev = se_dev->se_dev_su_ptr; ssize_t bl = sprintf(b, "TCM RamDisk ID: %u RamDisk Makeup: rd_mcp\n", rd_dev->rd_dev_id); bl += sprintf(b + bl, " PAGES/PAGE_SIZE: %u*%lu" @@ -455,9 +429,10 @@ static u32 rd_get_device_type(struct se_device *dev) static sector_t rd_get_blocks(struct se_device *dev) { - struct rd_dev *rd_dev = dev->dev_ptr; + struct rd_dev *rd_dev = RD_DEV(dev); + unsigned long long blocks_long = ((rd_dev->rd_page_count * PAGE_SIZE) / - dev->se_sub_dev->se_dev_attrib.block_size) - 1; + dev->dev_attrib.block_size) - 1; return blocks_long; } @@ -473,14 +448,15 @@ static int rd_parse_cdb(struct se_cmd *cmd) static struct se_subsystem_api rd_mcp_template = { .name = "rd_mcp", + .inquiry_prod = "RAMDISK-MCP", + .inquiry_rev = RD_MCP_VERSION, .transport_type = TRANSPORT_PLUGIN_VHBA_VDEV, .attach_hba = rd_attach_hba, .detach_hba = rd_detach_hba, - .allocate_virtdevice = rd_allocate_virtdevice, - .create_virtdevice = rd_create_virtdevice, + .alloc_device = rd_alloc_device, + .configure_device = rd_configure_device, .free_device = rd_free_device, .parse_cdb = rd_parse_cdb, - .check_configfs_dev_params = rd_check_configfs_dev_params, .set_configfs_dev_params = rd_set_configfs_dev_params, .show_configfs_dev_params = rd_show_configfs_dev_params, .get_device_rev = rd_get_device_rev, diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h index 2145812..933b38b 100644 --- a/drivers/target/target_core_rd.h +++ b/drivers/target/target_core_rd.h @@ -24,6 +24,7 @@ struct rd_dev_sg_table { #define RDF_HAS_PAGE_COUNT 0x01 struct rd_dev { + struct se_device dev; u32 rd_flags; /* Unique Ramdisk Device ID in Ramdisk HBA */ u32 rd_dev_id; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a6e27d9..035193d 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -54,10 +54,10 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd) buf[1] = (blocks >> 16) & 0xff; buf[2] = (blocks >> 8) & 0xff; buf[3] = blocks & 0xff; - buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff; - buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff; - buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff; - buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff; + buf[4] = (dev->dev_attrib.block_size >> 24) & 0xff; + buf[5] = (dev->dev_attrib.block_size >> 16) & 0xff; + buf[6] = (dev->dev_attrib.block_size >> 8) & 0xff; + buf[7] = dev->dev_attrib.block_size & 0xff; rbuf = transport_kmap_data_sg(cmd); if (rbuf) { @@ -85,15 +85,15 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) buf[5] = (blocks >> 16) & 0xff; buf[6] = (blocks >> 8) & 0xff; buf[7] = blocks & 0xff; - buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff; - buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff; - buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff; - buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff; + buf[8] = (dev->dev_attrib.block_size >> 24) & 0xff; + buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff; + buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff; + buf[11] = dev->dev_attrib.block_size & 0xff; /* * Set Thin Provisioning Enable bit following sbc3r22 in section * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled. */ - if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) + if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) buf[14] = 0x80; rbuf = transport_kmap_data_sg(cmd); @@ -143,7 +143,7 @@ static int sbc_emulate_noop(struct se_cmd *cmd) static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) { - return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; + return cmd->se_dev->dev_attrib.block_size * sectors; } static int sbc_check_valid_sectors(struct se_cmd *cmd) @@ -152,7 +152,7 @@ static int sbc_check_valid_sectors(struct se_cmd *cmd) unsigned long long end_lba; u32 sectors; - sectors = cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size; + sectors = cmd->data_length / dev->dev_attrib.block_size; end_lba = dev->transport->get_blocks(dev) + 1; if (cmd->t_task_lba + sectors > end_lba) { @@ -315,7 +315,6 @@ out: int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) { - struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; unsigned int size; @@ -562,18 +561,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { unsigned long long end_lba; - if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) { + if (sectors > dev->dev_attrib.fabric_max_sectors) { printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" " big sectors %u exceeds fabric_max_sectors:" " %u\n", cdb[0], sectors, - su_dev->se_dev_attrib.fabric_max_sectors); + dev->dev_attrib.fabric_max_sectors); goto out_invalid_cdb_field; } - if (sectors > su_dev->se_dev_attrib.hw_max_sectors) { + if (sectors > dev->dev_attrib.hw_max_sectors) { printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" " big sectors %u exceeds backend hw_max_sectors:" " %u\n", cdb[0], sectors, - su_dev->se_dev_attrib.hw_max_sectors); + dev->dev_attrib.hw_max_sectors); goto out_invalid_cdb_field; } diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 6fd434d..0af45ae 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -95,14 +95,14 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) /* * Enable SCCS and TPGS fields for Emulated ALUA */ - if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) + if (dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) spc_fill_alua_data(lun->lun_sep, buf); buf[7] = 0x2; /* CmdQue=1 */ snprintf(&buf[8], 8, "LIO-ORG"); - snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model); - snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision); + snprintf(&buf[16], 16, "%s", dev->t10_wwn.model); + snprintf(&buf[32], 4, "%s", dev->t10_wwn.revision); buf[4] = 31; /* Set additional length to 31 */ return 0; @@ -114,15 +114,13 @@ static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) struct se_device *dev = cmd->se_dev; u16 len = 0; - if (dev->se_sub_dev->su_dev_flags & - SDF_EMULATED_VPD_UNIT_SERIAL) { + if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { u32 unit_serial_len; - unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial); + unit_serial_len = strlen(dev->t10_wwn.unit_serial); unit_serial_len++; /* For NULL Terminator */ - len += sprintf(&buf[4], "%s", - dev->se_sub_dev->t10_wwn.unit_serial); + len += sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); len++; /* Extra Byte for NULL Terminator */ buf[3] = len; } @@ -132,7 +130,7 @@ static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf) { - unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0]; + unsigned char *p = &dev->t10_wwn.unit_serial[0]; int cnt; bool next = true; @@ -173,7 +171,7 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) struct t10_alua_lu_gp_member *lu_gp_mem; struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; - unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0]; + unsigned char *prod = &dev->t10_wwn.model[0]; u32 prod_len; u32 unit_serial_len, off = 0; u16 len = 0, id_len; @@ -188,7 +186,7 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial * value in order to return the NAA id. */ - if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL)) + if (!(dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL)) goto check_t10_vend_desc; /* CODE SET == Binary */ @@ -236,14 +234,12 @@ check_t10_vend_desc: prod_len += strlen(prod); prod_len++; /* For : */ - if (dev->se_sub_dev->su_dev_flags & - SDF_EMULATED_VPD_UNIT_SERIAL) { - unit_serial_len = - strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]); + if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { + unit_serial_len = strlen(&dev->t10_wwn.unit_serial[0]); unit_serial_len++; /* For NULL Terminator */ id_len += sprintf(&buf[off+12], "%s:%s", prod, - &dev->se_sub_dev->t10_wwn.unit_serial[0]); + &dev->t10_wwn.unit_serial[0]); } buf[off] = 0x2; /* ASCII */ buf[off+1] = 0x1; /* T10 Vendor ID */ @@ -298,8 +294,7 @@ check_t10_vend_desc: * Get the PROTOCOL IDENTIFIER as defined by spc4r17 * section 7.5.1 Table 362 */ - if (dev->se_sub_dev->t10_alua.alua_type != - SPC3_ALUA_EMULATED) + if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) goto check_scsi_name; tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; @@ -422,7 +417,7 @@ static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) buf[5] = 0x07; /* If WriteCache emulation is enabled, set V_SUP */ - if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) + if (cmd->se_dev->dev_attrib.emulate_write_cache > 0) buf[6] = 0x01; return 0; } @@ -439,7 +434,7 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) * emulate_tpu=1 or emulate_tpws=1 we will be expect a * different page length for Thin Provisioning. */ - if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) + if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) have_tp = 1; buf[0] = dev->transport->get_device_type(dev); @@ -456,14 +451,14 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) /* * Set MAXIMUM TRANSFER LENGTH */ - max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors, - dev->se_sub_dev->se_dev_attrib.hw_max_sectors); + max_sectors = min(dev->dev_attrib.fabric_max_sectors, + dev->dev_attrib.hw_max_sectors); put_unaligned_be32(max_sectors, &buf[8]); /* * Set OPTIMAL TRANSFER LENGTH */ - put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]); + put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); /* * Exit now if we don't support TP. @@ -474,25 +469,25 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) /* * Set MAXIMUM UNMAP LBA COUNT */ - put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]); + put_unaligned_be32(dev->dev_attrib.max_unmap_lba_count, &buf[20]); /* * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT */ - put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count, + put_unaligned_be32(dev->dev_attrib.max_unmap_block_desc_count, &buf[24]); /* * Set OPTIMAL UNMAP GRANULARITY */ - put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]); + put_unaligned_be32(dev->dev_attrib.unmap_granularity, &buf[28]); /* * UNMAP GRANULARITY ALIGNMENT */ - put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment, + put_unaligned_be32(dev->dev_attrib.unmap_granularity_alignment, &buf[32]); - if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0) + if (dev->dev_attrib.unmap_granularity_alignment != 0) buf[32] |= 0x80; /* Set the UGAVALID bit */ return 0; @@ -505,7 +500,7 @@ static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) buf[0] = dev->transport->get_device_type(dev); buf[3] = 0x3c; - buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0; + buf[5] = dev->dev_attrib.is_nonrot ? 1 : 0; return 0; } @@ -546,7 +541,7 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) * the UNMAP command (see 5.25). A TPU bit set to zero indicates * that the device server does not support the UNMAP command. */ - if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0) + if (dev->dev_attrib.emulate_tpu != 0) buf[5] = 0x80; /* @@ -555,7 +550,7 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) * A TPWS bit set to zero indicates that the device server does not * support the use of the WRITE SAME (16) command to unmap LBAs. */ - if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0) + if (dev->dev_attrib.emulate_tpws != 0) buf[5] |= 0x40; return 0; @@ -586,8 +581,7 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) * Registered Extended LUN WWN has been set via ConfigFS * during device creation/restart. */ - if (cmd->se_dev->se_sub_dev->su_dev_flags & - SDF_EMULATED_VPD_UNIT_SERIAL) { + if (cmd->se_dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { buf[3] = ARRAY_SIZE(evpd_handlers); for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) buf[p + 4] = evpd_handlers[p].page; @@ -690,7 +684,7 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) * command sequence order shall be explicitly handled by the application client * through the selection of appropriate ommands and task attributes. */ - p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10; + p[3] = (dev->dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10; /* * From spc4r17, section 7.4.6 Control mode Page * @@ -720,8 +714,8 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless * to the number of commands completed with one of those status codes. */ - p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 : - (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; + p[4] = (dev->dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 : + (dev->dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; /* * From spc4r17, section 7.4.6 Control mode Page * @@ -734,7 +728,7 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) * which the command was received shall be completed with TASK ABORTED * status (see SAM-4). */ - p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00; + p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00; p[8] = 0xff; p[9] = 0xff; p[11] = 30; @@ -746,7 +740,7 @@ static int spc_modesense_caching(struct se_device *dev, unsigned char *p) { p[0] = 0x08; p[1] = 0x12; - if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) + if (dev->dev_attrib.emulate_write_cache > 0) p[2] = 0x04; /* Write Cache Enable */ p[12] = 0x20; /* Disabled Read Ahead */ @@ -826,8 +820,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) spc_modesense_write_protect(&buf[3], type); - if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && - (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) + if ((dev->dev_attrib.emulate_write_cache > 0) && + (dev->dev_attrib.emulate_fua_write > 0)) spc_modesense_dpofua(&buf[3], type); } else { offset -= 1; @@ -839,8 +833,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) spc_modesense_write_protect(&buf[2], type); - if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && - (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) + if ((dev->dev_attrib.emulate_write_cache > 0) && + (dev->dev_attrib.emulate_fua_write > 0)) spc_modesense_dpofua(&buf[2], type); } @@ -923,7 +917,6 @@ static int spc_emulate_testunitready(struct se_cmd *cmd) int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) { struct se_device *dev = cmd->se_dev; - struct se_subsystem_dev *su_dev = dev->se_sub_dev; unsigned char *cdb = cmd->t_task_cdb; switch (cdb[0]) { @@ -946,12 +939,12 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) *size = (cdb[7] << 8) + cdb[8]; break; case PERSISTENT_RESERVE_IN: - if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) cmd->execute_cmd = target_scsi3_emulate_pr_in; *size = (cdb[7] << 8) + cdb[8]; break; case PERSISTENT_RESERVE_OUT: - if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) + if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) cmd->execute_cmd = target_scsi3_emulate_pr_out; *size = (cdb[7] << 8) + cdb[8]; break; @@ -962,7 +955,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) else *size = cmd->data_length; - if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) + if (dev->t10_pr.res_type != SPC_PASSTHROUGH) cmd->execute_cmd = target_scsi2_reservation_release; break; case RESERVE: @@ -983,7 +976,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * is running in SPC_PASSTHROUGH, and wants reservations * emulation disabled. */ - if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) + if (dev->t10_pr.res_type != SPC_PASSTHROUGH) cmd->execute_cmd = target_scsi2_reservation_reserve; break; case REQUEST_SENSE: @@ -1040,7 +1033,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * Check for emulated MI_REPORT_TARGET_PGS */ if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS && - su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { cmd->execute_cmd = target_emulate_report_target_port_groups; } @@ -1059,7 +1052,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * Check for emulated MO_SET_TARGET_PGS. */ if (cdb[1] == MO_SET_TARGET_PGS && - su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { cmd->execute_cmd = target_emulate_set_target_port_groups; } diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c index cb6b003..9bbb017 100644 --- a/drivers/target/target_core_stat.c +++ b/drivers/target/target_core_stat.c @@ -80,13 +80,9 @@ static struct target_stat_scsi_dev_attribute \ static ssize_t target_stat_scsi_dev_show_attr_inst( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_hba *hba = se_subdev->se_dev_hba; - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); + struct se_hba *hba = dev->se_hba; return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); } @@ -95,12 +91,8 @@ DEV_STAT_SCSI_DEV_ATTR_RO(inst); static ssize_t target_stat_scsi_dev_show_attr_indx( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); } @@ -109,13 +101,6 @@ DEV_STAT_SCSI_DEV_ATTR_RO(indx); static ssize_t target_stat_scsi_dev_show_attr_role( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; - return snprintf(page, PAGE_SIZE, "Target\n"); } DEV_STAT_SCSI_DEV_ATTR_RO(role); @@ -123,12 +108,8 @@ DEV_STAT_SCSI_DEV_ATTR_RO(role); static ssize_t target_stat_scsi_dev_show_attr_ports( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_port_count); } @@ -176,13 +157,9 @@ static struct target_stat_scsi_tgt_dev_attribute \ static ssize_t target_stat_scsi_tgt_dev_show_attr_inst( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_hba *hba = se_subdev->se_dev_hba; - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); + struct se_hba *hba = dev->se_hba; return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); } @@ -191,12 +168,8 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst); static ssize_t target_stat_scsi_tgt_dev_show_attr_indx( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); } @@ -205,13 +178,6 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx); static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; - return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT); } DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus); @@ -219,60 +185,27 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus); static ssize_t target_stat_scsi_tgt_dev_show_attr_status( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - char status[16]; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); - if (!dev) - return -ENODEV; - - switch (dev->dev_status) { - case TRANSPORT_DEVICE_ACTIVATED: - strcpy(status, "activated"); - break; - case TRANSPORT_DEVICE_DEACTIVATED: - strcpy(status, "deactivated"); - break; - case TRANSPORT_DEVICE_SHUTDOWN: - strcpy(status, "shutdown"); - break; - case TRANSPORT_DEVICE_OFFLINE_ACTIVATED: - case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED: - strcpy(status, "offline"); - break; - default: - sprintf(status, "unknown(%d)", dev->dev_status); - break; - } - - return snprintf(page, PAGE_SIZE, "%s\n", status); + if (dev->export_count) + return snprintf(page, PAGE_SIZE, "activated"); + else + return snprintf(page, PAGE_SIZE, "deactivated"); } DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status); static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); int non_accessible_lus; - if (!dev) - return -ENODEV; - - switch (dev->dev_status) { - case TRANSPORT_DEVICE_ACTIVATED: + if (dev->export_count) non_accessible_lus = 0; - break; - case TRANSPORT_DEVICE_DEACTIVATED: - case TRANSPORT_DEVICE_SHUTDOWN: - case TRANSPORT_DEVICE_OFFLINE_ACTIVATED: - case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED: - default: + else non_accessible_lus = 1; - break; - } return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus); } @@ -281,12 +214,8 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus); static ssize_t target_stat_scsi_tgt_dev_show_attr_resets( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets); } @@ -335,13 +264,9 @@ static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \ static ssize_t target_stat_scsi_lu_show_attr_inst( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_hba *hba = se_subdev->se_dev_hba; - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); + struct se_hba *hba = dev->se_hba; return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index); } @@ -350,12 +275,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(inst); static ssize_t target_stat_scsi_lu_show_attr_dev( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); } @@ -364,13 +285,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(dev); static ssize_t target_stat_scsi_lu_show_attr_indx( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; - return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX); } DEV_STAT_SCSI_LU_ATTR_RO(indx); @@ -378,12 +292,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(indx); static ssize_t target_stat_scsi_lu_show_attr_lun( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; /* FIXME: scsiLuDefaultLun */ return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0); } @@ -392,35 +300,28 @@ DEV_STAT_SCSI_LU_ATTR_RO(lun); static ssize_t target_stat_scsi_lu_show_attr_lu_name( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); - if (!dev) - return -ENODEV; /* scsiLuWwnName */ return snprintf(page, PAGE_SIZE, "%s\n", - (strlen(dev->se_sub_dev->t10_wwn.unit_serial)) ? - dev->se_sub_dev->t10_wwn.unit_serial : "None"); + (strlen(dev->t10_wwn.unit_serial)) ? + dev->t10_wwn.unit_serial : "None"); } DEV_STAT_SCSI_LU_ATTR_RO(lu_name); static ssize_t target_stat_scsi_lu_show_attr_vend( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); int i; - char str[sizeof(dev->se_sub_dev->t10_wwn.vendor)+1]; - - if (!dev) - return -ENODEV; + char str[sizeof(dev->t10_wwn.vendor)+1]; /* scsiLuVendorId */ - for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++) - str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.vendor[i]) ? - dev->se_sub_dev->t10_wwn.vendor[i] : ' '; + for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++) + str[i] = ISPRINT(dev->t10_wwn.vendor[i]) ? + dev->t10_wwn.vendor[i] : ' '; str[i] = '\0'; return snprintf(page, PAGE_SIZE, "%s\n", str); } @@ -429,19 +330,15 @@ DEV_STAT_SCSI_LU_ATTR_RO(vend); static ssize_t target_stat_scsi_lu_show_attr_prod( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); int i; - char str[sizeof(dev->se_sub_dev->t10_wwn.model)+1]; - - if (!dev) - return -ENODEV; + char str[sizeof(dev->t10_wwn.model)+1]; /* scsiLuProductId */ - for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++) - str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.model[i]) ? - dev->se_sub_dev->t10_wwn.model[i] : ' '; + for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++) + str[i] = ISPRINT(dev->t10_wwn.model[i]) ? + dev->t10_wwn.model[i] : ' '; str[i] = '\0'; return snprintf(page, PAGE_SIZE, "%s\n", str); } @@ -450,19 +347,15 @@ DEV_STAT_SCSI_LU_ATTR_RO(prod); static ssize_t target_stat_scsi_lu_show_attr_rev( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); int i; - char str[sizeof(dev->se_sub_dev->t10_wwn.revision)+1]; - - if (!dev) - return -ENODEV; + char str[sizeof(dev->t10_wwn.revision)+1]; /* scsiLuRevisionId */ - for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.revision); i++) - str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.revision[i]) ? - dev->se_sub_dev->t10_wwn.revision[i] : ' '; + for (i = 0; i < sizeof(dev->t10_wwn.revision); i++) + str[i] = ISPRINT(dev->t10_wwn.revision[i]) ? + dev->t10_wwn.revision[i] : ' '; str[i] = '\0'; return snprintf(page, PAGE_SIZE, "%s\n", str); } @@ -471,12 +364,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(rev); static ssize_t target_stat_scsi_lu_show_attr_dev_type( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuPeripheralType */ return snprintf(page, PAGE_SIZE, "%u\n", @@ -487,30 +376,18 @@ DEV_STAT_SCSI_LU_ATTR_RO(dev_type); static ssize_t target_stat_scsi_lu_show_attr_status( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuStatus */ return snprintf(page, PAGE_SIZE, "%s\n", - (dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ? - "available" : "notavailable"); + (dev->export_count) ? "available" : "notavailable"); } DEV_STAT_SCSI_LU_ATTR_RO(status); static ssize_t target_stat_scsi_lu_show_attr_state_bit( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; - /* scsiLuState */ return snprintf(page, PAGE_SIZE, "exposed\n"); } @@ -519,12 +396,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(state_bit); static ssize_t target_stat_scsi_lu_show_attr_num_cmds( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuNumCommands */ return snprintf(page, PAGE_SIZE, "%llu\n", @@ -535,12 +408,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(num_cmds); static ssize_t target_stat_scsi_lu_show_attr_read_mbytes( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuReadMegaBytes */ return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->read_bytes >> 20)); @@ -550,12 +419,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes); static ssize_t target_stat_scsi_lu_show_attr_write_mbytes( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuWrittenMegaBytes */ return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->write_bytes >> 20)); @@ -565,12 +430,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes); static ssize_t target_stat_scsi_lu_show_attr_resets( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuInResets */ return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets); @@ -580,13 +441,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(resets); static ssize_t target_stat_scsi_lu_show_attr_full_stat( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; - /* FIXME: scsiLuOutTaskSetFullStatus */ return snprintf(page, PAGE_SIZE, "%u\n", 0); } @@ -595,13 +449,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(full_stat); static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; - /* FIXME: scsiLuHSInCommands */ return snprintf(page, PAGE_SIZE, "%u\n", 0); } @@ -610,12 +457,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds); static ssize_t target_stat_scsi_lu_show_attr_creation_time( struct se_dev_stat_grps *sgrps, char *page) { - struct se_subsystem_dev *se_subdev = container_of(sgrps, - struct se_subsystem_dev, dev_stat_grps); - struct se_device *dev = se_subdev->se_dev_ptr; - - if (!dev) - return -ENODEV; + struct se_device *dev = + container_of(sgrps, struct se_device, dev_stat_grps); /* scsiLuCreationTime */ return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time - @@ -662,20 +505,20 @@ static struct config_item_type target_stat_scsi_lu_cit = { * Called from target_core_configfs.c:target_core_make_subdev() to setup * the target statistics groups + configfs CITs located in target_core_stat.c */ -void target_stat_setup_dev_default_groups(struct se_subsystem_dev *se_subdev) +void target_stat_setup_dev_default_groups(struct se_device *dev) { - struct config_group *dev_stat_grp = &se_subdev->dev_stat_grps.stat_group; + struct config_group *dev_stat_grp = &dev->dev_stat_grps.stat_group; - config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_dev_group, + config_group_init_type_name(&dev->dev_stat_grps.scsi_dev_group, "scsi_dev", &target_stat_scsi_dev_cit); - config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_tgt_dev_group, + config_group_init_type_name(&dev->dev_stat_grps.scsi_tgt_dev_group, "scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit); - config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_lu_group, + config_group_init_type_name(&dev->dev_stat_grps.scsi_lu_group, "scsi_lu", &target_stat_scsi_lu_cit); - dev_stat_grp->default_groups[0] = &se_subdev->dev_stat_grps.scsi_dev_group; - dev_stat_grp->default_groups[1] = &se_subdev->dev_stat_grps.scsi_tgt_dev_group; - dev_stat_grp->default_groups[2] = &se_subdev->dev_stat_grps.scsi_lu_group; + dev_stat_grp->default_groups[0] = &dev->dev_stat_grps.scsi_dev_group; + dev_stat_grp->default_groups[1] = &dev->dev_stat_grps.scsi_tgt_dev_group; + dev_stat_grp->default_groups[2] = &dev->dev_stat_grps.scsi_lu_group; dev_stat_grp->default_groups[3] = NULL; } @@ -1161,7 +1004,7 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name( return -ENODEV; } tpg = sep->sep_tpg; - wwn = &dev->se_sub_dev->t10_wwn; + wwn = &dev->t10_wwn; /* scsiTransportDevName */ ret = snprintf(page, PAGE_SIZE, "%s+%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg), diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index be75c43..2aaceae 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -371,7 +371,7 @@ int core_tmr_lun_reset( * which the command was received shall be completed with TASK ABORTED * status (see SAM-4). */ - tas = dev->se_sub_dev->se_dev_attrib.emulate_tas; + tas = dev->dev_attrib.emulate_tas; /* * Determine if this se_tmr is coming from a $FABRIC_MOD * or struct se_device passthrough.. @@ -399,10 +399,10 @@ int core_tmr_lun_reset( * LOGICAL UNIT RESET */ if (!preempt_and_abort_list && - (dev->dev_flags & DF_SPC2_RESERVATIONS)) { + (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)) { spin_lock(&dev->dev_reservation_lock); dev->dev_reserved_node_acl = NULL; - dev->dev_flags &= ~DF_SPC2_RESERVATIONS; + dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS; spin_unlock(&dev->dev_reservation_lock); pr_debug("LUN_RESET: SCSI-2 Released reservation\n"); } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 9097155..d6d24a4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -659,7 +659,7 @@ static void target_add_to_state_list(struct se_cmd *cmd) static void transport_write_pending_qf(struct se_cmd *cmd); static void transport_complete_qf(struct se_cmd *cmd); -static void target_qf_do_work(struct work_struct *work) +void target_qf_do_work(struct work_struct *work) { struct se_device *dev = container_of(work, struct se_device, qf_work_queue); @@ -712,29 +712,15 @@ void transport_dump_dev_state( int *bl) { *bl += sprintf(b + *bl, "Status: "); - switch (dev->dev_status) { - case TRANSPORT_DEVICE_ACTIVATED: + if (dev->export_count) *bl += sprintf(b + *bl, "ACTIVATED"); - break; - case TRANSPORT_DEVICE_DEACTIVATED: + else *bl += sprintf(b + *bl, "DEACTIVATED"); - break; - case TRANSPORT_DEVICE_SHUTDOWN: - *bl += sprintf(b + *bl, "SHUTDOWN"); - break; - case TRANSPORT_DEVICE_OFFLINE_ACTIVATED: - case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED: - *bl += sprintf(b + *bl, "OFFLINE"); - break; - default: - *bl += sprintf(b + *bl, "UNKNOWN=%d", dev->dev_status); - break; - } *bl += sprintf(b + *bl, " Max Queue Depth: %d", dev->queue_depth); *bl += sprintf(b + *bl, " SectorSize: %u HwMaxSectors: %u\n", - dev->se_sub_dev->se_dev_attrib.block_size, - dev->se_sub_dev->se_dev_attrib.hw_max_sectors); + dev->dev_attrib.block_size, + dev->dev_attrib.hw_max_sectors); *bl += sprintf(b + *bl, " "); } @@ -991,185 +977,6 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83) } EXPORT_SYMBOL(transport_set_vpd_ident); -static void core_setup_task_attr_emulation(struct se_device *dev) -{ - /* - * If this device is from Target_Core_Mod/pSCSI, disable the - * SAM Task Attribute emulation. - * - * This is currently not available in upsream Linux/SCSI Target - * mode code, and is assumed to be disabled while using TCM/pSCSI. - */ - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH; - return; - } - - dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED; - pr_debug("%s: Using SAM_TASK_ATTR_EMULATED for SPC: 0x%02x" - " device\n", dev->transport->name, - dev->transport->get_device_rev(dev)); -} - -static void scsi_dump_inquiry(struct se_device *dev) -{ - struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; - char buf[17]; - int i, device_type; - /* - * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer - */ - for (i = 0; i < 8; i++) - if (wwn->vendor[i] >= 0x20) - buf[i] = wwn->vendor[i]; - else - buf[i] = ' '; - buf[i] = '\0'; - pr_debug(" Vendor: %s\n", buf); - - for (i = 0; i < 16; i++) - if (wwn->model[i] >= 0x20) - buf[i] = wwn->model[i]; - else - buf[i] = ' '; - buf[i] = '\0'; - pr_debug(" Model: %s\n", buf); - - for (i = 0; i < 4; i++) - if (wwn->revision[i] >= 0x20) - buf[i] = wwn->revision[i]; - else - buf[i] = ' '; - buf[i] = '\0'; - pr_debug(" Revision: %s\n", buf); - - device_type = dev->transport->get_device_type(dev); - pr_debug(" Type: %s ", scsi_device_type(device_type)); - pr_debug(" ANSI SCSI revision: %02x\n", - dev->transport->get_device_rev(dev)); -} - -struct se_device *transport_add_device_to_core_hba( - struct se_hba *hba, - struct se_subsystem_api *transport, - struct se_subsystem_dev *se_dev, - u32 device_flags, - void *transport_dev, - struct se_dev_limits *dev_limits, - const char *inquiry_prod, - const char *inquiry_rev) -{ - int force_pt; - struct se_device *dev; - - dev = kzalloc(sizeof(struct se_device), GFP_KERNEL); - if (!dev) { - pr_err("Unable to allocate memory for se_dev_t\n"); - return NULL; - } - - dev->dev_flags = device_flags; - dev->dev_status |= TRANSPORT_DEVICE_DEACTIVATED; - dev->dev_ptr = transport_dev; - dev->se_hba = hba; - dev->se_sub_dev = se_dev; - dev->transport = transport; - INIT_LIST_HEAD(&dev->dev_list); - INIT_LIST_HEAD(&dev->dev_sep_list); - INIT_LIST_HEAD(&dev->dev_tmr_list); - INIT_LIST_HEAD(&dev->delayed_cmd_list); - INIT_LIST_HEAD(&dev->state_list); - INIT_LIST_HEAD(&dev->qf_cmd_list); - spin_lock_init(&dev->execute_task_lock); - spin_lock_init(&dev->delayed_cmd_lock); - spin_lock_init(&dev->dev_reservation_lock); - spin_lock_init(&dev->dev_status_lock); - spin_lock_init(&dev->se_port_lock); - spin_lock_init(&dev->se_tmr_lock); - spin_lock_init(&dev->qf_cmd_lock); - atomic_set(&dev->dev_ordered_id, 0); - - se_dev_set_default_attribs(dev, dev_limits); - - dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); - dev->creation_time = get_jiffies_64(); - spin_lock_init(&dev->stats_lock); - - spin_lock(&hba->device_lock); - list_add_tail(&dev->dev_list, &hba->hba_dev_list); - hba->dev_count++; - spin_unlock(&hba->device_lock); - /* - * Setup the SAM Task Attribute emulation for struct se_device - */ - core_setup_task_attr_emulation(dev); - /* - * Force PR and ALUA passthrough emulation with internal object use. - */ - force_pt = (hba->hba_flags & HBA_FLAGS_INTERNAL_USE); - /* - * Setup the Reservations infrastructure for struct se_device - */ - core_setup_reservations(dev, force_pt); - /* - * Setup the Asymmetric Logical Unit Assignment for struct se_device - */ - if (core_setup_alua(dev, force_pt) < 0) - goto err_dev_list; - - /* - * Startup the struct se_device processing thread - */ - dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1, - dev->transport->name); - if (!dev->tmr_wq) { - pr_err("Unable to create tmr workqueue for %s\n", - dev->transport->name); - goto err_dev_list; - } - /* - * Setup work_queue for QUEUE_FULL - */ - INIT_WORK(&dev->qf_work_queue, target_qf_do_work); - /* - * Preload the initial INQUIRY const values if we are doing - * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI - * passthrough because this is being provided by the backend LLD. - * This is required so that transport_get_inquiry() copies these - * originals once back into DEV_T10_WWN(dev) for the virtual device - * setup. - */ - if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { - if (!inquiry_prod || !inquiry_rev) { - pr_err("All non TCM/pSCSI plugins require" - " INQUIRY consts\n"); - goto err_wq; - } - - strncpy(&dev->se_sub_dev->t10_wwn.vendor[0], "LIO-ORG", 8); - strncpy(&dev->se_sub_dev->t10_wwn.model[0], inquiry_prod, 16); - strncpy(&dev->se_sub_dev->t10_wwn.revision[0], inquiry_rev, 4); - } - scsi_dump_inquiry(dev); - - return dev; - -err_wq: - destroy_workqueue(dev->tmr_wq); -err_dev_list: - spin_lock(&hba->device_lock); - list_del(&dev->dev_list); - hba->dev_count--; - spin_unlock(&hba->device_lock); - - se_release_vpd_for_dev(dev); - - kfree(dev); - - return NULL; -} -EXPORT_SYMBOL(transport_add_device_to_core_hba); - int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) { struct se_device *dev = cmd->se_dev; @@ -1191,7 +998,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) * Reject READ_* or WRITE_* with overflow/underflow for * type SCF_SCSI_DATA_CDB. */ - if (dev->se_sub_dev->se_dev_attrib.block_size != 512) { + if (dev->dev_attrib.block_size != 512) { pr_err("Failing OVERFLOW/UNDERFLOW for LBA op" " CDB on non 512-byte sector setup subsystem" " plugin: %s\n", dev->transport->name); @@ -1293,7 +1100,7 @@ int target_setup_cmd_from_cdb( struct se_cmd *cmd, unsigned char *cdb) { - struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; u32 pr_reg_type = 0; u8 alua_ascq = 0; unsigned long flags; @@ -1345,7 +1152,7 @@ int target_setup_cmd_from_cdb( return -EINVAL; } - ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); + ret = dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); if (ret != 0) { /* * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; @@ -1371,8 +1178,8 @@ int target_setup_cmd_from_cdb( /* * Check status for SPC-3 Persistent Reservations */ - if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) { - if (su_dev->t10_pr.pr_ops.t10_seq_non_holder( + if (dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) { + if (dev->t10_pr.pr_ops.t10_seq_non_holder( cmd, cdb, pr_reg_type) != 0) { cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; @@ -1387,7 +1194,7 @@ int target_setup_cmd_from_cdb( */ } - ret = cmd->se_dev->transport->parse_cdb(cmd); + ret = dev->transport->parse_cdb(cmd); if (ret < 0) return ret; @@ -1759,7 +1566,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) * See spc4r17, section 7.4.6 Control Mode Page, Table 349 */ if (cmd->se_sess && - cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) + cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2) core_scsi3_ua_allocate(cmd->se_sess->se_node_acl, cmd->orig_fe_lun, 0x2C, ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 6666a0c..59c95ee 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -237,7 +237,7 @@ void core_scsi3_ua_for_check_condition( * highest priority UNIT_ATTENTION and ASC/ASCQ without * clearing it. */ - if (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) { + if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) { *asc = ua->ua_asc; *ascq = ua->ua_ascq; break; @@ -265,8 +265,8 @@ void core_scsi3_ua_for_check_condition( " INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x" " reported ASC: 0x%02x, ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->get_fabric_name(), - (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : - "Releasing", dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl, + (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : + "Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl, cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); } diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 2acd540..6c5bfb5 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -9,6 +9,8 @@ struct se_subsystem_api { struct list_head sub_api_list; char name[16]; + char inquiry_prod[16]; + char inquiry_rev[4]; struct module *owner; u8 transport_type; @@ -16,21 +18,20 @@ struct se_subsystem_api { int (*attach_hba)(struct se_hba *, u32); void (*detach_hba)(struct se_hba *); int (*pmode_enable_hba)(struct se_hba *, unsigned long); - void *(*allocate_virtdevice)(struct se_hba *, const char *); - struct se_device *(*create_virtdevice)(struct se_hba *, - struct se_subsystem_dev *, void *); - void (*free_device)(void *); + + struct se_device *(*alloc_device)(struct se_hba *, const char *); + int (*configure_device)(struct se_device *); + void (*free_device)(struct se_device *device); + + ssize_t (*set_configfs_dev_params)(struct se_device *, + const char *, ssize_t); + ssize_t (*show_configfs_dev_params)(struct se_device *, char *); + void (*transport_complete)(struct se_cmd *cmd, struct scatterlist *, unsigned char *); int (*parse_cdb)(struct se_cmd *cmd); - ssize_t (*check_configfs_dev_params)(struct se_hba *, - struct se_subsystem_dev *); - ssize_t (*set_configfs_dev_params)(struct se_hba *, - struct se_subsystem_dev *, const char *, ssize_t); - ssize_t (*show_configfs_dev_params)(struct se_hba *, - struct se_subsystem_dev *, char *); u32 (*get_device_rev)(struct se_device *); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); @@ -47,10 +48,6 @@ struct spc_ops { int transport_subsystem_register(struct se_subsystem_api *); void transport_subsystem_release(struct se_subsystem_api *); -struct se_device *transport_add_device_to_core_hba(struct se_hba *, - struct se_subsystem_api *, struct se_subsystem_dev *, u32, - void *, struct se_dev_limits *, const char *, const char *); - void target_complete_cmd(struct se_cmd *, u8); int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5be8937..f6355fc 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -62,20 +62,6 @@ #define PYX_TRANSPORT_STATUS_INTERVAL 5 /* In seconds */ -/* - * struct se_subsystem_dev->su_dev_flags -*/ -#define SDF_FIRMWARE_VPD_UNIT_SERIAL 0x00000001 -#define SDF_EMULATED_VPD_UNIT_SERIAL 0x00000002 -#define SDF_USING_UDEV_PATH 0x00000004 -#define SDF_USING_ALIAS 0x00000008 - -/* - * struct se_device->dev_flags - */ -#define DF_SPC2_RESERVATIONS 0x00000001 -#define DF_SPC2_RESERVATIONS_WITH_ISID 0x00000002 - /* struct se_dev_attrib sanity values */ /* Default max_unmap_lba_count */ #define DA_MAX_UNMAP_LBA_COUNT 0 @@ -182,16 +168,6 @@ enum transport_lunflags_table { TRANSPORT_LUNFLAGS_READ_WRITE = 0x04, }; -/* struct se_device->dev_status */ -enum transport_device_status_table { - TRANSPORT_DEVICE_ACTIVATED = 0x01, - TRANSPORT_DEVICE_DEACTIVATED = 0x02, - TRANSPORT_DEVICE_QUEUE_FULL = 0x04, - TRANSPORT_DEVICE_SHUTDOWN = 0x08, - TRANSPORT_DEVICE_OFFLINE_ACTIVATED = 0x10, - TRANSPORT_DEVICE_OFFLINE_DEACTIVATED = 0x20, -}; - /* * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason * to signal which ASC/ASCQ sense payload should be built. @@ -246,10 +222,6 @@ enum tcm_tmrsp_table { TMR_FUNCTION_REJECTED = 255, }; -struct se_obj { - atomic_t obj_access_count; -}; - /* * Used by TCM Core internally to signal if ALUA emulation is enabled or * disabled, or running in with TCM/pSCSI passthrough mode @@ -288,7 +260,7 @@ struct t10_alua { u16 alua_tg_pt_gps_counter; u32 alua_tg_pt_gps_count; spinlock_t tg_pt_gps_lock; - struct se_subsystem_dev *t10_sub_dev; + struct se_device *t10_dev; /* Used for default ALUA Target Port Group */ struct t10_alua_tg_pt_gp *default_tg_pt_gp; /* Used for default ALUA Target Port Group ConfigFS group */ @@ -335,7 +307,7 @@ struct t10_alua_tg_pt_gp { atomic_t tg_pt_gp_ref_cnt; spinlock_t tg_pt_gp_lock; struct mutex tg_pt_gp_md_mutex; - struct se_subsystem_dev *tg_pt_gp_su_dev; + struct se_device *tg_pt_gp_dev; struct config_group tg_pt_gp_group; struct list_head tg_pt_gp_list; struct list_head tg_pt_gp_mem_list; @@ -366,7 +338,7 @@ struct t10_wwn { char revision[4]; char unit_serial[INQUIRY_VPD_SERIAL_LEN]; spinlock_t t10_vpd_lock; - struct se_subsystem_dev *t10_sub_dev; + struct se_device *t10_dev; struct config_group t10_wwn_group; struct list_head t10_vpd_list; }; @@ -662,15 +634,6 @@ struct se_dev_entry { struct list_head ua_list; }; -struct se_dev_limits { - /* Max supported HW queue depth */ - u32 hw_queue_depth; - /* Max supported virtual queue depth */ - u32 queue_depth; - /* From include/linux/blkdev.h for the other HW/SW limits. */ - struct queue_limits limits; -}; - struct se_dev_attrib { int emulate_dpo; int emulate_fua_write; @@ -696,7 +659,7 @@ struct se_dev_attrib { u32 max_unmap_block_desc_count; u32 unmap_granularity; u32 unmap_granularity_alignment; - struct se_subsystem_dev *da_sub_dev; + struct se_device *da_dev; struct config_group da_group; }; @@ -707,48 +670,24 @@ struct se_dev_stat_grps { struct config_group scsi_lu_group; }; -struct se_subsystem_dev { -/* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */ -#define SE_DEV_ALIAS_LEN 512 - unsigned char se_dev_alias[SE_DEV_ALIAS_LEN]; -/* Used for struct se_subsystem_dev->se_dev_udev_path[], must be less than PAGE_SIZE */ -#define SE_UDEV_PATH_LEN 512 - unsigned char se_dev_udev_path[SE_UDEV_PATH_LEN]; - u32 su_dev_flags; - struct se_hba *se_dev_hba; - struct se_device *se_dev_ptr; - struct se_dev_attrib se_dev_attrib; - /* T10 Asymmetric Logical Unit Assignment for Target Ports */ - struct t10_alua t10_alua; - /* T10 Inquiry and VPD WWN Information */ - struct t10_wwn t10_wwn; - /* T10 SPC-2 + SPC-3 Reservations */ - struct t10_reservation t10_pr; - spinlock_t se_dev_lock; - void *se_dev_su_ptr; - struct config_group se_dev_group; - /* For T10 Reservations */ - struct config_group se_dev_pr_group; - /* For target_core_stat.c groups */ - struct se_dev_stat_grps dev_stat_grps; -}; - struct se_device { /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ u32 dev_cur_ordered_id; u32 dev_flags; +#define DF_CONFIGURED 0x00000001 +#define DF_FIRMWARE_VPD_UNIT_SERIAL 0x00000002 +#define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004 +#define DF_USING_UDEV_PATH 0x00000008 +#define DF_USING_ALIAS 0x00000010 u32 dev_port_count; - /* See transport_device_status_table */ - u32 dev_status; /* Physical device queue depth */ u32 queue_depth; /* Used for SPC-2 reservations enforce of ISIDs */ u64 dev_res_bin_isid; t10_task_attr_index_t dev_task_attr_type; /* Pointer to transport specific device structure */ - void *dev_ptr; u32 dev_index; u64 creation_time; u32 num_resets; @@ -761,13 +700,13 @@ struct se_device { atomic_t dev_ordered_id; atomic_t dev_ordered_sync; atomic_t dev_qf_count; - struct se_obj dev_obj; - struct se_obj dev_access_obj; - struct se_obj dev_export_obj; + int export_count; spinlock_t delayed_cmd_lock; spinlock_t execute_task_lock; spinlock_t dev_reservation_lock; - spinlock_t dev_status_lock; + unsigned int dev_reservation_flags; +#define DRF_SPC2_RESERVATIONS 0x00000001 +#define DRF_SPC2_RESERVATIONS_WITH_ISID 0x00000002 spinlock_t se_port_lock; spinlock_t se_tmr_lock; spinlock_t qf_cmd_lock; @@ -786,7 +725,20 @@ struct se_device { struct list_head qf_cmd_list; /* Pointer to associated SE HBA */ struct se_hba *se_hba; - struct se_subsystem_dev *se_sub_dev; + /* T10 Inquiry and VPD WWN Information */ + struct t10_wwn t10_wwn; + /* T10 Asymmetric Logical Unit Assignment for Target Ports */ + struct t10_alua t10_alua; + /* T10 SPC-2 + SPC-3 Reservations */ + struct t10_reservation t10_pr; + struct se_dev_attrib dev_attrib; + struct config_group dev_group; + struct config_group dev_pr_group; + struct se_dev_stat_grps dev_stat_grps; +#define SE_DEV_ALIAS_LEN 512 /* must be less than PAGE_SIZE */ + unsigned char dev_alias[SE_DEV_ALIAS_LEN]; +#define SE_UDEV_PATH_LEN 512 /* must be less than PAGE_SIZE */ + unsigned char udev_path[SE_UDEV_PATH_LEN]; /* Pointer to template of function pointers for transport */ struct se_subsystem_api *transport; /* Linked list for struct se_hba struct se_device list */ @@ -803,8 +755,6 @@ struct se_hba { u32 hba_index; /* Pointer to transport specific host structure. */ void *hba_ptr; - /* Linked list for struct se_device */ - struct list_head hba_dev_list; struct list_head hba_node; spinlock_t device_lock; struct config_group hba_group; -- cgit v0.10.2 From 9e999a6c51fe74a41a76038c64ce038ff9243bfb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:50 -0400 Subject: target: rename spc_ops These really are sbc_ops, so name them correctly. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index a89d80d..571d364 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -528,14 +528,14 @@ static sector_t fd_get_blocks(struct se_device *dev) return div_u64(dev_size, dev->dev_attrib.block_size); } -static struct spc_ops fd_spc_ops = { +static struct sbc_ops fd_sbc_ops = { .execute_rw = fd_execute_rw, .execute_sync_cache = fd_execute_sync_cache, }; static int fd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &fd_spc_ops); + return sbc_parse_cdb(cmd, &fd_sbc_ops); } static struct se_subsystem_api fileio_template = { diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index dd6cd92..969eed8 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -709,7 +709,7 @@ static void iblock_bio_done(struct bio *bio, int err) iblock_complete_cmd(cmd); } -static struct spc_ops iblock_spc_ops = { +static struct sbc_ops iblock_sbc_ops = { .execute_rw = iblock_execute_rw, .execute_sync_cache = iblock_execute_sync_cache, .execute_write_same = iblock_execute_write_same, @@ -718,7 +718,7 @@ static struct spc_ops iblock_spc_ops = { static int iblock_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &iblock_spc_ops); + return sbc_parse_cdb(cmd, &iblock_sbc_ops); } static struct se_subsystem_api iblock_template = { diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index d083f39..1b36e67 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -437,13 +437,13 @@ static sector_t rd_get_blocks(struct se_device *dev) return blocks_long; } -static struct spc_ops rd_spc_ops = { +static struct sbc_ops rd_sbc_ops = { .execute_rw = rd_execute_rw, }; static int rd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &rd_spc_ops); + return sbc_parse_cdb(cmd, &rd_sbc_ops); } static struct se_subsystem_api rd_mcp_template = { diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 035193d..a77a19c 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -313,7 +313,7 @@ out: kfree(buf); } -int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) +int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 6c5bfb5..1c43955 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -38,7 +38,7 @@ struct se_subsystem_api { unsigned char *(*get_sense_buffer)(struct se_cmd *); }; -struct spc_ops { +struct sbc_ops { int (*execute_rw)(struct se_cmd *cmd); int (*execute_sync_cache)(struct se_cmd *cmd); int (*execute_write_same)(struct se_cmd *cmd); @@ -50,7 +50,7 @@ void transport_subsystem_release(struct se_subsystem_api *); void target_complete_cmd(struct se_cmd *, u8); -int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops); +int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); int spc_get_write_same_sectors(struct se_cmd *cmd); -- cgit v0.10.2 From d1b1f8053401aaf1dfe636afa6d361301e3ae8b7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:51 -0400 Subject: target: move REPORT LUNS emulation to target_core_spc.c Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index b27c75a..e45a709 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -646,69 +646,6 @@ void core_dev_unexport( lun->lun_se_dev = NULL; } -int target_report_luns(struct se_cmd *se_cmd) -{ - struct se_dev_entry *deve; - struct se_session *se_sess = se_cmd->se_sess; - unsigned char *buf; - u32 lun_count = 0, offset = 8, i; - - if (se_cmd->data_length < 16) { - pr_warn("REPORT LUNS allocation length %u too small\n", - se_cmd->data_length); - se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - - buf = transport_kmap_data_sg(se_cmd); - if (!buf) - return -ENOMEM; - - /* - * If no struct se_session pointer is present, this struct se_cmd is - * coming via a target_core_mod PASSTHROUGH op, and not through - * a $FABRIC_MOD. In that case, report LUN=0 only. - */ - if (!se_sess) { - int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); - lun_count = 1; - goto done; - } - - spin_lock_irq(&se_sess->se_node_acl->device_list_lock); - for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { - deve = se_sess->se_node_acl->device_list[i]; - if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) - continue; - /* - * We determine the correct LUN LIST LENGTH even once we - * have reached the initial allocation length. - * See SPC2-R20 7.19. - */ - lun_count++; - if ((offset + 8) > se_cmd->data_length) - continue; - - int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); - offset += 8; - } - spin_unlock_irq(&se_sess->se_node_acl->device_list_lock); - - /* - * See SPC3 r07, page 159. - */ -done: - lun_count *= 8; - buf[0] = ((lun_count >> 24) & 0xff); - buf[1] = ((lun_count >> 16) & 0xff); - buf[2] = ((lun_count >> 8) & 0xff); - buf[3] = (lun_count & 0xff); - transport_kunmap_data_sg(se_cmd); - - target_complete_cmd(se_cmd, GOOD); - return 0; -} - static void se_release_vpd_for_dev(struct se_device *dev) { struct t10_vpd *vpd, *vpd_tmp; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 5854ed6..2f37720 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -19,7 +19,6 @@ int core_dev_export(struct se_device *, struct se_portal_group *, struct se_lun *); void core_dev_unexport(struct se_device *, struct se_portal_group *, struct se_lun *); -int target_report_luns(struct se_cmd *); int se_dev_set_task_timeout(struct se_device *, u32); int se_dev_set_max_unmap_lba_count(struct se_device *, u32); int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 0af45ae..07b8270 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -908,6 +908,69 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return 0; } +static int spc_emulate_report_luns(struct se_cmd *cmd) +{ + struct se_dev_entry *deve; + struct se_session *sess = cmd->se_sess; + unsigned char *buf; + u32 lun_count = 0, offset = 8, i; + + if (cmd->data_length < 16) { + pr_warn("REPORT LUNS allocation length %u too small\n", + cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + + buf = transport_kmap_data_sg(cmd); + if (!buf) + return -ENOMEM; + + /* + * If no struct se_session pointer is present, this struct se_cmd is + * coming via a target_core_mod PASSTHROUGH op, and not through + * a $FABRIC_MOD. In that case, report LUN=0 only. + */ + if (!sess) { + int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); + lun_count = 1; + goto done; + } + + spin_lock_irq(&sess->se_node_acl->device_list_lock); + for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { + deve = sess->se_node_acl->device_list[i]; + if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) + continue; + /* + * We determine the correct LUN LIST LENGTH even once we + * have reached the initial allocation length. + * See SPC2-R20 7.19. + */ + lun_count++; + if ((offset + 8) > cmd->data_length) + continue; + + int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); + offset += 8; + } + spin_unlock_irq(&sess->se_node_acl->device_list_lock); + + /* + * See SPC3 r07, page 159. + */ +done: + lun_count *= 8; + buf[0] = ((lun_count >> 24) & 0xff); + buf[1] = ((lun_count >> 16) & 0xff); + buf[2] = ((lun_count >> 8) & 0xff); + buf[3] = (lun_count & 0xff); + transport_kunmap_data_sg(cmd); + + target_complete_cmd(cmd, GOOD); + return 0; +} + static int spc_emulate_testunitready(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); @@ -1013,7 +1076,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; break; case REPORT_LUNS: - cmd->execute_cmd = target_report_luns; + cmd->execute_cmd = spc_emulate_report_luns; *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; /* * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS -- cgit v0.10.2 From 8de530a523fd3cc46b5d8d96f3016298c5c808ac Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:52 -0400 Subject: target/pscsi: call spc_emulate_report_luns directly No need to indirect through spc_parse_cdb if we only ever call it for REPORT LUNS emulation. (nab: Add missing EXPORT_SYMBOL for spc_emulate_report_luns) Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index b296508..dc10e29 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -985,8 +985,6 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb) static int pscsi_parse_cdb(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - unsigned int dummy_size; - int ret; if (cmd->se_cmd_flags & SCF_BIDI) { cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; @@ -1003,10 +1001,7 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) */ switch (cdb[0]) { case REPORT_LUNS: - ret = spc_parse_cdb(cmd, &dummy_size); - if (ret) - return ret; - break; + return spc_emulate_report_luns(cmd); case READ_6: case READ_10: case READ_12: @@ -1020,10 +1015,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) /* FALLTHROUGH*/ default: cmd->execute_cmd = pscsi_execute_cmd; - break; + return 0; } - - return 0; } static int pscsi_execute_cmd(struct se_cmd *cmd) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 07b8270..1f1ddb8 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -908,7 +908,7 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return 0; } -static int spc_emulate_report_luns(struct se_cmd *cmd) +int spc_emulate_report_luns(struct se_cmd *cmd) { struct se_dev_entry *deve; struct se_session *sess = cmd->se_sess; @@ -970,6 +970,7 @@ done: target_complete_cmd(cmd, GOOD); return 0; } +EXPORT_SYMBOL(spc_emulate_report_luns); static int spc_emulate_testunitready(struct se_cmd *cmd) { diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 1c43955..e7a0305 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -52,6 +52,7 @@ void target_complete_cmd(struct se_cmd *, u8); int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); +int spc_emulate_report_luns(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd); void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); -- cgit v0.10.2 From 6f23ac8a39418d6c6711f4fd73cc4519067d7f08 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:53 -0400 Subject: target: provide generic sbc device type/revision helpers Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 571d364..2a3e2bb 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -491,24 +491,6 @@ static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b) return bl; } -/* fd_get_device_rev(): (Part of se_subsystem_api_t template) - * - * - */ -static u32 fd_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} - -/* fd_get_device_type(): (Part of se_subsystem_api_t template) - * - * - */ -static u32 fd_get_device_type(struct se_device *dev) -{ - return TYPE_DISK; -} - static sector_t fd_get_blocks(struct se_device *dev) { struct fd_dev *fd_dev = FD_DEV(dev); @@ -552,8 +534,8 @@ static struct se_subsystem_api fileio_template = { .parse_cdb = fd_parse_cdb, .set_configfs_dev_params = fd_set_configfs_dev_params, .show_configfs_dev_params = fd_show_configfs_dev_params, - .get_device_rev = fd_get_device_rev, - .get_device_type = fd_get_device_type, + .get_device_rev = sbc_get_device_rev, + .get_device_type = sbc_get_device_type, .get_blocks = fd_get_blocks, }; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 969eed8..701877f 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -664,16 +664,6 @@ fail: return -ENOMEM; } -static u32 iblock_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} - -static u32 iblock_get_device_type(struct se_device *dev) -{ - return TYPE_DISK; -} - static sector_t iblock_get_blocks(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -735,8 +725,8 @@ static struct se_subsystem_api iblock_template = { .parse_cdb = iblock_parse_cdb, .set_configfs_dev_params = iblock_set_configfs_dev_params, .show_configfs_dev_params = iblock_show_configfs_dev_params, - .get_device_rev = iblock_get_device_rev, - .get_device_type = iblock_get_device_type, + .get_device_rev = sbc_get_device_rev, + .get_device_type = sbc_get_device_type, .get_blocks = iblock_get_blocks, }; diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 1b36e67..6348b66 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -417,16 +417,6 @@ static ssize_t rd_show_configfs_dev_params(struct se_device *dev, char *b) return bl; } -static u32 rd_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} - -static u32 rd_get_device_type(struct se_device *dev) -{ - return TYPE_DISK; -} - static sector_t rd_get_blocks(struct se_device *dev) { struct rd_dev *rd_dev = RD_DEV(dev); @@ -459,8 +449,8 @@ static struct se_subsystem_api rd_mcp_template = { .parse_cdb = rd_parse_cdb, .set_configfs_dev_params = rd_set_configfs_dev_params, .show_configfs_dev_params = rd_show_configfs_dev_params, - .get_device_rev = rd_get_device_rev, - .get_device_type = rd_get_device_type, + .get_device_rev = sbc_get_device_rev, + .get_device_type = sbc_get_device_type, .get_blocks = rd_get_blocks, }; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a77a19c..0168695 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -603,3 +603,15 @@ out_invalid_cdb_field: return -EINVAL; } EXPORT_SYMBOL(sbc_parse_cdb); + +u32 sbc_get_device_rev(struct se_device *dev) +{ + return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ +} +EXPORT_SYMBOL(sbc_get_device_rev); + +u32 sbc_get_device_type(struct se_device *dev) +{ + return TYPE_DISK; +} +EXPORT_SYMBOL(sbc_get_device_type); diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index e7a0305..b7f3936 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -50,11 +50,14 @@ void transport_subsystem_release(struct se_subsystem_api *); void target_complete_cmd(struct se_cmd *, u8); -int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); int spc_emulate_report_luns(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd); +int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); +u32 sbc_get_device_rev(struct se_device *dev); +u32 sbc_get_device_type(struct se_device *dev); + void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *); -- cgit v0.10.2 From ecf0dd6642ecf7c0aff89c1be48b870586f4be4f Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Wed, 10 Oct 2012 07:30:20 +0800 Subject: target/pscsi: Make pscsi_configure_device + target_release_session static drivers/target/target_core_pscsi.c:464:5: sparse: symbol 'pscsi_configure_device' was not declared. Should it be static? FYI, there are new sparse warnings show up in tree: git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git queue head: 738b86ac5e56c645aa5b7bf49cb38e2a04c665f8 commit: 410aeee637c47bcf7e8dd7893347fe0811e07ab1 [47/51] target: kill struct se_subsystem_dev vim +464 drivers/target/target_core_pscsi.c 410aeee6 Christoph Hellwig 2012-10-08 @464 int pscsi_configure_device(struct se_device *dev) c66ac9db Nicholas Bellinger 2010-12-17 465 { 410aeee6 Christoph Hellwig 2012-10-08 466 struct se_hba *hba = dev->se_hba; 410aeee6 Christoph Hellwig 2012-10-08 467 struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); c66ac9db Nicholas Bellinger 2010-12-17 468 struct scsi_device *sd; 410aeee6 Christoph Hellwig 2012-10-08 469 struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; c66ac9db Nicholas Bellinger 2010-12-17 470 struct Scsi_Host *sh = phv->phv_lld_host; c66ac9db Nicholas Bellinger 2010-12-17 471 int legacy_mode_enable = 0; 410aeee6 Christoph Hellwig 2012-10-08 472 int ret; Please consider folding the attached diff :-) Signed-off-by: Fengguang Wu Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index dc10e29..c3bcc17 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -461,7 +461,7 @@ static int pscsi_create_type_other(struct se_device *dev, return 0; } -int pscsi_configure_device(struct se_device *dev) +static int pscsi_configure_device(struct se_device *dev) { struct se_hba *hba = dev->se_hba; struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d6d24a4..c80d884 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -297,7 +297,7 @@ void transport_register_session( } EXPORT_SYMBOL(transport_register_session); -void target_release_session(struct kref *kref) +static void target_release_session(struct kref *kref) { struct se_session *se_sess = container_of(kref, struct se_session, sess_kref); -- cgit v0.10.2 From e6c4219b54ac9d0bd348ea59e606303f9aef1784 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 16:52:48 -0400 Subject: pscsi: fix REPORT LUNS handling We need to assign spc_emulate_report_luns to the execute_cmd callback and not execute it directly. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index c3bcc17..dd6ac7c 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1001,7 +1001,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) */ switch (cdb[0]) { case REPORT_LUNS: - return spc_emulate_report_luns(cmd); + cmd->execute_cmd = spc_emulate_report_luns; + return 0; case READ_6: case READ_10: case READ_12: -- cgit v0.10.2 From 019c4ca621488739b1bfb7597a14ac7f0cbcc908 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:14 -0400 Subject: target: kill dev->dev_task_attr_type We can just key off ordered tag emulation of the transport_type field. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index e45a709..6a27e7f 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1412,11 +1412,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) - dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH; - else - dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED; - return dev; } diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 1f1ddb8..8ca6263 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1054,8 +1054,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * Do implict HEAD_OF_QUEUE processing for INQUIRY. * See spc4r17 section 5.3 */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - cmd->sam_task_attr = MSG_HEAD_TAG; + cmd->sam_task_attr = MSG_HEAD_TAG; cmd->execute_cmd = spc_emulate_inquiry; break; case SECURITY_PROTOCOL_IN: @@ -1083,8 +1082,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS * See spc4r17 section 5.3 */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - cmd->sam_task_attr = MSG_HEAD_TAG; + cmd->sam_task_attr = MSG_HEAD_TAG; break; case TEST_UNIT_READY: cmd->execute_cmd = spc_emulate_testunitready; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c80d884..757e377 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1068,11 +1068,13 @@ EXPORT_SYMBOL(transport_init_se_cmd); static int transport_check_alloc_task_attr(struct se_cmd *cmd) { + struct se_device *dev = cmd->se_dev; + /* * Check if SAM Task Attribute emulation is enabled for this * struct se_device storage object */ - if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; if (cmd->sam_task_attr == MSG_ACA_TAG) { @@ -1084,11 +1086,11 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) * Used to determine when ORDERED commands should go from * Dormant to Active status. */ - cmd->se_ordered_id = atomic_inc_return(&cmd->se_dev->dev_ordered_id); + cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id); smp_mb__after_atomic_inc(); pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n", cmd->se_ordered_id, cmd->sam_task_attr, - cmd->se_dev->transport->name); + dev->transport->name); return 0; } @@ -1534,8 +1536,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) /* * For SAM Task Attribute emulation for failed struct se_cmd */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - transport_complete_task_attr(cmd); + transport_complete_task_attr(cmd); switch (cmd->scsi_sense_reason) { case TCM_NON_EXISTENT_LUN: @@ -1619,49 +1620,12 @@ static void __target_execute_cmd(struct se_cmd *cmd) } } -void target_execute_cmd(struct se_cmd *cmd) +static bool target_handle_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - /* - * If the received CDB has aleady been aborted stop processing it here. - */ - if (transport_check_aborted_status(cmd, 1)) - return; - - /* - * Determine if IOCTL context caller in requesting the stopping of this - * command for LUN shutdown purposes. - */ - spin_lock_irq(&cmd->t_state_lock); - if (cmd->transport_state & CMD_T_LUN_STOP) { - pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n", - __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd)); - - cmd->transport_state &= ~CMD_T_ACTIVE; - spin_unlock_irq(&cmd->t_state_lock); - complete(&cmd->transport_lun_stop_comp); - return; - } - /* - * Determine if frontend context caller is requesting the stopping of - * this command for frontend exceptions. - */ - if (cmd->transport_state & CMD_T_STOP) { - pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", - __func__, __LINE__, - cmd->se_tfo->get_task_tag(cmd)); - - spin_unlock_irq(&cmd->t_state_lock); - complete(&cmd->t_transport_stop_comp); - return; - } - - cmd->t_state = TRANSPORT_PROCESSING; - spin_unlock_irq(&cmd->t_state_lock); - - if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) - goto execute; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return false; /* * Check for the existence of HEAD_OF_QUEUE, and if true return 1 @@ -1672,7 +1636,7 @@ void target_execute_cmd(struct se_cmd *cmd) pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, " "se_ordered_id: %u\n", cmd->t_task_cdb[0], cmd->se_ordered_id); - goto execute; + return false; case MSG_ORDERED_TAG: atomic_inc(&dev->dev_ordered_sync); smp_mb__after_atomic_inc(); @@ -1686,7 +1650,7 @@ void target_execute_cmd(struct se_cmd *cmd) * exist that need to be completed first. */ if (!atomic_read(&dev->simple_cmds)) - goto execute; + return false; break; default: /* @@ -1697,23 +1661,61 @@ void target_execute_cmd(struct se_cmd *cmd) break; } - if (atomic_read(&dev->dev_ordered_sync) != 0) { - spin_lock(&dev->delayed_cmd_lock); - list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); - spin_unlock(&dev->delayed_cmd_lock); + if (atomic_read(&dev->dev_ordered_sync) == 0) + return false; - pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" - " delayed CMD list, se_ordered_id: %u\n", - cmd->t_task_cdb[0], cmd->sam_task_attr, - cmd->se_ordered_id); + spin_lock(&dev->delayed_cmd_lock); + list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); + spin_unlock(&dev->delayed_cmd_lock); + + pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" + " delayed CMD list, se_ordered_id: %u\n", + cmd->t_task_cdb[0], cmd->sam_task_attr, + cmd->se_ordered_id); + return true; +} + +void target_execute_cmd(struct se_cmd *cmd) +{ + /* + * If the received CDB has aleady been aborted stop processing it here. + */ + if (transport_check_aborted_status(cmd, 1)) return; - } -execute: /* - * Otherwise, no ORDERED task attributes exist.. + * Determine if IOCTL context caller in requesting the stopping of this + * command for LUN shutdown purposes. */ - __target_execute_cmd(cmd); + spin_lock_irq(&cmd->t_state_lock); + if (cmd->transport_state & CMD_T_LUN_STOP) { + pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n", + __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd)); + + cmd->transport_state &= ~CMD_T_ACTIVE; + spin_unlock_irq(&cmd->t_state_lock); + complete(&cmd->transport_lun_stop_comp); + return; + } + /* + * Determine if frontend context caller is requesting the stopping of + * this command for frontend exceptions. + */ + if (cmd->transport_state & CMD_T_STOP) { + pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", + __func__, __LINE__, + cmd->se_tfo->get_task_tag(cmd)); + + spin_unlock_irq(&cmd->t_state_lock); + complete(&cmd->t_transport_stop_comp); + return; + } + + cmd->t_state = TRANSPORT_PROCESSING; + spin_unlock_irq(&cmd->t_state_lock); + + if (!target_handle_task_attr(cmd)) + __target_execute_cmd(cmd); } EXPORT_SYMBOL(target_execute_cmd); @@ -1752,6 +1754,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return; + if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { atomic_dec(&dev->simple_cmds); smp_mb__after_atomic_dec(); @@ -1780,8 +1785,7 @@ static void transport_complete_qf(struct se_cmd *cmd) { int ret = 0; - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - transport_complete_task_attr(cmd); + transport_complete_task_attr(cmd); if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { ret = cmd->se_tfo->queue_status(cmd); @@ -1839,8 +1843,8 @@ static void target_complete_ok_work(struct work_struct *work) * delayed execution list after a HEAD_OF_QUEUE or ORDERED Task * Attribute. */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - transport_complete_task_attr(cmd); + transport_complete_task_attr(cmd); + /* * Check to schedule QUEUE_FULL work, or execute an existing * cmd->transport_qf_callback() diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index f6355fc..15af130 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -233,16 +233,6 @@ typedef enum { } t10_alua_index_t; /* - * Used by TCM Core internally to signal if SAM Task Attribute emulation - * is enabled or disabled, or running in with TCM/pSCSI passthrough mode - */ -typedef enum { - SAM_TASK_ATTR_PASSTHROUGH, - SAM_TASK_ATTR_UNTAGGED, - SAM_TASK_ATTR_EMULATED -} t10_task_attr_index_t; - -/* * Used for target SCSI statistics */ typedef enum { @@ -686,7 +676,6 @@ struct se_device { u32 queue_depth; /* Used for SPC-2 reservations enforce of ISIDs */ u64 dev_res_bin_isid; - t10_task_attr_index_t dev_task_attr_type; /* Pointer to transport specific device structure */ u32 dev_index; u64 creation_time; -- cgit v0.10.2 From d977f4377fbc396b888e12fdb3b13118b09ca7db Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:15 -0400 Subject: target: simplify reservations code We do not support host-level reservations for the pscsi backend, and all virtual backends are newere than SCSI-2, so just make the combined SPC-3 + SCSI-2 support the only supported variant and kill the switches for the different implementations, given that this code handles the no-op version just fine. (hch: Update DRF_SPC2_RESERVATIONS lock usage) Signed-off-by: Christoph Hellwig diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 7272016..3d5570da 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -970,13 +970,8 @@ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ __CONFIGFS_EATTR_RO(_name, \ target_core_dev_pr_show_attr_##_name); -/* - * res_holder - */ -static ssize_t target_core_dev_pr_show_spc3_res( - struct se_device *dev, - char *page, - ssize_t *len) +static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev, + char *page) { struct se_node_acl *se_nacl; struct t10_pr_registration *pr_reg; @@ -985,68 +980,52 @@ static ssize_t target_core_dev_pr_show_spc3_res( memset(i_buf, 0, PR_REG_ISID_ID_LEN); - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!pr_reg) { - *len += sprintf(page + *len, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return *len; - } + if (!pr_reg) + return sprintf(page, "No SPC-3 Reservation holder\n"); + se_nacl = pr_reg->pr_reg_nacl; prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], PR_REG_ISID_ID_LEN); - *len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n", + return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n", se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); - spin_unlock(&dev->dev_reservation_lock); - - return *len; } -static ssize_t target_core_dev_pr_show_spc2_res( - struct se_device *dev, - char *page, - ssize_t *len) +static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev, + char *page) { struct se_node_acl *se_nacl; + ssize_t len; - spin_lock(&dev->dev_reservation_lock); se_nacl = dev->dev_reserved_node_acl; - if (!se_nacl) { - *len += sprintf(page + *len, "No SPC-2 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return *len; + if (se_nacl) { + len = sprintf(page, + "SPC-2 Reservation: %s Initiator: %s\n", + se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), + se_nacl->initiatorname); + } else { + len = sprintf(page, "No SPC-2 Reservation holder\n"); } - *len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n", - se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), - se_nacl->initiatorname); - spin_unlock(&dev->dev_reservation_lock); - - return *len; + return len; } static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev, char *page) { - ssize_t len = 0; + int ret; - switch (dev->t10_pr.res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - target_core_dev_pr_show_spc3_res(dev, page, &len); - break; - case SPC2_RESERVATIONS: - target_core_dev_pr_show_spc2_res(dev, page, &len); - break; - case SPC_PASSTHROUGH: - len += sprintf(page+len, "Passthrough\n"); - break; - default: - len += sprintf(page+len, "Unknown\n"); - break; - } + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return sprintf(page, "Passthrough\n"); - return len; + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + ret = target_core_dev_pr_show_spc2_res(dev, page); + else + ret = target_core_dev_pr_show_spc3_res(dev, page); + spin_unlock(&dev->dev_reservation_lock); + return ret; } SE_DEV_PR_ATTR_RO(res_holder); @@ -1054,31 +1033,20 @@ SE_DEV_PR_ATTR_RO(res_holder); static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( struct se_device *dev, char *page) { - struct t10_pr_registration *pr_reg; ssize_t len = 0; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); - pr_reg = dev->dev_pr_res_holder; - if (!pr_reg) { + if (!dev->dev_pr_res_holder) { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; - } - /* - * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3 - * Basic PERSISTENT RESERVER OUT parameter list, page 290 - */ - if (pr_reg->pr_reg_all_tg_pt) + } else if (dev->dev_pr_res_holder->pr_reg_all_tg_pt) { len = sprintf(page, "SPC-3 Reservation: All Target" " Ports registration\n"); - else + } else { len = sprintf(page, "SPC-3 Reservation: Single" " Target Port registration\n"); - spin_unlock(&dev->dev_reservation_lock); + } + spin_unlock(&dev->dev_reservation_lock); return len; } @@ -1087,9 +1055,6 @@ SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); static ssize_t target_core_dev_pr_show_attr_res_pr_generation( struct se_device *dev, char *page) { - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return 0; - return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation); } @@ -1108,16 +1073,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( struct target_core_fabric_ops *tfo; ssize_t len = 0; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; if (!pr_reg) { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; + goto out_unlock; } + se_nacl = pr_reg->pr_reg_nacl; se_tpg = se_nacl->se_tpg; lun = pr_reg->pr_reg_tg_pt_lun; @@ -1131,8 +1093,9 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), tfo->get_fabric_name(), lun->unpacked_lun); - spin_unlock(&dev->dev_reservation_lock); +out_unlock: + spin_unlock(&dev->dev_reservation_lock); return len; } @@ -1148,9 +1111,6 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( ssize_t len = 0; int reg_count = 0, prf_isid; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - len += sprintf(page+len, "SPC-3 PR Registrations:\n"); spin_lock(&dev->t10_pr.registration_lock); @@ -1190,20 +1150,16 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type( struct t10_pr_registration *pr_reg; ssize_t len = 0; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!pr_reg) { + if (pr_reg) { + len = sprintf(page, "SPC-3 Reservation Type: %s\n", + core_scsi3_pr_dump_type(pr_reg->pr_res_type)); + } else { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; } - len = sprintf(page, "SPC-3 Reservation Type: %s\n", - core_scsi3_pr_dump_type(pr_reg->pr_res_type)); - spin_unlock(&dev->dev_reservation_lock); + spin_unlock(&dev->dev_reservation_lock); return len; } @@ -1212,24 +1168,12 @@ SE_DEV_PR_ATTR_RO(res_pr_type); static ssize_t target_core_dev_pr_show_attr_res_type( struct se_device *dev, char *page) { - ssize_t len = 0; - - switch (dev->t10_pr.res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); - break; - case SPC2_RESERVATIONS: - len = sprintf(page, "SPC2_RESERVATIONS\n"); - break; - case SPC_PASSTHROUGH: - len = sprintf(page, "SPC_PASSTHROUGH\n"); - break; - default: - len = sprintf(page, "UNKNOWN\n"); - break; - } - - return len; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return sprintf(page, "SPC_PASSTHROUGH\n"); + else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + return sprintf(page, "SPC2_RESERVATIONS\n"); + else + return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); } SE_DEV_PR_ATTR_RO(res_type); @@ -1237,7 +1181,7 @@ SE_DEV_PR_ATTR_RO(res_type); static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( struct se_device *dev, char *page) { - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "APTPL Bit Status: %s\n", @@ -1252,7 +1196,7 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active); static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( struct se_device *dev, char *page) { - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "Ready to process PR APTPL metadata..\n"); @@ -1299,7 +1243,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( u16 port_rpti = 0, tpgt = 0; u8 type = 0, scope; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return 0; if (dev->export_count) { diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 6a27e7f..4ae1d39 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1398,7 +1398,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; - dev->dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; dev->dev_attrib.emulate_alua = DA_EMULATE_ALUA; dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; dev->dev_attrib.is_nonrot = DA_IS_NONROT; @@ -1447,8 +1446,6 @@ int target_configure_device(struct se_device *dev) dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); dev->creation_time = get_jiffies_64(); - core_setup_reservations(dev); - ret = core_setup_alua(dev); if (ret) goto out; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 2b28989..f561a08 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -68,49 +68,32 @@ int core_pr_dump_initiator_port( static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); -static int core_scsi2_reservation_seq_non_holder( - struct se_cmd *cmd, - unsigned char *cdb, - u32 pr_reg_type) +static int target_scsi2_reservation_check(struct se_cmd *cmd) { - switch (cdb[0]) { + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + + switch (cmd->t_task_cdb[0]) { case INQUIRY: case RELEASE: case RELEASE_10: return 0; default: - return 1; + break; } - return 1; -} - -static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type) -{ - struct se_device *dev = cmd->se_dev; - struct se_session *sess = cmd->se_sess; - int ret; - - if (!sess) + if (!dev->dev_reserved_node_acl || !sess) return 0; - spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_reserved_node_acl || !sess) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - if (dev->dev_reserved_node_acl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return -EINVAL; - } - if (!(dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID)) { - spin_unlock(&dev->dev_reservation_lock); - return 0; + if (dev->dev_reserved_node_acl != sess->se_node_acl) + return -EBUSY; + + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { + if (dev->dev_res_bin_isid != sess->sess_bin_isid) + return -EBUSY; } - ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL; - spin_unlock(&dev->dev_reservation_lock); - return ret; + return 0; } static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *, @@ -123,12 +106,8 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; struct t10_reservation *pr_tmpl = &dev->t10_pr; - int crh = (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS); int conflict = 0; - if (!crh) - return -EINVAL; - pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); if (pr_reg) { @@ -319,9 +298,9 @@ out: */ static int core_scsi3_pr_seq_non_holder( struct se_cmd *cmd, - unsigned char *cdb, u32 pr_reg_type) { + unsigned char *cdb = cmd->t_task_cdb; struct se_dev_entry *se_deve; struct se_session *se_sess = cmd->se_sess; int other_cdb = 0, ignore_reg; @@ -330,17 +309,11 @@ static int core_scsi3_pr_seq_non_holder( int we = 0; /* Write Exclusive */ int legacy = 0; /* Act like a legacy device and return * RESERVATION CONFLICT on some CDBs */ - /* - * A legacy SPC-2 reservation is being held. - */ - if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) - return core_scsi2_reservation_seq_non_holder(cmd, - cdb, pr_reg_type); se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; /* * Determine if the registration should be ignored due to - * non-matching ISIDs in core_scsi3_pr_reservation_check(). + * non-matching ISIDs in target_scsi3_pr_reservation_check(). */ ignore_reg = (pr_reg_type & 0x80000000); if (ignore_reg) @@ -563,6 +536,36 @@ static int core_scsi3_pr_seq_non_holder( return 1; /* Conflict by default */ } +static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + u32 pr_reg_type; + + if (!dev->dev_pr_res_holder) + return 0; + + pr_reg_type = dev->dev_pr_res_holder->pr_res_type; + cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; + if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) + goto check_nonholder; + + if (dev->dev_pr_res_holder->isid_present_at_reg) { + if (dev->dev_pr_res_holder->pr_reg_bin_isid != + sess->sess_bin_isid) { + pr_reg_type |= 0x80000000; + goto check_nonholder; + } + } + + return 0; + +check_nonholder: + if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) + return -EBUSY; + return 0; +} + static u32 core_scsi3_pr_generation(struct se_device *dev) { u32 prg; @@ -583,50 +586,6 @@ static u32 core_scsi3_pr_generation(struct se_device *dev) return prg; } -static int core_scsi3_pr_reservation_check( - struct se_cmd *cmd, - u32 *pr_reg_type) -{ - struct se_device *dev = cmd->se_dev; - struct se_session *sess = cmd->se_sess; - int ret; - - if (!sess) - return 0; - /* - * A legacy SPC-2 reservation is being held. - */ - if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) - return core_scsi2_reservation_check(cmd, pr_reg_type); - - spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_pr_res_holder) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - *pr_reg_type = dev->dev_pr_res_holder->pr_res_type; - cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; - if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return -EINVAL; - } - if (!dev->dev_pr_res_holder->isid_present_at_reg) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - ret = (dev->dev_pr_res_holder->pr_reg_bin_isid == - sess->sess_bin_isid) ? 0 : -EINVAL; - /* - * Use bit in *pr_reg_type to notify ISID mismatch in - * core_scsi3_pr_seq_non_holder(). - */ - if (ret != 0) - *pr_reg_type |= 0x80000000; - spin_unlock(&dev->dev_reservation_lock); - - return ret; -} - static struct t10_pr_registration *__core_scsi3_do_alloc_registration( struct se_device *dev, struct se_node_acl *nacl, @@ -998,7 +957,7 @@ int core_scsi3_check_aptpl_registration( struct se_node_acl *nacl = lun_acl->se_lun_nacl; struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return 0; return __core_scsi3_check_aptpl_registration(dev, tpg, lun, @@ -4343,49 +4302,24 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) return ret; } -static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) +int target_check_reservation(struct se_cmd *cmd) { - return 0; -} + struct se_device *dev = cmd->se_dev; + int ret; -static int core_pt_seq_non_holder( - struct se_cmd *cmd, - unsigned char *cdb, - u32 pr_reg_type) -{ - return 0; -} + if (!cmd->se_sess) + return 0; + if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) + return 0; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; -void core_setup_reservations(struct se_device *dev) -{ - struct t10_reservation *rest = &dev->t10_pr; + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + ret = target_scsi2_reservation_check(cmd); + else + ret = target_scsi3_pr_reservation_check(cmd); + spin_unlock(&dev->dev_reservation_lock); - /* - * If this device is from Target_Core_Mod/pSCSI, use the reservations - * 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 to emulate reservations themselves. - */ - if ((dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) || - (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV && - !dev->dev_attrib.emulate_reservations)) { - rest->res_type = SPC_PASSTHROUGH; - rest->pr_ops.t10_reservation_check = &core_pt_reservation_check; - rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder; - pr_debug("%s: Using SPC_PASSTHROUGH, no reservation" - " emulation\n", dev->transport->name); - } else if (dev->transport->get_device_rev(dev) >= SCSI_3) { - rest->res_type = SPC3_PERSISTENT_RESERVATIONS; - rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check; - rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder; - pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS" - " emulation\n", dev->transport->name); - } else { - rest->res_type = SPC2_RESERVATIONS; - rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check; - rest->pr_ops.t10_seq_non_holder = - &core_scsi2_reservation_seq_non_holder; - pr_debug("%s: Using SPC2_RESERVATIONS emulation\n", - dev->transport->name); - } + return ret; } diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index 7845143..7616f26 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -63,6 +63,6 @@ extern unsigned char *core_scsi3_pr_dump_type(int); extern int target_scsi3_emulate_pr_in(struct se_cmd *); extern int target_scsi3_emulate_pr_out(struct se_cmd *); -extern void core_setup_reservations(struct se_device *); +extern int target_check_reservation(struct se_cmd *cmd); #endif /* TARGET_CORE_PR_H */ diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 8ca6263..862e434 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1003,14 +1003,12 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) *size = (cdb[7] << 8) + cdb[8]; break; case PERSISTENT_RESERVE_IN: - if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) - cmd->execute_cmd = target_scsi3_emulate_pr_in; *size = (cdb[7] << 8) + cdb[8]; + cmd->execute_cmd = target_scsi3_emulate_pr_in; break; case PERSISTENT_RESERVE_OUT: - if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) - cmd->execute_cmd = target_scsi3_emulate_pr_out; *size = (cdb[7] << 8) + cdb[8]; + cmd->execute_cmd = target_scsi3_emulate_pr_out; break; case RELEASE: case RELEASE_10: @@ -1019,8 +1017,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) else *size = cmd->data_length; - if (dev->t10_pr.res_type != SPC_PASSTHROUGH) - cmd->execute_cmd = target_scsi2_reservation_release; + cmd->execute_cmd = target_scsi2_reservation_release; break; case RESERVE: case RESERVE_10: @@ -1033,15 +1030,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) else *size = cmd->data_length; - /* - * Setup the legacy emulated handler for SPC-2 and - * >= SPC-3 compatible reservation handling (CRH=1) - * Otherwise, we assume the underlying SCSI logic is - * is running in SPC_PASSTHROUGH, and wants reservations - * emulation disabled. - */ - if (dev->t10_pr.res_type != SPC_PASSTHROUGH) - cmd->execute_cmd = target_scsi2_reservation_reserve; + cmd->execute_cmd = target_scsi2_reservation_reserve; break; case REQUEST_SENSE: *size = cdb[4]; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 757e377..e996bdf 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1103,7 +1103,6 @@ int target_setup_cmd_from_cdb( unsigned char *cdb) { struct se_device *dev = cmd->se_dev; - u32 pr_reg_type = 0; u8 alua_ascq = 0; unsigned long flags; int ret; @@ -1180,20 +1179,13 @@ int target_setup_cmd_from_cdb( /* * Check status for SPC-3 Persistent Reservations */ - if (dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) { - if (dev->t10_pr.pr_ops.t10_seq_non_holder( - cmd, cdb, pr_reg_type) != 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EBUSY; - } - /* - * This means the CDB is allowed for the SCSI Initiator port - * when said port is *NOT* holding the legacy SPC-2 or - * SPC-3 Persistent Reservation. - */ + ret = target_check_reservation(cmd); + if (ret) { + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; + cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return ret; } ret = dev->transport->parse_cdb(cmd); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 15af130..892a93d 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -93,8 +93,6 @@ */ #define DA_EMULATE_TPWS 0 /* No Emulation for PSCSI by default */ -#define DA_EMULATE_RESERVATIONS 0 -/* No Emulation for PSCSI by default */ #define DA_EMULATE_ALUA 0 /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ #define DA_ENFORCE_PR_ISIDS 1 @@ -333,18 +331,6 @@ struct t10_wwn { struct list_head t10_vpd_list; }; - -/* - * Used by TCM Core internally to signal if >= SPC-3 persistent reservations - * emulation is enabled or disabled, or running in with TCM/pSCSI passthrough - * mode - */ -typedef enum { - SPC_PASSTHROUGH, - SPC2_RESERVATIONS, - SPC3_PERSISTENT_RESERVATIONS -} t10_reservations_index_t; - struct t10_pr_registration { /* Used for fabrics that contain WWN+ISID */ #define PR_REG_ISID_LEN 16 @@ -386,18 +372,6 @@ struct t10_pr_registration { struct list_head pr_reg_atp_mem_list; }; -/* - * This set of function pointer ops is set based upon SPC3_PERSISTENT_RESERVATIONS, - * SPC2_RESERVATIONS or SPC_PASSTHROUGH in drivers/target/target_core_pr.c: - * core_setup_reservations() - */ -struct t10_reservation_ops { - int (*t10_reservation_check)(struct se_cmd *, u32 *); - int (*t10_seq_non_holder)(struct se_cmd *, unsigned char *, u32); - int (*t10_pr_register)(struct se_cmd *); - int (*t10_pr_clear)(struct se_cmd *); -}; - struct t10_reservation { /* Reservation effects all target ports */ int pr_all_tg_pt; @@ -408,7 +382,6 @@ struct t10_reservation { #define PR_APTPL_BUF_LEN 8192 u32 pr_aptpl_buf_len; u32 pr_generation; - t10_reservations_index_t res_type; spinlock_t registration_lock; spinlock_t aptpl_reg_lock; /* @@ -424,7 +397,6 @@ struct t10_reservation { struct se_node_acl *pr_res_holder; struct list_head registration_list; struct list_head aptpl_reg_list; - struct t10_reservation_ops pr_ops; }; struct se_tmr_req { @@ -633,7 +605,6 @@ struct se_dev_attrib { int emulate_tas; int emulate_tpu; int emulate_tpws; - int emulate_reservations; int emulate_alua; int enforce_pr_isids; int is_nonrot; -- cgit v0.10.2 From c87fbd5656f263f0fc1c37d20f402797c068232e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:16 -0400 Subject: target: simplify alua support We always support ALUA for virtual backends, and never for physical ones. Simplify the code to just deal with these two cases and remove the superflous abstractions. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 15c127b..b3302a9 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -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; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index 5019157..a2af8aa 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -132,5 +132,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, const char *, size_t); extern int core_setup_alua(struct se_device *); +extern int target_alua_state_check(struct se_cmd *cmd); #endif /* TARGET_CORE_ALUA_H */ diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 3d5570da..7b473b6 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -1615,15 +1615,9 @@ static ssize_t target_core_show_alua_lu_gp(void *p, char *page) struct t10_alua_lu_gp_member *lu_gp_mem; ssize_t len = 0; - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) - return len; - lu_gp_mem = dev->dev_alua_lu_gp_mem; - if (!lu_gp_mem) { - pr_err("NULL struct se_device->dev_alua_lu_gp_mem" - " pointer\n"); - return -EINVAL; - } + if (!lu_gp_mem) + return 0; spin_lock(&lu_gp_mem->lu_gp_mem_lock); lu_gp = lu_gp_mem->lu_gp; @@ -1649,12 +1643,10 @@ static ssize_t target_core_store_alua_lu_gp( unsigned char buf[LU_GROUP_NAME_BUF]; int move = 0; - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { - pr_warn("SPC3_ALUA_EMULATED not enabled for %s/%s\n", - config_item_name(&hba->hba_group.cg_item), - config_item_name(&dev->dev_group.cg_item)); - return -EINVAL; - } + lu_gp_mem = dev->dev_alua_lu_gp_mem; + if (!lu_gp_mem) + return 0; + if (count > LU_GROUP_NAME_BUF) { pr_err("ALUA LU Group Alias too large!\n"); return -EINVAL; @@ -1675,14 +1667,6 @@ static ssize_t target_core_store_alua_lu_gp( if (!lu_gp_new) return -ENODEV; } - lu_gp_mem = dev->dev_alua_lu_gp_mem; - if (!lu_gp_mem) { - if (lu_gp_new) - core_alua_put_lu_gp_from_name(lu_gp_new); - pr_err("NULL struct se_device->dev_alua_lu_gp_mem" - " pointer\n"); - return -EINVAL; - } spin_lock(&lu_gp_mem->lu_gp_mem_lock); lu_gp = lu_gp_mem->lu_gp; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4ae1d39..3c3a301 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -556,7 +556,8 @@ static void core_export_port( list_add_tail(&port->sep_list, &dev->dev_sep_list); spin_unlock(&dev->se_port_lock); - if (dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && + !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port); if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) { pr_err("Unable to allocate t10_alua_tg_pt" @@ -1398,7 +1399,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; - dev->dev_attrib.emulate_alua = DA_EMULATE_ALUA; dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; dev->dev_attrib.is_nonrot = DA_IS_NONROT; dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 862e434..7ecac45 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -95,8 +95,7 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) /* * Enable SCCS and TPGS fields for Emulated ALUA */ - if (dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) - spc_fill_alua_data(lun->lun_sep, buf); + spc_fill_alua_data(lun->lun_sep, buf); buf[7] = 0x2; /* CmdQue=1 */ @@ -294,9 +293,6 @@ check_t10_vend_desc: * Get the PROTOCOL IDENTIFIER as defined by spc4r17 * section 7.5.1 Table 362 */ - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) - goto check_scsi_name; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; if (!tg_pt_gp_mem) goto check_lu_gp; @@ -1083,8 +1079,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * MAINTENANCE_IN from SCC-2 * Check for emulated MI_REPORT_TARGET_PGS */ - if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS && - dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS) { cmd->execute_cmd = target_emulate_report_target_port_groups; } @@ -1102,8 +1097,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * MAINTENANCE_OUT from SCC-2 * Check for emulated MO_SET_TARGET_PGS. */ - if (cdb[1] == MO_SET_TARGET_PGS && - dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if (cdb[1] == MO_SET_TARGET_PGS) { cmd->execute_cmd = target_emulate_set_target_port_groups; } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e996bdf..c4c931b 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -70,7 +70,6 @@ static void transport_handle_queue_full(struct se_cmd *cmd, static int transport_generic_get_mem(struct se_cmd *cmd); static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool); static void transport_put_cmd(struct se_cmd *cmd); -static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq); static void target_complete_ok_work(struct work_struct *work); int init_se_kmem_caches(void) @@ -1103,7 +1102,6 @@ int target_setup_cmd_from_cdb( unsigned char *cdb) { struct se_device *dev = cmd->se_dev; - u8 alua_ascq = 0; unsigned long flags; int ret; @@ -1153,26 +1151,13 @@ int target_setup_cmd_from_cdb( return -EINVAL; } - ret = dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); - 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.. - */ - if (ret > 0) { - 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); - - transport_set_sense_codes(cmd, 0x04, alua_ascq); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; - return -EINVAL; - } + ret = target_alua_state_check(cmd); + if (ret) { cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + if (ret > 0) + cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; + else + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return -EINVAL; } @@ -2640,17 +2625,6 @@ static int transport_get_sense_codes( return 0; } -static int transport_set_sense_codes( - struct se_cmd *cmd, - u8 asc, - u8 ascq) -{ - cmd->scsi_asc = asc; - cmd->scsi_ascq = ascq; - - return 0; -} - int transport_send_check_condition_and_sense( struct se_cmd *cmd, u8 reason, diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 892a93d..11b0a68 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -221,16 +221,6 @@ enum tcm_tmrsp_table { }; /* - * Used by TCM Core internally to signal if ALUA emulation is enabled or - * disabled, or running in with TCM/pSCSI passthrough mode - */ -typedef enum { - SPC_ALUA_PASSTHROUGH, - SPC2_ALUA_DISABLED, - SPC3_ALUA_EMULATED -} t10_alua_index_t; - -/* * Used for target SCSI statistics */ typedef enum { @@ -243,7 +233,6 @@ typedef enum { struct se_cmd; struct t10_alua { - t10_alua_index_t alua_type; /* ALUA Target Port Group ID */ u16 alua_tg_pt_gps_counter; u32 alua_tg_pt_gps_count; @@ -253,7 +242,6 @@ struct t10_alua { struct t10_alua_tg_pt_gp *default_tg_pt_gp; /* Used for default ALUA Target Port Group ConfigFS group */ struct config_group alua_tg_pt_gps_group; - int (*alua_state_check)(struct se_cmd *, unsigned char *, u8 *); struct list_head tg_pt_gps_list; }; @@ -605,7 +593,6 @@ struct se_dev_attrib { int emulate_tas; int emulate_tpu; int emulate_tpws; - int emulate_alua; int enforce_pr_isids; int is_nonrot; int emulate_rest_reord; -- cgit v0.10.2 From 48c2567d1a10b5a2cab72b37775b886b08f88726 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:17 -0400 Subject: target: remove ->get_device_rev Now that the reservations and ALUA code have been cleaned up there is no need for the get_device_rev method, as we only need the standards revision in the inquiry data, where we can hardcode it. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 3c3a301..066e815 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1348,8 +1348,6 @@ static void scsi_dump_inquiry(struct se_device *dev) device_type = dev->transport->get_device_type(dev); pr_debug(" Type: %s ", scsi_device_type(device_type)); - pr_debug(" ANSI SCSI revision: %02x\n", - dev->transport->get_device_rev(dev)); } struct se_device *target_alloc_device(struct se_hba *hba, const char *name) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 2a3e2bb..342a6a6 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -534,7 +534,6 @@ static struct se_subsystem_api fileio_template = { .parse_cdb = fd_parse_cdb, .set_configfs_dev_params = fd_set_configfs_dev_params, .show_configfs_dev_params = fd_show_configfs_dev_params, - .get_device_rev = sbc_get_device_rev, .get_device_type = sbc_get_device_type, .get_blocks = fd_get_blocks, }; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 701877f..17fc01d 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -725,7 +725,6 @@ static struct se_subsystem_api iblock_template = { .parse_cdb = iblock_parse_cdb, .set_configfs_dev_params = iblock_set_configfs_dev_params, .show_configfs_dev_params = iblock_show_configfs_dev_params, - .get_device_rev = sbc_get_device_rev, .get_device_type = sbc_get_device_type, .get_blocks = iblock_get_blocks, }; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index dd6ac7c..aa3e80a 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1106,18 +1106,6 @@ fail: return -ENOMEM; } -/* pscsi_get_device_rev(): - * - * - */ -static u32 pscsi_get_device_rev(struct se_device *dev) -{ - struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); - struct scsi_device *sd = pdv->pdv_sd; - - return (sd->scsi_level - 1) ? sd->scsi_level - 1 : 1; -} - /* pscsi_get_device_type(): * * @@ -1187,7 +1175,6 @@ static struct se_subsystem_api pscsi_template = { .parse_cdb = pscsi_parse_cdb, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, - .get_device_rev = pscsi_get_device_rev, .get_device_type = pscsi_get_device_type, .get_blocks = pscsi_get_blocks, }; diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 6348b66..92b1307 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -449,7 +449,6 @@ static struct se_subsystem_api rd_mcp_template = { .parse_cdb = rd_parse_cdb, .set_configfs_dev_params = rd_set_configfs_dev_params, .show_configfs_dev_params = rd_show_configfs_dev_params, - .get_device_rev = sbc_get_device_rev, .get_device_type = sbc_get_device_type, .get_blocks = rd_get_blocks, }; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 0168695..a4eb9c5 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -604,12 +604,6 @@ out_invalid_cdb_field: } EXPORT_SYMBOL(sbc_parse_cdb); -u32 sbc_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} -EXPORT_SYMBOL(sbc_get_device_rev); - u32 sbc_get_device_type(struct se_device *dev) { return TYPE_DISK; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 7ecac45..71d440f 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -78,7 +78,7 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) if (dev->transport->get_device_type(dev) == TYPE_TAPE) buf[1] = 0x80; - buf[2] = dev->transport->get_device_rev(dev); + buf[2] = 0x05; /* SPC-3 */ /* * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2 diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index b7f3936..e57f738 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -32,7 +32,6 @@ struct se_subsystem_api { unsigned char *); int (*parse_cdb)(struct se_cmd *cmd); - u32 (*get_device_rev)(struct se_device *); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); unsigned char *(*get_sense_buffer)(struct se_cmd *); -- cgit v0.10.2 From 1f981de55a46777ca0da93af5faf7d3f6e7e7000 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:47 -0700 Subject: iscsi-target: Use list_first_entry() where appropriate Instead of using the obfuscated pattern of list_for_each_entry(var, list, ...) break; to set var to the first entry of a list, use the straightforward var = list_first_entry(list, ...); Reported-by: Joern Engel Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c index 9d881a0..8128952 100644 --- a/drivers/target/iscsi/iscsi_target_tq.c +++ b/drivers/target/iscsi/iscsi_target_tq.c @@ -66,8 +66,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) return NULL; } - list_for_each_entry(ts, &inactive_ts_list, ts_list) - break; + ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list); list_del(&ts->ts_list); iscsit_global->inactive_ts--; diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 1a91195..87e153b 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -500,8 +500,8 @@ struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *c spin_unlock_bh(&conn->immed_queue_lock); return NULL; } - list_for_each_entry(qr, &conn->immed_queue_list, qr_list) - break; + qr = list_first_entry(&conn->immed_queue_list, + struct iscsi_queue_req, qr_list); list_del(&qr->qr_list); if (qr->cmd) @@ -575,8 +575,8 @@ struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *co return NULL; } - list_for_each_entry(qr, &conn->response_queue_list, qr_list) - break; + qr = list_first_entry(&conn->response_queue_list, + struct iscsi_queue_req, qr_list); list_del(&qr->qr_list); if (qr->cmd) -- cgit v0.10.2 From d4b2b867193c157f0ac8c10137e287a90ed4e5d5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:48 -0700 Subject: target: Refactor MODE SENSE emulation Convert spc_emulate_modesense() to use a table of mode pages, rather than a switch statement. This makes it possible to add more pages sanely -- in particular we no longer need to make sure we keep the 0x3f (return all mode pages) case in sync. While we're touching this code, make our MODE SENSE emulation a bit better in a couple of ways: - When the initiator passes PC == 1 asking for changeable values, return all 0s to show we don't support setting anything. - Return a block descriptor for disk devices. (nab: fix up device attribute references to use dev->dev_attrib in for-next code) Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 71d440f..8ccfe00 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -639,18 +639,28 @@ out: return ret; } -static int spc_modesense_rwrecovery(unsigned char *p) +static int spc_modesense_rwrecovery(struct se_device *dev, u8 pc, u8 *p) { p[0] = 0x01; p[1] = 0x0a; + /* No changeable values for now */ + if (pc == 1) + goto out; + +out: return 12; } -static int spc_modesense_control(struct se_device *dev, unsigned char *p) +static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p) { p[0] = 0x0a; p[1] = 0x0a; + + /* No changeable values for now */ + if (pc == 1) + goto out; + p[2] = 2; /* * From spc4r23, 7.4.7 Control mode page @@ -729,20 +739,37 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p) p[9] = 0xff; p[11] = 30; +out: return 12; } -static int spc_modesense_caching(struct se_device *dev, unsigned char *p) +static int spc_modesense_caching(struct se_device *dev, u8 pc, u8 *p) { p[0] = 0x08; p[1] = 0x12; + + /* No changeable values for now */ + if (pc == 1) + goto out; + if (dev->dev_attrib.emulate_write_cache > 0) p[2] = 0x04; /* Write Cache Enable */ p[12] = 0x20; /* Disabled Read Ahead */ +out: return 20; } +static struct { + uint8_t page; + uint8_t subpage; + int (*emulate)(struct se_device *, u8, unsigned char *); +} modesense_handlers[] = { + { .page = 0x01, .subpage = 0x00, .emulate = spc_modesense_rwrecovery }, + { .page = 0x08, .subpage = 0x00, .emulate = spc_modesense_caching }, + { .page = 0x0a, .subpage = 0x00, .emulate = spc_modesense_control }, +}; + static void spc_modesense_write_protect(unsigned char *buf, int type) { /* @@ -769,77 +796,167 @@ static void spc_modesense_dpofua(unsigned char *buf, int type) } } +static int spc_modesense_blockdesc(unsigned char *buf, u64 blocks, u32 block_size) +{ + *buf++ = 8; + put_unaligned_be32(min(blocks, 0xffffffffull), buf); + buf += 4; + put_unaligned_be32(block_size, buf); + return 9; +} + +static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 block_size) +{ + if (blocks <= 0xffffffff) + return spc_modesense_blockdesc(buf + 3, blocks, block_size) + 3; + + *buf++ = 1; /* LONGLBA */ + buf += 2; + *buf++ = 16; + put_unaligned_be64(blocks, buf); + buf += 12; + put_unaligned_be32(block_size, buf); + + return 17; +} + static int spc_emulate_modesense(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; char *cdb = cmd->t_task_cdb; - unsigned char *rbuf; + unsigned char *buf, *map_buf; int type = dev->transport->get_device_type(dev); int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); - u32 offset = ten ? 8 : 4; + bool dbd = !!(cdb[1] & 0x08); + bool llba = ten ? !!(cdb[1] & 0x10) : false; + u8 pc = cdb[2] >> 6; + u8 page = cdb[2] & 0x3f; + u8 subpage = cdb[3]; int length = 0; - unsigned char buf[SE_MODE_PAGE_BUF]; + int ret; + int i; - memset(buf, 0, SE_MODE_PAGE_BUF); + map_buf = transport_kmap_data_sg(cmd); - switch (cdb[2] & 0x3f) { - case 0x01: - length = spc_modesense_rwrecovery(&buf[offset]); - break; - case 0x08: - length = spc_modesense_caching(dev, &buf[offset]); - break; - case 0x0a: - length = spc_modesense_control(dev, &buf[offset]); - break; - case 0x3f: - length = spc_modesense_rwrecovery(&buf[offset]); - length += spc_modesense_caching(dev, &buf[offset+length]); - length += spc_modesense_control(dev, &buf[offset+length]); - break; - default: - pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", - cdb[2] & 0x3f, cdb[3]); - cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; - return -EINVAL; + /* + * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we + * know we actually allocated a full page. Otherwise, if the + * data buffer is too small, allocate a temporary buffer so we + * don't have to worry about overruns in all our INQUIRY + * emulation handling. + */ + if (cmd->data_length < SE_MODE_PAGE_BUF && + (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { + buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); + if (!buf) { + transport_kunmap_data_sg(cmd); + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; + } + } else { + buf = map_buf; } - offset += length; - - if (ten) { - offset -= 2; - buf[0] = (offset >> 8) & 0xff; - buf[1] = offset & 0xff; - offset += 2; - - if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || - (cmd->se_deve && - (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) - spc_modesense_write_protect(&buf[3], type); - - if ((dev->dev_attrib.emulate_write_cache > 0) && - (dev->dev_attrib.emulate_fua_write > 0)) - spc_modesense_dpofua(&buf[3], type); + + length = ten ? 2 : 1; + + /* DEVICE-SPECIFIC PARAMETER */ + if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || + (cmd->se_deve && + (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) + spc_modesense_write_protect(&buf[length], type); + + if ((dev->dev_attrib.emulate_write_cache > 0) && + (dev->dev_attrib.emulate_fua_write > 0)) + spc_modesense_dpofua(&buf[length], type); + + ++length; + + /* BLOCK DESCRIPTOR */ + + /* + * For now we only include a block descriptor for disk (SBC) + * devices; other command sets use a slightly different format. + */ + if (!dbd && type == TYPE_DISK) { + u64 blocks = dev->transport->get_blocks(dev); + u32 block_size = dev->dev_attrib.block_size; + + if (ten) { + if (llba) { + length += spc_modesense_long_blockdesc(&buf[length], + blocks, block_size); + } else { + length += 3; + length += spc_modesense_blockdesc(&buf[length], + blocks, block_size); + } + } else { + length += spc_modesense_blockdesc(&buf[length], blocks, + block_size); + } } else { - offset -= 1; - buf[0] = offset & 0xff; - offset += 1; - - if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || - (cmd->se_deve && - (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) - spc_modesense_write_protect(&buf[2], type); - - if ((dev->dev_attrib.emulate_write_cache > 0) && - (dev->dev_attrib.emulate_fua_write > 0)) - spc_modesense_dpofua(&buf[2], type); + if (ten) + length += 4; + else + length += 1; } - rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min(offset, cmd->data_length)); - transport_kunmap_data_sg(cmd); + if (page == 0x3f) { + if (subpage != 0x00 && subpage != 0xff) { + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + length = -EINVAL; + goto out; + } + + for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) { + /* + * Tricky way to say all subpage 00h for + * subpage==0, all subpages for subpage==0xff + * (and we just checked above that those are + * the only two possibilities). + */ + if ((modesense_handlers[i].subpage & ~subpage) == 0) { + ret = modesense_handlers[i].emulate(dev, pc, &buf[length]); + if (!ten && length + ret >= 255) + break; + length += ret; + } + } + + goto set_length; + } + + for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) + if (modesense_handlers[i].page == page && + modesense_handlers[i].subpage == subpage) { + length += modesense_handlers[i].emulate(dev, pc, &buf[length]); + goto set_length; + } + + /* + * We don't intend to implement: + * - obsolete page 03h "format parameters" (checked by Solaris) + */ + if (page != 0x03) + pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", + page, subpage); + + cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; + return -EINVAL; + +set_length: + if (ten) + put_unaligned_be16(length - 2, buf); + else + buf[0] = length - 1; + +out: + if (buf != map_buf) { + memcpy(map_buf, buf, cmd->data_length); + kfree(buf); } + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } -- cgit v0.10.2 From 0f6d64cee9c518f5d3138a90cead62fba2031074 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:49 -0700 Subject: target: Implement mode page 0x1c, "Informational Exceptions" The Windows SCSI compliance test asks for this mode page, and it's easy to implement: we can just return all 0s to show we don't support any of these features. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 8ccfe00..6c10fce 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -760,6 +760,19 @@ out: return 20; } +static int spc_modesense_informational_exceptions(struct se_device *dev, u8 pc, unsigned char *p) +{ + p[0] = 0x1c; + p[1] = 0x0a; + + /* No changeable values for now */ + if (pc == 1) + goto out; + +out: + return 12; +} + static struct { uint8_t page; uint8_t subpage; @@ -768,6 +781,7 @@ static struct { { .page = 0x01, .subpage = 0x00, .emulate = spc_modesense_rwrecovery }, { .page = 0x08, .subpage = 0x00, .emulate = spc_modesense_caching }, { .page = 0x0a, .subpage = 0x00, .emulate = spc_modesense_control }, + { .page = 0x1c, .subpage = 0x00, .emulate = spc_modesense_informational_exceptions }, }; static void spc_modesense_write_protect(unsigned char *buf, int type) -- cgit v0.10.2 From 3a3c5e4a672c5cd61cbdcedcd027312577f9ab7c Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:50 -0700 Subject: target: Add emulation for MODE SELECT This is another thing that compliance tests try, and it's easy to implement on top of the MODE SENSE refactoring; since we don't claim to support any changeable values, all we need to do is check that the page contents sent by the initiator match what we would return. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 6c10fce..33022a3 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -975,6 +975,57 @@ out: return 0; } +static int spc_emulate_modeselect(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + char *cdb = cmd->t_task_cdb; + bool ten = cdb[0] == MODE_SELECT_10; + int off = ten ? 8 : 4; + bool pf = !!(cdb[1] & 0x10); + u8 page, subpage; + unsigned char *buf; + unsigned char tbuf[SE_MODE_PAGE_BUF]; + int length; + int ret = 0; + int i; + + buf = transport_kmap_data_sg(cmd); + + if (!pf) { + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + ret = -EINVAL; + goto out; + } + + page = buf[off] & 0x3f; + subpage = buf[off] & 0x40 ? buf[off + 1] : 0; + + for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) + if (modesense_handlers[i].page == page && + modesense_handlers[i].subpage == subpage) { + memset(tbuf, 0, SE_MODE_PAGE_BUF); + length = modesense_handlers[i].emulate(dev, 0, tbuf); + goto check_contents; + } + + cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; + ret = -EINVAL; + goto out; + +check_contents: + if (memcmp(buf + off, tbuf, length)) { + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + } + +out: + transport_kunmap_data_sg(cmd); + + if (!ret) + target_complete_cmd(cmd, GOOD); + return ret; +} + static int spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; @@ -1113,9 +1164,11 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) switch (cdb[0]) { case MODE_SELECT: *size = cdb[4]; + cmd->execute_cmd = spc_emulate_modeselect; break; case MODE_SELECT_10: *size = (cdb[7] << 8) + cdb[8]; + cmd->execute_cmd = spc_emulate_modeselect; break; case MODE_SENSE: *size = cdb[4]; -- cgit v0.10.2 From fecae40abb1ae9218bdbaa8b8e30bfb5ae43f522 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 1 Nov 2012 18:43:03 -0700 Subject: target: Fix incorrect starting offset after MODE_SENSE refactoring This patch fixes a new off-by-one bug in the hardcoded starting offset of spc_emulate_modesense() code that causes BLOCK DESCRIPTOR to be incorrectly written within the MEDIUM TYPE buffer area of the mode parameter header. According to spc4r30, Section 7.5.4, BLOCK DESCRIPTOR for MODE_SENSE_10 starts at byte 3, and BLOCK_DESCRIPTOR for MODE_SENSE (6) starts at byte 2. (roland: add MODE DATA LENGTH + MEDIUM TYPE offset comment) Cc: Roland Dreier Cc: Christoph Hellwig Cc: Douglas Gilbert Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 33022a3..f9c2bd0 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -870,8 +870,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd) } else { buf = map_buf; } - - length = ten ? 2 : 1; + /* + * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for + * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). + */ + length = ten ? 3 : 2; /* DEVICE-SPECIFIC PARAMETER */ if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || -- cgit v0.10.2 From de103c93aff0bed0ae984274e5dc8b95899badab Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Nov 2012 12:24:09 -0800 Subject: target: pass sense_reason as a return value Pass the sense reason as an explicit return value from the I/O submission path instead of storing it in struct se_cmd and using negative return values. This cleans up a lot of the code pathes, and with the sparse annotations for the new sense_reason_t type allows for much better error checking. (nab: Convert spc_emulate_modesense + spc_emulate_modeselect to use sense_reason_t with Roland's MODE SELECT changes) Signed-off-by: Christoph Hellwig Cc: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index cf23c46..e6fafc62 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1730,7 +1730,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, uint64_t unpacked_lun; u64 data_len; enum dma_data_direction dir; - int ret; + sense_reason_t ret; BUG_ON(!send_ioctx); @@ -1755,12 +1755,10 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, break; } - ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len); - if (ret) { + if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) { printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", srp_cmd->tag); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + ret = TCM_INVALID_CDB_FIELD; kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; } @@ -1769,26 +1767,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, cmd->data_direction = dir; unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, sizeof(srp_cmd->lun)); - if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) { + ret = transport_lookup_cmd_lun(cmd, unpacked_lun); + if (ret) { kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; } ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb); - if (ret < 0) { + if (ret) { kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); - if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) { + if (ret == TCM_RESERVATION_CONFLICT) { srpt_queue_status(cmd); return 0; - } else - goto send_sense; + } + goto send_sense; } transport_handle_cdb_direct(cmd); return 0; send_sense: - transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason, - 0); + transport_send_check_condition_and_sense(cmd, ret, 0); return -1; } @@ -1882,16 +1880,14 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, send_ioctx->tag = srp_tsk->tag; tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); if (tcm_tmr < 0) { - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; - goto process_tmr; + goto fail; } res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); if (res < 0) { - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; - goto process_tmr; + goto fail; } unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, @@ -1899,22 +1895,19 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun); if (res) { pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun); - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; - goto process_tmr; + goto fail; } if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); -process_tmr: kref_get(&send_ioctx->kref); - if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) - transport_generic_handle_tmr(&send_ioctx->cmd); - else - transport_send_check_condition_and_sense(cmd, - cmd->scsi_sense_reason, 0); - + transport_generic_handle_tmr(&send_ioctx->cmd); + return; +fail: + kref_get(&send_ioctx->kref); + transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: } /** diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 3d74f2f..c569624 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -620,8 +620,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work) return; } - cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; - transport_generic_request_failure(&cmd->se_cmd); + transport_generic_request_failure(&cmd->se_cmd, + TCM_CHECK_CONDITION_ABORT_CMD); return; } diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 035c2c7..093fb60 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd( struct iscsi_conn *conn, unsigned char *buf) { - int data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret; - int dump_immediate_data = 0, send_check_condition = 0, payload_length; - struct iscsi_cmd *cmd = NULL; + int data_direction, payload_length, cmdsn_ret = 0, immed_ret; + struct iscsi_cmd *cmd = NULL; struct iscsi_scsi_req *hdr; int iscsi_task_attr; int sam_task_attr; @@ -956,38 +955,26 @@ done: " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, hdr->cmdsn, hdr->data_length, payload_length, conn->cid); - /* - * The CDB is going to an se_device_t. - */ - ret = transport_lookup_cmd_lun(&cmd->se_cmd, - scsilun_to_int(&hdr->lun)); - if (ret < 0) { - if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) { - pr_debug("Responding to non-acl'ed," - " non-existent or non-exported iSCSI LUN:" - " 0x%016Lx\n", get_unaligned_le64(&hdr->lun)); + cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, + scsilun_to_int(&hdr->lun)); + if (cmd->sense_reason) + goto attach_cmd; + + cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); + if (cmd->sense_reason) { + if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { + return iscsit_add_reject_from_cmd( + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, 1, buf, cmd); } - send_check_condition = 1; + goto attach_cmd; } - transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); - if (transport_ret == -ENOMEM) { + if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); - } else if (transport_ret < 0) { - /* - * Unsupported SAM Opcode. CHECK_CONDITION will be sent - * in iscsit_execute_cmd() during the CmdSN OOO Execution - * Mechinism. - */ - send_check_condition = 1; - } else { - if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, 1, buf, cmd); } attach_cmd: @@ -1000,11 +987,12 @@ attach_cmd: */ core_alua_check_nonop_delay(&cmd->se_cmd); - ret = iscsit_allocate_iovecs(cmd); - if (ret < 0) + if (iscsit_allocate_iovecs(cmd) < 0) { return iscsit_add_reject_from_cmd( ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1, 0, buf, cmd); + } + /* * Check the CmdSN against ExpCmdSN/MaxCmdSN here if * the Immediate Bit is not set, and no Immediate @@ -1031,10 +1019,7 @@ attach_cmd: * If no Immediate Data is attached, it's OK to return now. */ if (!cmd->immediate_data) { - if (send_check_condition) - return 0; - - if (cmd->unsolicited_data) { + if (!cmd->sense_reason && cmd->unsolicited_data) { iscsit_set_dataout_sequence_values(cmd); spin_lock_bh(&cmd->dataout_timeout_lock); @@ -1050,19 +1035,17 @@ attach_cmd: * thread. They are processed in CmdSN order by * iscsit_check_received_cmdsn() below. */ - if (send_check_condition) { + if (cmd->sense_reason) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; - dump_immediate_data = 1; goto after_immediate_data; } /* * Call directly into transport_generic_new_cmd() to perform * the backend memory allocation. */ - ret = transport_generic_new_cmd(&cmd->se_cmd); - if (ret < 0) { + cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); + if (cmd->sense_reason) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; - dump_immediate_data = 1; goto after_immediate_data; } @@ -1079,7 +1062,7 @@ after_immediate_data: * Special case for Unsupported SAM WRITE Opcodes * and ImmediateData=Yes. */ - if (dump_immediate_data) { + if (cmd->sense_reason) { if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) return -1; } else if (cmd->unsolicited_data) { @@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); spin_lock_irqsave(&se_cmd->t_state_lock, flags); - if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) || - (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) + if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE)) dump_unsolicited_data = 1; spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); @@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd( ret = transport_lookup_tmr_lun(&cmd->se_cmd, scsilun_to_int(&hdr->lun)); if (ret < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_NO_LUN; goto attach; } @@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd( switch (function) { case ISCSI_TM_FUNC_ABORT_TASK: se_tmr->response = iscsit_tmr_abort_task(cmd, buf); - if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + if (se_tmr->response) goto attach; - } break; case ISCSI_TM_FUNC_ABORT_TASK_SET: case ISCSI_TM_FUNC_CLEAR_ACA: @@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd( break; case ISCSI_TM_FUNC_TARGET_WARM_RESET: if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; goto attach; } break; case ISCSI_TM_FUNC_TARGET_COLD_RESET: if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; goto attach; } @@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd( * Perform sanity checks on the ExpDataSN only if the * TASK_REASSIGN was successful. */ - if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) + if (se_tmr->response) break; if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) @@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd( default: pr_err("Unknown TMR function: 0x%02x, protocol" " error.\n", function); - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED; goto attach; } diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 21048db..7a333d2 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -474,7 +474,7 @@ struct iscsi_cmd { struct scatterlist *first_data_sg; u32 first_data_sg_off; u32 kmapped_nents; - + sense_reason_t sense_reason; } ____cacheline_aligned; struct iscsi_tmr_req { diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 21f29d9..0b52a23 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) case ISCSI_OP_SCSI_CMD: /* * Go ahead and send the CHECK_CONDITION status for - * any SCSI CDB exceptions that may have occurred, also - * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well. + * any SCSI CDB exceptions that may have occurred. */ - if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { - if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) { + if (cmd->sense_reason) { + if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) { cmd->i_state = ISTATE_SEND_STATUS; spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, @@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) * exception */ return transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); + cmd->sense_reason, 0); } /* * Special case for delayed CmdSN with Immediate @@ -1013,7 +1012,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); break; case ISCSI_OP_SCSI_TMFUNC: - if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { + if (cmd->se_cmd.se_tmr_req->response) { spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index b3302a9..e62dc52 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -41,7 +41,7 @@ #include "target_core_alua.h" #include "target_core_ua.h" -static int core_alua_check_transition(int state, int *primary); +static sense_reason_t core_alua_check_transition(int state, int *primary); static int core_alua_set_tg_pt_secondary_state( struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, struct se_port *port, int explict, int offline); @@ -59,7 +59,8 @@ struct t10_alua_lu_gp *default_lu_gp; * * See spc4r17 section 6.27 */ -int target_emulate_report_target_port_groups(struct se_cmd *cmd) +sense_reason_t +target_emulate_report_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_port *port; @@ -68,6 +69,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) unsigned char *buf; u32 rd_len = 0, off; int ext_hdr = (cmd->t_task_cdb[1] & 0x20); + /* * Skip over RESERVED area to first Target port group descriptor * depending on the PARAMETER DATA FORMAT type.. @@ -81,10 +83,11 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) 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; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, @@ -200,7 +203,8 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) * * See spc4r17 section 6.35 */ -int target_emulate_set_target_port_groups(struct se_cmd *cmd) +sense_reason_t +target_emulate_set_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_port *port, *l_port = cmd->se_lun->lun_sep; @@ -209,22 +213,23 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; unsigned char *buf; unsigned char *ptr; + sense_reason_t rc; u32 len = 4; /* Skip over RESERVED area in header */ - int alua_access_state, primary = 0, rc; + int alua_access_state, primary = 0; u16 tg_pt_id, rtpi; - if (!l_port) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; - } + if (!l_port) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (cmd->data_length < 4) { pr_warn("SET TARGET PORT GROUPS parameter list length %u too" " small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed @@ -233,8 +238,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; if (!l_tg_pt_gp_mem) { pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); @@ -242,24 +246,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) if (!l_tg_pt_gp) { spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } - rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA); spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); - if (!rc) { + if (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) { pr_debug("Unable to process SET_TARGET_PORT_GROUPS" " while TPGS_EXPLICT_ALUA is disabled\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } ptr = &buf[4]; /* Skip over RESERVED area in header */ while (len < cmd->data_length) { + bool found = false; alua_access_state = (ptr[0] & 0x0f); /* * Check the received ALUA access state, and determine if @@ -267,7 +269,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * access state. */ rc = core_alua_check_transition(alua_access_state, &primary); - if (rc != 0) { + if (rc) { /* * If the SET TARGET PORT GROUPS attempts to establish * an invalid combination of target port asymmetric @@ -278,11 +280,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * REQUEST, and the additional sense code set to INVALID * FIELD IN PARAMETER LIST. */ - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; goto out; } - rc = -1; + /* * If the ASYMMETRIC ACCESS STATE field (see table 267) * specifies a primary target port asymmetric access state, @@ -314,11 +314,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_inc(); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - rc = core_alua_do_port_transition(tg_pt_gp, + if (!core_alua_do_port_transition(tg_pt_gp, dev, l_port, nacl, - alua_access_state, 1); + alua_access_state, 1)) + found = true; spin_lock(&dev->t10_alua.tg_pt_gps_lock); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); @@ -326,15 +328,6 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) break; } spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - /* - * If not matching target port group ID can be located - * throw an exception with ASCQ: INVALID_PARAMETER_LIST - */ - if (rc != 0) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; - goto out; - } } else { /* * Extact the RELATIVE TARGET PORT IDENTIFIER to identify @@ -353,25 +346,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) continue; tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; + spin_unlock(&dev->se_port_lock); - rc = core_alua_set_tg_pt_secondary_state( - tg_pt_gp_mem, port, 1, 1); + if (!core_alua_set_tg_pt_secondary_state( + tg_pt_gp_mem, port, 1, 1)) + found = true; spin_lock(&dev->se_port_lock); break; } spin_unlock(&dev->se_port_lock); - /* - * If not matching relative target port identifier can - * be located, throw an exception with ASCQ: - * INVALID_PARAMETER_LIST - */ - if (rc != 0) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; - goto out; - } + } + + if (!found) { + rc = TCM_INVALID_PARAMETER_LIST; + goto out; } ptr += 4; @@ -526,7 +516,8 @@ static inline int core_alua_state_transition( * return 0: Used to signal success * reutrn -1: Used to signal failure, and invalid cdb field */ -int target_alua_state_check(struct se_cmd *cmd) +sense_reason_t +target_alua_state_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -599,8 +590,7 @@ int target_alua_state_check(struct se_cmd *cmd) default: pr_err("Unknown ALUA access state: 0x%02x\n", out_alua_state); - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } out: @@ -617,15 +607,17 @@ out: cmd->scsi_asc = 0x04; cmd->scsi_ascq = alua_ascq; + return TCM_CHECK_CONDITION_NOT_READY; } - return ret; + return 0; } /* * Check implict and explict ALUA state change request. */ -static int core_alua_check_transition(int state, int *primary) +static sense_reason_t +core_alua_check_transition(int state, int *primary) { switch (state) { case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: @@ -647,7 +639,7 @@ static int core_alua_check_transition(int state, int *primary) break; default: pr_err("Unknown ALUA access state: 0x%02x\n", state); - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } return 0; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index a2af8aa..e539c3e 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -72,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; -extern int target_emulate_report_target_port_groups(struct se_cmd *); -extern int target_emulate_set_target_port_groups(struct se_cmd *); +extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *); +extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *); extern int core_alua_check_nonop_delay(struct se_cmd *); extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, struct se_device *, struct se_port *, @@ -132,6 +132,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, const char *, size_t); extern int core_setup_alua(struct se_device *); -extern int target_alua_state_check(struct se_cmd *cmd); +extern sense_reason_t target_alua_state_check(struct se_cmd *cmd); #endif /* TARGET_CORE_ALUA_H */ diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 066e815..599374e 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -54,18 +54,16 @@ static struct se_hba *lun0_hba; /* not static, needed by tpg.c */ struct se_device *g_lun0_dev; -int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) +sense_reason_t +transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) { struct se_lun *se_lun = NULL; struct se_session *se_sess = se_cmd->se_sess; struct se_device *dev; unsigned long flags; - if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -ENODEV; - } + if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) + return TCM_NON_EXISTENT_LUN; spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; @@ -77,14 +75,12 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) if ((se_cmd->data_direction == DMA_TO_DEVICE) && (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) { - se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); - return -EACCES; + return TCM_WRITE_PROTECTED; } if (se_cmd->data_direction == DMA_TO_DEVICE) @@ -109,23 +105,18 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) * MappedLUN=0 exists for this Initiator Port. */ if (unpacked_lun != 0) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); - return -ENODEV; + return TCM_NON_EXISTENT_LUN; } /* * Force WRITE PROTECT for virtual LUN 0 */ if ((se_cmd->data_direction != DMA_FROM_DEVICE) && - (se_cmd->data_direction != DMA_NONE)) { - se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -EACCES; - } + (se_cmd->data_direction != DMA_NONE)) + return TCM_WRITE_PROTECTED; se_lun = &se_sess->se_tpg->tpg_virt_lun0; se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; @@ -162,11 +153,8 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; unsigned long flags; - if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) return -ENODEV; - } spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; @@ -186,7 +174,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return -ENODEV; } diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 342a6a6..3ccef83 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -309,7 +309,8 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, return 1; } -static int fd_execute_sync_cache(struct se_cmd *cmd) +static sense_reason_t +fd_execute_sync_cache(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct fd_dev *fd_dev = FD_DEV(dev); @@ -345,17 +346,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) if (immed) return 0; - if (ret) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); - } else { + else target_complete_cmd(cmd, SAM_STAT_GOOD); - } return 0; } -static int fd_execute_rw(struct se_cmd *cmd) +static sense_reason_t +fd_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -388,10 +388,9 @@ static int fd_execute_rw(struct se_cmd *cmd) } } - if (ret < 0) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return ret; - } + if (ret < 0) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; @@ -515,7 +514,8 @@ static struct sbc_ops fd_sbc_ops = { .execute_sync_cache = fd_execute_sync_cache, }; -static int fd_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +fd_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &fd_sbc_ops); } diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 17fc01d..53f4501 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -261,13 +261,10 @@ static void iblock_end_io_flush(struct bio *bio, int err) pr_err("IBLOCK: cache flush failed: %d\n", err); if (cmd) { - if (err) { - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (err) target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); - } else { + else target_complete_cmd(cmd, SAM_STAT_GOOD); - } } bio_put(bio); @@ -277,7 +274,8 @@ static void iblock_end_io_flush(struct bio *bio, int err) * Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must * always flush the whole cache. */ -static int iblock_execute_sync_cache(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_sync_cache(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int immed = (cmd->t_task_cdb[1] & 0x2); @@ -299,7 +297,8 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) return 0; } -static int iblock_execute_unmap(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_unmap(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -307,17 +306,18 @@ static int iblock_execute_unmap(struct se_cmd *cmd) sector_t lba; int size; u32 range; - int ret = 0; - int dl, bd_dl; + sense_reason_t ret = 0; + int dl, bd_dl, err; if (cmd->data_length < 8) { pr_warn("UNMAP parameter list length %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); @@ -330,8 +330,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) size = bd_dl; if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto err; } @@ -347,22 +346,21 @@ static int iblock_execute_unmap(struct se_cmd *cmd) (unsigned long long)lba, range); if (range > dev->dev_attrib.max_unmap_lba_count) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto err; } if (lba + range > dev->transport->get_blocks(dev) + 1) { - cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; - ret = -EINVAL; + ret = TCM_ADDRESS_OUT_OF_RANGE; goto err; } - ret = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, + err = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, GFP_KERNEL, 0); - if (ret < 0) { + if (err < 0) { pr_err("blkdev_issue_discard() failed: %d\n", - ret); + err); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto err; } @@ -377,7 +375,8 @@ err: return ret; } -static int iblock_execute_write_same(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_write_same(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int ret; @@ -387,7 +386,7 @@ static int iblock_execute_write_same(struct se_cmd *cmd) 0); if (ret < 0) { pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); - return ret; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } target_complete_cmd(cmd, GOOD); @@ -552,7 +551,8 @@ static void iblock_submit_bios(struct bio_list *list, int rw) blk_finish_plug(&plug); } -static int iblock_execute_rw(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -598,8 +598,7 @@ static int iblock_execute_rw(struct se_cmd *cmd) else { pr_err("Unsupported SCSI -> BLOCK LBA conversion:" " %u\n", dev->dev_attrib.block_size); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOSYS; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); @@ -659,9 +658,8 @@ fail_put_bios: bio_put(bio); fail_free_ibr: kfree(ibr); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; fail: - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } static sector_t iblock_get_blocks(struct se_device *dev) @@ -706,7 +704,8 @@ static struct sbc_ops iblock_sbc_ops = { .execute_unmap = iblock_execute_unmap, }; -static int iblock_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +iblock_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &iblock_sbc_ops); } diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 2f37720..bc9c522 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -101,7 +101,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); int transport_clear_lun_from_sessions(struct se_lun *); void transport_send_task_abort(struct se_cmd *); -int target_cmd_size_check(struct se_cmd *cmd, unsigned int size); +sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); void target_qf_do_work(struct work_struct *work); /* target_core_stat.c */ diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index f561a08..ffbe0ea 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -68,7 +68,8 @@ int core_pr_dump_initiator_port( static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); -static int target_scsi2_reservation_check(struct se_cmd *cmd) +static sense_reason_t +target_scsi2_reservation_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; @@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struct se_cmd *cmd) return 0; if (dev->dev_reserved_node_acl != sess->se_node_acl) - return -EBUSY; + return TCM_RESERVATION_CONFLICT; if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { if (dev->dev_res_bin_isid != sess->sess_bin_isid) - return -EBUSY; + return TCM_RESERVATION_CONFLICT; } return 0; @@ -165,32 +166,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) pr_err("Received legacy SPC-2 RESERVE/RELEASE" " while active SPC-3 registrations exist," " returning RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return -EBUSY; } return 0; } -int target_scsi2_reservation_release(struct se_cmd *cmd) +sense_reason_t +target_scsi2_reservation_release(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg; - int ret = 0, rc; + int rc; if (!sess || !sess->se_tpg) goto out; rc = target_check_scsi2_reservation_conflict(cmd); if (rc == 1) goto out; - else if (rc < 0) { - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; - } + if (rc < 0) + return TCM_RESERVATION_CONFLICT; - ret = 0; spin_lock(&dev->dev_reservation_lock); if (!dev->dev_reserved_node_acl || !sess) goto out_unlock; @@ -216,25 +213,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) out_unlock: spin_unlock(&dev->dev_reservation_lock); out: - if (!ret) - target_complete_cmd(cmd, GOOD); - return ret; + target_complete_cmd(cmd, GOOD); + return 0; } -int target_scsi2_reservation_reserve(struct se_cmd *cmd) +sense_reason_t +target_scsi2_reservation_reserve(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg; - int ret = 0, rc; + sense_reason_t ret = 0; + int rc; if ((cmd->t_task_cdb[1] & 0x01) && (cmd->t_task_cdb[1] & 0x02)) { pr_err("LongIO and Obselete Bits set, returning" " ILLEGAL_REQUEST\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - ret = -EINVAL; - goto out; + return TCM_UNSUPPORTED_SCSI_OPCODE; } /* * This is currently the case for target_core_mod passthrough struct se_cmd @@ -245,13 +241,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) rc = target_check_scsi2_reservation_conflict(cmd); if (rc == 1) goto out; - else if (rc < 0) { - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; - } - ret = 0; + if (rc < 0) + return TCM_RESERVATION_CONFLICT; + tpg = sess->se_tpg; spin_lock(&dev->dev_reservation_lock); if (dev->dev_reserved_node_acl && @@ -265,8 +258,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) " from %s \n", cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out_unlock; } @@ -536,7 +528,8 @@ static int core_scsi3_pr_seq_non_holder( return 1; /* Conflict by default */ } -static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) +static sense_reason_t +target_scsi3_pr_reservation_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; @@ -562,7 +555,7 @@ static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) check_nonholder: if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) - return -EBUSY; + return TCM_RESERVATION_CONFLICT; return 0; } @@ -1435,7 +1428,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) smp_mb__after_atomic_dec(); } -static int core_scsi3_decode_spec_i_port( +static sense_reason_t +core_scsi3_decode_spec_i_port( struct se_cmd *cmd, struct se_portal_group *tpg, unsigned char *l_isid, @@ -1457,8 +1451,9 @@ static int core_scsi3_decode_spec_i_port( unsigned char *buf; unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; + sense_reason_t ret; u32 tpdl, tid_len = 0; - int ret, dest_local_nexus, prf_isid; + int dest_local_nexus, prf_isid; u32 dest_rtpi = 0; memset(dest_iport, 0, 64); @@ -1473,8 +1468,7 @@ static int core_scsi3_decode_spec_i_port( tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); if (!tidh_new) { pr_err("Unable to allocate tidh_new\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = tpg; @@ -1486,8 +1480,7 @@ static int core_scsi3_decode_spec_i_port( sa_res_key, all_tg_pt, aptpl); if (!local_pr_reg) { kfree(tidh_new); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } tidh_new->dest_pr_reg = local_pr_reg; /* @@ -1501,12 +1494,16 @@ static int core_scsi3_decode_spec_i_port( if (cmd->data_length < 28) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out; + } + /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, * first extract TransportID Parameter Data Length, and make sure @@ -1521,9 +1518,8 @@ static int core_scsi3_decode_spec_i_port( pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" " does not equal CDB data_length: %u\n", tpdl, cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } /* * Start processing the received transport IDs using the @@ -1566,16 +1562,13 @@ static int core_scsi3_decode_spec_i_port( smp_mb__after_atomic_inc(); spin_unlock(&dev->se_port_lock); - ret = core_scsi3_tpg_depend_item(tmp_tpg); - if (ret != 0) { + if (core_scsi3_tpg_depend_item(tmp_tpg)) { pr_err(" core_scsi3_tpg_depend_item()" " for tmp_tpg\n"); atomic_dec(&tmp_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } /* * Locate the destination initiator ACL to be registered @@ -1597,17 +1590,14 @@ static int core_scsi3_decode_spec_i_port( continue; } - ret = core_scsi3_nodeacl_depend_item(dest_node_acl); - if (ret != 0) { + if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { pr_err("configfs_depend_item() failed" " for dest_node_acl->acl_group\n"); atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_tpg_undepend_item(tmp_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } dest_tpg = tmp_tpg; @@ -1624,9 +1614,8 @@ static int core_scsi3_decode_spec_i_port( if (!dest_tpg) { pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" " dest_tpg\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" @@ -1639,9 +1628,8 @@ static int core_scsi3_decode_spec_i_port( " %u for Transport ID: %s\n", tid_len, ptr); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } /* * Locate the desintation struct se_dev_entry pointer for matching @@ -1658,23 +1646,19 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } - ret = core_scsi3_lunacl_depend_item(dest_se_deve); - if (ret < 0) { + if (core_scsi3_lunacl_depend_item(dest_se_deve)) { pr_err("core_scsi3_lunacl_depend_item()" " failed\n"); atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" @@ -1710,10 +1694,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -ENOMEM; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = dest_tpg; @@ -1744,9 +1726,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); kfree(tidh_new); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } tidh_new->dest_pr_reg = dest_pr_reg; list_add_tail(&tidh_new->dest_list, &tid_dest_list); @@ -1804,8 +1785,9 @@ static int core_scsi3_decode_spec_i_port( } return 0; -out: +out_unmap: transport_kunmap_data_sg(cmd); +out: /* * For the failure case, release everything from tid_dest_list * including *dest_pr_reg and the configfs dependances.. @@ -2020,14 +2002,15 @@ static int __core_scsi3_write_aptpl_to_file( return 0; } -static int core_scsi3_update_and_write_aptpl( - struct se_device *dev, - unsigned char *in_buf, - u32 in_pr_aptpl_buf_len) +static int +core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, + u32 in_pr_aptpl_buf_len) { unsigned char null_buf[64], *buf; u32 pr_aptpl_buf_len; - int ret, clear_aptpl_metadata = 0; + int clear_aptpl_metadata = 0; + int ret; + /* * Can be called with a NULL pointer from PROUT service action CLEAR */ @@ -2049,25 +2032,17 @@ static int core_scsi3_update_and_write_aptpl( clear_aptpl_metadata); if (ret != 0) return ret; + /* * __core_scsi3_write_aptpl_to_file() will call strlen() * on the passed buf to determine pr_aptpl_buf_len. */ - ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0); - if (ret != 0) - return ret; - - return ret; + return __core_scsi3_write_aptpl_to_file(dev, buf, 0); } -static int core_scsi3_emulate_pro_register( - struct se_cmd *cmd, - u64 res_key, - u64 sa_res_key, - int aptpl, - int all_tg_pt, - int spec_i_pt, - int ignore_key) +static sense_reason_t +core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, + int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_register( /* Used for APTPL metadata w/ UNREGISTER */ unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; - int pr_holder = 0, ret = 0, type; + sense_reason_t ret; + int pr_holder = 0, type; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } se_tpg = se_sess->se_tpg; se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; @@ -2103,8 +2078,7 @@ static int core_scsi3_emulate_pro_register( if (res_key) { pr_warn("SPC-3 PR: Reservation Key non-zero" " for SA REGISTER, returning CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * Do nothing but return GOOD status. @@ -2118,15 +2092,13 @@ static int core_scsi3_emulate_pro_register( * Port Endpoint that the PRO was received from on the * Logical Unit of the SCSI device server. */ - ret = core_scsi3_alloc_registration(cmd->se_dev, + if (core_scsi3_alloc_registration(cmd->se_dev, se_sess->se_node_acl, se_deve, isid_ptr, sa_res_key, all_tg_pt, aptpl, - ignore_key, 0); - if (ret != 0) { + ignore_key, 0)) { pr_err("Unable to allocate" " struct t10_pr_registration\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } } else { /* @@ -2160,201 +2132,192 @@ static int core_scsi3_emulate_pro_register( pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { + pr_tmpl->pr_aptpl_buf_len)) { pr_tmpl->pr_aptpl_active = 1; pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); } - core_scsi3_put_pr_reg(pr_reg); - return ret; - } else { - /* - * Locate the existing *pr_reg via struct se_node_acl pointers - */ - pr_reg = pr_reg_e; - type = pr_reg->pr_res_type; - - if (!ignore_key) { - if (res_key != pr_reg->pr_res_key) { - pr_err("SPC-3 PR REGISTER: Received" - " res_key: 0x%016Lx does not match" - " existing SA REGISTER res_key:" - " 0x%016Lx\n", res_key, - pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; - } + goto out_put_pr_reg; + } + + /* + * Locate the existing *pr_reg via struct se_node_acl pointers + */ + pr_reg = pr_reg_e; + type = pr_reg->pr_res_type; + + if (!ignore_key) { + if (res_key != pr_reg->pr_res_key) { + pr_err("SPC-3 PR REGISTER: Received" + " res_key: 0x%016Lx does not match" + " existing SA REGISTER res_key:" + " 0x%016Lx\n", res_key, + pr_reg->pr_res_key); + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } - if (spec_i_pt) { - pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" - " set while sa_res_key=0\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + } + + if (spec_i_pt) { + pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" + " set while sa_res_key=0\n"); + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; + } + + /* + * An existing ALL_TG_PT=1 registration being released + * must also set ALL_TG_PT=1 in the incoming PROUT. + */ + if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { + pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" + " registration exists, but ALL_TG_PT=1 bit not" + " present in received PROUT\n"); + ret = TCM_INVALID_CDB_FIELD; + goto out_put_pr_reg; + } + + /* + * Allocate APTPL metadata buffer used for UNREGISTER ops + */ + if (aptpl) { + pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, + GFP_KERNEL); + if (!pr_aptpl_buf) { + pr_err("Unable to allocate" + " pr_aptpl_buf\n"); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; } - /* - * An existing ALL_TG_PT=1 registration being released - * must also set ALL_TG_PT=1 in the incoming PROUT. - */ - if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { - pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" - " registration exists, but ALL_TG_PT=1 bit not" - " present in received PROUT\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + } + + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T + * Nexus sa_res_key=1 Change Reservation Key for registered I_T + * Nexus. + */ + if (!sa_res_key) { + pr_holder = core_scsi3_check_implict_release( + cmd->se_dev, pr_reg); + if (pr_holder < 0) { + kfree(pr_aptpl_buf); + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } + + spin_lock(&pr_tmpl->registration_lock); /* - * Allocate APTPL metadata buffer used for UNREGISTER ops + * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port + * and matching pr_res_key. */ - if (aptpl) { - pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, - GFP_KERNEL); - if (!pr_aptpl_buf) { - pr_err("Unable to allocate" - " pr_aptpl_buf\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + if (pr_reg->pr_reg_all_tg_pt) { + list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, + &pr_tmpl->registration_list, + pr_reg_list) { + + if (!pr_reg_p->pr_reg_all_tg_pt) + continue; + if (pr_reg_p->pr_res_key != res_key) + continue; + if (pr_reg == pr_reg_p) + continue; + if (strcmp(pr_reg->pr_reg_nacl->initiatorname, + pr_reg_p->pr_reg_nacl->initiatorname)) + continue; + + __core_scsi3_free_registration(dev, + pr_reg_p, NULL, 0); } } + /* - * sa_res_key=0 Unregister Reservation Key for registered I_T - * Nexus sa_res_key=1 Change Reservation Key for registered I_T - * Nexus. + * Release the calling I_T Nexus registration now.. */ - if (!sa_res_key) { - pr_holder = core_scsi3_check_implict_release( - cmd->se_dev, pr_reg); - if (pr_holder < 0) { - kfree(pr_aptpl_buf); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; - } - - spin_lock(&pr_tmpl->registration_lock); - /* - * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port - * and matching pr_res_key. - */ - if (pr_reg->pr_reg_all_tg_pt) { - list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, - &pr_tmpl->registration_list, - pr_reg_list) { - - if (!pr_reg_p->pr_reg_all_tg_pt) - continue; + __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1); - if (pr_reg_p->pr_res_key != res_key) - continue; - - if (pr_reg == pr_reg_p) - continue; - - if (strcmp(pr_reg->pr_reg_nacl->initiatorname, - pr_reg_p->pr_reg_nacl->initiatorname)) - continue; - - __core_scsi3_free_registration(dev, - pr_reg_p, NULL, 0); - } - } - /* - * Release the calling I_T Nexus registration now.. - */ - __core_scsi3_free_registration(cmd->se_dev, pr_reg, - NULL, 1); - /* - * From spc4r17, section 5.7.11.3 Unregistering - * - * If the persistent reservation is a registrants only - * type, the device server shall establish a unit - * attention condition for the initiator port associated - * with every registered I_T nexus except for the I_T - * nexus on which the PERSISTENT RESERVE OUT command was - * received, with the additional sense code set to - * RESERVATIONS RELEASED. - */ - if (pr_holder && - ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) || - (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) { - list_for_each_entry(pr_reg_p, - &pr_tmpl->registration_list, - pr_reg_list) { - - core_scsi3_ua_allocate( - pr_reg_p->pr_reg_nacl, - pr_reg_p->pr_res_mapped_lun, - 0x2A, - ASCQ_2AH_RESERVATIONS_RELEASED); - } + /* + * From spc4r17, section 5.7.11.3 Unregistering + * + * If the persistent reservation is a registrants only + * type, the device server shall establish a unit + * attention condition for the initiator port associated + * with every registered I_T nexus except for the I_T + * nexus on which the PERSISTENT RESERVE OUT command was + * received, with the additional sense code set to + * RESERVATIONS RELEASED. + */ + if (pr_holder && + (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || + type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { + list_for_each_entry(pr_reg_p, + &pr_tmpl->registration_list, + pr_reg_list) { + + core_scsi3_ua_allocate( + pr_reg_p->pr_reg_nacl, + pr_reg_p->pr_res_mapped_lun, + 0x2A, + ASCQ_2AH_RESERVATIONS_RELEASED); } - spin_unlock(&pr_tmpl->registration_lock); + } + spin_unlock(&pr_tmpl->registration_lock); - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for UNREGISTER\n"); - return 0; - } + if (!aptpl) { + pr_tmpl->pr_aptpl_active = 0; + core_scsi3_update_and_write_aptpl(dev, NULL, 0); + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" + " for UNREGISTER\n"); + return 0; + } - ret = core_scsi3_update_and_write_aptpl(dev, - &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for UNREGISTER\n"); - } + if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], + pr_tmpl->pr_aptpl_buf_len)) { + pr_tmpl->pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated" + " for UNREGISTER\n"); + } - kfree(pr_aptpl_buf); - return ret; - } else { - /* - * Increment PRgeneration counter for struct se_device" - * upon a successful REGISTER, see spc4r17 section 6.3.2 - * READ_KEYS service action. - */ - pr_reg->pr_res_generation = core_scsi3_pr_generation( - cmd->se_dev); - pr_reg->pr_res_key = sa_res_key; - pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" - " Key for %s to: 0x%016Lx PRgeneration:" - " 0x%08x\n", cmd->se_tfo->get_fabric_name(), - (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", - pr_reg->pr_reg_nacl->initiatorname, - pr_reg->pr_res_key, pr_reg->pr_res_generation); - - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - core_scsi3_put_pr_reg(pr_reg); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for REGISTER\n"); - return 0; - } + goto out_free_aptpl_buf; + } - ret = core_scsi3_update_and_write_aptpl(dev, - &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for REGISTER\n"); - } + /* + * Increment PRgeneration counter for struct se_device" + * upon a successful REGISTER, see spc4r17 section 6.3.2 + * READ_KEYS service action. + */ + pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); + pr_reg->pr_res_key = sa_res_key; + pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" + " Key for %s to: 0x%016Lx PRgeneration:" + " 0x%08x\n", cmd->se_tfo->get_fabric_name(), + (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", + pr_reg->pr_reg_nacl->initiatorname, + pr_reg->pr_res_key, pr_reg->pr_res_generation); - kfree(pr_aptpl_buf); - core_scsi3_put_pr_reg(pr_reg); - } + if (!aptpl) { + pr_tmpl->pr_aptpl_active = 0; + core_scsi3_update_and_write_aptpl(dev, NULL, 0); + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" + " for REGISTER\n"); + ret = 0; + goto out_put_pr_reg; } - return 0; + + if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], + pr_tmpl->pr_aptpl_buf_len)) { + pr_tmpl->pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated" + " for REGISTER\n"); + } + +out_free_aptpl_buf: + kfree(pr_aptpl_buf); + ret = 0; +out_put_pr_reg: + core_scsi3_put_pr_reg(pr_reg); + return ret; } unsigned char *core_scsi3_pr_dump_type(int type) @@ -2379,26 +2342,23 @@ unsigned char *core_scsi3_pr_dump_type(int type) return "Unknown SPC-3 PR Type"; } -static int core_scsi3_pro_reserve( - struct se_cmd *cmd, - struct se_device *dev, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) { + struct se_device *dev = cmd->se_dev; struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_res_holder; struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; - int ret, prf_isid; + sense_reason_t ret; + int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2408,8 +2368,7 @@ static int core_scsi3_pro_reserve( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RESERVE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2424,9 +2383,8 @@ static int core_scsi3_pro_reserve( pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2440,9 +2398,8 @@ static int core_scsi3_pro_reserve( */ if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } /* * See if we have an existing PR reservation holder pointer at @@ -2473,9 +2430,8 @@ static int core_scsi3_pro_reserve( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2497,9 +2453,8 @@ static int core_scsi3_pro_reserve( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2512,8 +2467,8 @@ static int core_scsi3_pro_reserve( * shall completethe command with GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + ret = 0; + goto out_put_pr_reg; } /* * Otherwise, our *pr_reg becomes the PR reservation holder for said @@ -2537,27 +2492,24 @@ static int core_scsi3_pro_reserve( spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata" " for RESERVE\n"); + } } + ret = 0; +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); - return 0; + return ret; } -static int core_scsi3_emulate_pro_reserve( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope, + u64 res_key) { - struct se_device *dev = cmd->se_dev; - int ret = 0; - switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_EXCLUSIVE_ACCESS: @@ -2565,16 +2517,12 @@ static int core_scsi3_emulate_pro_reserve( case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: - ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key); - break; + return core_scsi3_pro_reserve(cmd, type, scope, res_key); default: pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" " 0x%02x\n", type); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } - - return ret; } /* @@ -2612,23 +2560,21 @@ static void __core_scsi3_complete_pro_release( pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; } -static int core_scsi3_emulate_pro_release( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, + u64 res_key) { struct se_device *dev = cmd->se_dev; struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; struct t10_reservation *pr_tmpl = &dev->t10_pr; - int ret, all_reg = 0; + int all_reg = 0; + sense_reason_t ret = 0; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_release( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RELEASE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 Section 5.7.11.2 Releasing: @@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_release( * No persistent reservation, return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); return 0; } if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || @@ -2673,9 +2617,9 @@ static int core_scsi3_emulate_pro_release( * persistent reservation holder. return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + goto out_put_pr_reg; } + /* * From spc4r17 Section 5.7.11.2 Releasing: * @@ -2695,9 +2639,8 @@ static int core_scsi3_emulate_pro_release( " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.11.2 Releasing and above: @@ -2718,9 +2661,8 @@ static int core_scsi3_emulate_pro_release( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * In response to a persistent reservation release request from the @@ -2773,20 +2715,18 @@ static int core_scsi3_emulate_pro_release( write_aptpl: if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, + &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); + } } - +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); - return 0; + return ret; } -static int core_scsi3_emulate_pro_clear( - struct se_cmd *cmd, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; @@ -2803,8 +2743,7 @@ static int core_scsi3_emulate_pro_clear( if (!pr_reg_n) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for CLEAR\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 section 5.7.11.6, Clearing: @@ -2823,8 +2762,7 @@ static int core_scsi3_emulate_pro_clear( " existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * a) Release the persistent reservation, if any; @@ -2948,13 +2886,9 @@ static void core_scsi3_release_preempt_and_abort( } } -static int core_scsi3_pro_preempt( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key, - u64 sa_res_key, - int abort) +static sense_reason_t +core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, + u64 sa_res_key, int abort) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; @@ -2964,12 +2898,10 @@ static int core_scsi3_pro_preempt( struct t10_reservation *pr_tmpl = &dev->t10_pr; u32 pr_res_mapped_lun = 0; int all_reg = 0, calling_it_nexus = 0, released_regs = 0; - int prh_type = 0, prh_scope = 0, ret; + int prh_type = 0, prh_scope = 0; - if (!se_sess) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; - } + if (!se_sess) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); @@ -2977,19 +2909,16 @@ static int core_scsi3_pro_preempt( pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } if (pr_reg_n->pr_res_key != res_key) { core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } spin_lock(&dev->dev_reservation_lock); @@ -3002,8 +2931,7 @@ static int core_scsi3_pro_preempt( if (!all_reg && !sa_res_key) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } /* * From spc4r17, section 5.7.11.4.4 Removing Registrations: @@ -3097,8 +3025,7 @@ static int core_scsi3_pro_preempt( if (!released_regs) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * For an existing all registrants type reservation @@ -3117,13 +3044,13 @@ static int core_scsi3_pro_preempt( spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL" " metadata for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); + } } core_scsi3_put_pr_reg(pr_reg_n); @@ -3253,12 +3180,12 @@ static int core_scsi3_pro_preempt( } if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" - "%s\n", (abort) ? "_AND_ABORT" : ""); + "%s\n", abort ? "_AND_ABORT" : ""); + } } core_scsi3_put_pr_reg(pr_reg_n); @@ -3266,16 +3193,10 @@ static int core_scsi3_pro_preempt( return 0; } -static int core_scsi3_emulate_pro_preempt( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key, - u64 sa_res_key, - int abort) +static sense_reason_t +core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, + u64 res_key, u64 sa_res_key, int abort) { - int ret = 0; - switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_EXCLUSIVE_ACCESS: @@ -3283,26 +3204,19 @@ static int core_scsi3_emulate_pro_preempt( case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: - ret = core_scsi3_pro_preempt(cmd, type, scope, - res_key, sa_res_key, abort); - break; + return core_scsi3_pro_preempt(cmd, type, scope, res_key, + sa_res_key, abort); default: pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } - - return ret; } -static int core_scsi3_emulate_pro_register_and_move( - struct se_cmd *cmd, - u64 res_key, - u64 sa_res_key, - int aptpl, - int unreg) +static sense_reason_t +core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, + u64 sa_res_key, int aptpl, int unreg) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -3318,15 +3232,16 @@ static int core_scsi3_emulate_pro_register_and_move( unsigned char *initiator_str; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; u32 tid_len, tmp_tid_len; - int new_reg = 0, type, scope, ret, matching_iname, prf_isid; + int new_reg = 0, type, scope, matching_iname, prf_isid; + sense_reason_t ret; unsigned short rtpi; unsigned char proto_ident; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } + memset(dest_iport, 0, 64); memset(i_buf, 0, PR_REG_ISID_ID_LEN); se_tpg = se_sess->se_tpg; @@ -3342,8 +3257,7 @@ static int core_scsi3_emulate_pro_register_and_move( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" " *pr_reg for REGISTER_AND_MOVE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * The provided reservation key much match the existing reservation key @@ -3353,9 +3267,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" " res_key: 0x%016Lx does not match existing SA REGISTER" " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * The service active reservation key needs to be non zero @@ -3363,9 +3276,8 @@ static int core_scsi3_emulate_pro_register_and_move( if (!sa_res_key) { pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" " sa_res_key\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } /* @@ -3374,6 +3286,11 @@ static int core_scsi3_emulate_pro_register_and_move( * information. */ buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; + } + rtpi = (buf[18] & 0xff) << 8; rtpi |= buf[19] & 0xff; tid_len = (buf[20] & 0xff) << 24; @@ -3387,9 +3304,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" " does not equal CDB data_length: %u\n", tid_len, cmd->data_length); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } spin_lock(&dev->se_port_lock); @@ -3407,15 +3323,13 @@ static int core_scsi3_emulate_pro_register_and_move( smp_mb__after_atomic_inc(); spin_unlock(&dev->se_port_lock); - ret = core_scsi3_tpg_depend_item(dest_se_tpg); - if (ret != 0) { + if (core_scsi3_tpg_depend_item(dest_se_tpg)) { pr_err("core_scsi3_tpg_depend_item() failed" " for dest_se_tpg\n"); atomic_dec(&dest_se_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; } spin_lock(&dev->se_port_lock); @@ -3427,12 +3341,15 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " fabric ops from Relative Target Port Identifier:" " %hu\n", rtpi); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; + } proto_ident = (buf[24] & 0x0f); pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" @@ -3444,16 +3361,14 @@ static int core_scsi3_emulate_pro_register_and_move( " from fabric: %s\n", proto_ident, dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), dest_tf_ops->get_fabric_name()); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" " containg a valid tpg_parse_pr_out_transport_id" " function pointer\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, @@ -3461,8 +3376,7 @@ static int core_scsi3_emulate_pro_register_and_move( if (!initiator_str) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " initiator_str from Transport ID\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } @@ -3491,8 +3405,7 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" " matches: %s on received I_T Nexus\n", initiator_str, pr_reg_nacl->initiatorname); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { @@ -3500,8 +3413,7 @@ static int core_scsi3_emulate_pro_register_and_move( " matches: %s %s on received I_T Nexus\n", initiator_str, iport_ptr, pr_reg_nacl->initiatorname, pr_reg->pr_reg_isid); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } after_iport_check: @@ -3521,19 +3433,17 @@ after_iport_check: pr_err("Unable to locate %s dest_node_acl for" " TransportID%s\n", dest_tf_ops->get_fabric_name(), initiator_str); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } - ret = core_scsi3_nodeacl_depend_item(dest_node_acl); - if (ret != 0) { + + if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { pr_err("core_scsi3_nodeacl_depend_item() for" " dest_node_acl\n"); atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); dest_node_acl = NULL; - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } @@ -3549,19 +3459,16 @@ after_iport_check: if (!dest_se_deve) { pr_err("Unable to locate %s dest_se_deve from RTPI:" " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } - ret = core_scsi3_lunacl_depend_item(dest_se_deve); - if (ret < 0) { + if (core_scsi3_lunacl_depend_item(dest_se_deve)) { pr_err("core_scsi3_lunacl_depend_item() failed\n"); atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); dest_se_deve = NULL; - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } @@ -3580,8 +3487,7 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" " currently held\n"); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } /* @@ -3594,8 +3500,7 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" " Nexus is not reservation holder\n"); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out; } /* @@ -3613,8 +3518,7 @@ after_iport_check: " reservation for type: %s\n", core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out; } pr_res_nacl = pr_res_holder->pr_reg_nacl; @@ -3646,13 +3550,11 @@ after_iport_check: dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, iport_ptr); if (!dest_pr_reg) { - ret = core_scsi3_alloc_registration(cmd->se_dev, + if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl, dest_se_deve, iport_ptr, - sa_res_key, 0, aptpl, 2, 1); - if (ret != 0) { + sa_res_key, 0, aptpl, 2, 1)) { spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, @@ -3723,12 +3625,12 @@ after_iport_check: " REGISTER_AND_MOVE\n"); } else { pr_tmpl->pr_aptpl_active = 1; - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &dest_pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Set APTPL Bit Activated for" " REGISTER_AND_MOVE\n"); + } } transport_kunmap_data_sg(cmd); @@ -3743,6 +3645,8 @@ out: if (dest_node_acl) core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_se_tpg); + +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); return ret; } @@ -3760,14 +3664,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) /* * See spc4r17 section 6.14 Table 170 */ -int target_scsi3_emulate_pr_out(struct se_cmd *cmd) +sense_reason_t +target_scsi3_emulate_pr_out(struct se_cmd *cmd) { unsigned char *cdb = &cmd->t_task_cdb[0]; unsigned char *buf; u64 res_key, sa_res_key; int sa, scope, type, aptpl; int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; - int ret; + sense_reason_t ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -3782,28 +3687,22 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; + return TCM_RESERVATION_CONFLICT; } /* * FIXME: A NULL struct se_session pointer means an this is not coming from * a $FABRIC_MOD's nexus, but from internal passthrough ops. */ - if (!cmd->se_sess) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; - } + if (!cmd->se_sess) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; if (cmd->data_length < 24) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + return TCM_INVALID_PARAMETER_LIST; } + /* * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) */ @@ -3812,6 +3711,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) type = (cdb[2] & 0x0f); buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + /* * From PERSISTENT_RESERVE_OUT parameter list (payload) */ @@ -3835,11 +3737,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) /* * SPEC_I_PT=1 is only valid for Service action: REGISTER */ - if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; - } + if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) + return TCM_INVALID_PARAMETER_LIST; /* * From spc4r17 section 6.14: @@ -3854,10 +3753,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) (cmd->data_length != 24)) { pr_warn("SPC-PR: Received PR OUT illegal parameter" " list length: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + return TCM_INVALID_PARAMETER_LIST; } + /* * (core_scsi3_emulate_pro_* function parameters * are defined by spc4r17 Table 174: @@ -3896,12 +3794,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) default: pr_err("Unknown PERSISTENT_RESERVE_OUT service" " action: 0x%02x\n", cdb[1] & 0x1f); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } -out: if (!ret) target_complete_cmd(cmd, GOOD); return ret; @@ -3912,7 +3807,8 @@ out: * * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 */ -static int core_scsi3_pri_read_keys(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_keys(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; @@ -3922,11 +3818,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); @@ -3970,7 +3868,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) * * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 */ -static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_reservation(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; @@ -3981,11 +3880,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4054,7 +3955,8 @@ err: * * See spc4r17 section 6.13.4 Table 165 */ -static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_report_capabilities(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_reservation *pr_tmpl = &dev->t10_pr; @@ -4064,11 +3966,12 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) if (cmd->data_length < 6) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" " %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((add_len << 8) & 0xff); buf[1] = (add_len & 0xff); @@ -4110,7 +4013,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) * * See spc4r17 section 6.13.5 Table 168 and 169 */ -static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_full_status(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_node_acl *se_nacl; @@ -4125,11 +4029,12 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); @@ -4255,9 +4160,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) return 0; } -int target_scsi3_emulate_pr_in(struct se_cmd *cmd) +sense_reason_t +target_scsi3_emulate_pr_in(struct se_cmd *cmd) { - int ret; + sense_reason_t ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -4272,8 +4178,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } switch (cmd->t_task_cdb[1] & 0x1f) { @@ -4292,9 +4197,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) default: pr_err("Unknown PERSISTENT_RESERVE_IN service" " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } if (!ret) @@ -4302,10 +4205,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) return ret; } -int target_check_reservation(struct se_cmd *cmd) +sense_reason_t +target_check_reservation(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - int ret; + sense_reason_t ret; if (!cmd->se_sess) return 0; diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index 7616f26..b4a0042 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache; extern int core_pr_dump_initiator_port(struct t10_pr_registration *, char *, u32); -extern int target_scsi2_reservation_release(struct se_cmd *); -extern int target_scsi2_reservation_reserve(struct se_cmd *); +extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *); +extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *); extern int core_scsi3_alloc_aptpl_registration( struct t10_reservation *, u64, unsigned char *, unsigned char *, u32, @@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, extern void core_scsi3_free_all_registrations(struct se_device *); extern unsigned char *core_scsi3_pr_dump_type(int); -extern int target_scsi3_emulate_pr_in(struct se_cmd *); -extern int target_scsi3_emulate_pr_out(struct se_cmd *); -extern int target_check_reservation(struct se_cmd *cmd); +extern sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *); +extern sense_reason_t target_scsi3_emulate_pr_out(struct se_cmd *); +extern sense_reason_t target_check_reservation(struct se_cmd *); #endif /* TARGET_CORE_PR_H */ diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index aa3e80a..b5c722b 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -60,7 +60,7 @@ static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev) static struct se_subsystem_api pscsi_template; -static int pscsi_execute_cmd(struct se_cmd *cmd); +static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd); static void pscsi_req_done(struct request *, int); /* pscsi_attach_hba(): @@ -642,7 +642,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && (status_byte(result) << 1) == SAM_STAT_GOOD) { if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { - unsigned char *buf = transport_kmap_data_sg(cmd); + unsigned char *buf; + + buf = transport_kmap_data_sg(cmd); + if (!buf) + ; /* XXX: TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE */ if (cdb[0] == MODE_SENSE_10) { if (!(buf[3] & 0x80)) @@ -856,9 +860,9 @@ static inline struct bio *pscsi_get_bio(int sg_num) return bio; } -static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, - u32 sgl_nents, enum dma_data_direction data_direction, - struct bio **hbio) +static sense_reason_t +pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + enum dma_data_direction data_direction, struct bio **hbio) { struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct bio *bio = NULL, *tbio = NULL; @@ -946,7 +950,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, } } - return sgl_nents; + return 0; fail: while (*hbio) { bio = *hbio; @@ -954,8 +958,7 @@ fail: bio->bi_next = NULL; bio_endio(bio, 0); /* XXX: should be error */ } - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* @@ -982,15 +985,13 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb) } } -static int pscsi_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +pscsi_parse_cdb(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - if (cmd->se_cmd_flags & SCF_BIDI) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - return -EINVAL; - } + if (cmd->se_cmd_flags & SCF_BIDI) + return TCM_UNSUPPORTED_SCSI_OPCODE; pscsi_clear_cdb_lun(cdb); @@ -1020,7 +1021,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) } } -static int pscsi_execute_cmd(struct se_cmd *cmd) +static sense_reason_t +pscsi_execute_cmd(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -1029,7 +1031,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) struct pscsi_plugin_task *pt; struct request *req; struct bio *hbio; - int ret; + sense_reason_t ret; /* * Dynamically alloc cdb space, since it may be larger than @@ -1037,8 +1039,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) */ pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL); if (!pt) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } cmd->priv = pt; @@ -1052,24 +1053,21 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) if (!req || IS_ERR(req)) { pr_err("PSCSI: blk_get_request() failed: %ld\n", req ? IS_ERR(req) : -ENOMEM); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto fail; } } else { BUG_ON(!cmd->data_length); ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio); - if (ret < 0) { - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) goto fail; - } req = blk_make_request(pdv->pdv_sd->request_queue, hbio, GFP_KERNEL); if (IS_ERR(req)) { pr_err("pSCSI: blk_make_request() failed\n"); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto fail_free_bio; } } @@ -1100,10 +1098,10 @@ fail_free_bio: bio->bi_next = NULL; bio_endio(bio, 0); /* XXX: should be error */ } - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; fail: kfree(pt); - return -ENOMEM; + return ret; } /* pscsi_get_device_type(): @@ -1152,7 +1150,6 @@ static void pscsi_req_done(struct request *req, int uptodate) pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0], pt->pscsi_result); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); break; } diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 92b1307..126529c 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -275,7 +275,8 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) return NULL; } -static int rd_execute_rw(struct se_cmd *cmd) +static sense_reason_t +rd_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -298,7 +299,7 @@ static int rd_execute_rw(struct se_cmd *cmd) table = rd_get_sg_table(dev, rd_page); if (!table) - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; rd_sg = &table->sg_table[rd_page - table->page_start_offset]; @@ -348,7 +349,7 @@ static int rd_execute_rw(struct se_cmd *cmd) table = rd_get_sg_table(dev, rd_page); if (!table) { sg_miter_stop(&m); - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* since we increment, the first sg entry is correct */ @@ -431,7 +432,8 @@ static struct sbc_ops rd_sbc_ops = { .execute_rw = rd_execute_rw, }; -static int rd_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +rd_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &rd_sbc_ops); } diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a4eb9c5..3929fa2 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -37,7 +37,8 @@ #include "target_core_ua.h" -static int sbc_emulate_readcapacity(struct se_cmd *cmd) +static sense_reason_t +sbc_emulate_readcapacity(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned long long blocks_long = dev->transport->get_blocks(dev); @@ -60,16 +61,18 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd) buf[7] = dev->dev_attrib.block_size & 0xff; rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } -static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) +static sense_reason_t +sbc_emulate_readcapacity_16(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned char *rbuf; @@ -97,10 +100,11 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) buf[14] = 0x80; rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; @@ -129,7 +133,8 @@ int spc_get_write_same_sectors(struct se_cmd *cmd) } EXPORT_SYMBOL(spc_get_write_same_sectors); -static int sbc_emulate_verify(struct se_cmd *cmd) +static sense_reason_t +sbc_emulate_verify(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); return 0; @@ -313,13 +318,14 @@ out: kfree(buf); } -int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) +sense_reason_t +sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; unsigned int size; u32 sectors = 0; - int ret; + sense_reason_t ret; switch (cdb[0]) { case READ_6: @@ -378,9 +384,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->execute_cmd = ops->execute_rw; break; case XDWRITEREAD_10: - if ((cmd->data_direction != DMA_TO_DEVICE) || + if (cmd->data_direction != DMA_TO_DEVICE || !(cmd->se_cmd_flags & SCF_BIDI)) - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; sectors = transport_get_sectors_10(cdb); cmd->t_task_lba = transport_lba_32(cdb); @@ -419,26 +425,26 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) break; case WRITE_SAME_32: if (!ops->execute_write_same) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; sectors = transport_get_sectors_32(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" " supported\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[12]); if (sbc_write_same_supported(dev, &cdb[10]) < 0) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; cmd->execute_cmd = ops->execute_write_same; break; default: pr_err("VARIABLE_LENGTH_CMD service action" " 0x%04x not supported\n", service_action); - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; } break; } @@ -454,7 +460,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) default: pr_err("Unsupported SA: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = (cdb[10] << 24) | (cdb[11] << 16) | (cdb[12] << 8) | cdb[13]; @@ -462,7 +468,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE_16: if (!ops->execute_sync_cache) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; /* * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE @@ -483,42 +489,42 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) */ if (cmd->t_task_lba || sectors) { if (sbc_check_valid_sectors(cmd) < 0) - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } cmd->execute_cmd = ops->execute_sync_cache; break; case UNMAP: if (!ops->execute_unmap) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; size = get_unaligned_be16(&cdb[7]); cmd->execute_cmd = ops->execute_unmap; break; case WRITE_SAME_16: if (!ops->execute_write_same) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; sectors = transport_get_sectors_16(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[2]); if (sbc_write_same_supported(dev, &cdb[1]) < 0) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; cmd->execute_cmd = ops->execute_write_same; break; case WRITE_SAME: if (!ops->execute_write_same) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; sectors = transport_get_sectors_10(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, 1); @@ -529,7 +535,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) * of byte 1 bit 3 UNMAP instead of original reserved field */ if (sbc_write_same_supported(dev, &cdb[1]) < 0) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; cmd->execute_cmd = ops->execute_write_same; break; case VERIFY: @@ -556,7 +562,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) /* reject any command that we don't have a handler for */ if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { unsigned long long end_lba; @@ -566,14 +572,14 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) " big sectors %u exceeds fabric_max_sectors:" " %u\n", cdb[0], sectors, dev->dev_attrib.fabric_max_sectors); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } if (sectors > dev->dev_attrib.hw_max_sectors) { printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" " big sectors %u exceeds backend hw_max_sectors:" " %u\n", cdb[0], sectors, dev->dev_attrib.hw_max_sectors); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } end_lba = dev->transport->get_blocks(dev) + 1; @@ -581,26 +587,13 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) pr_err("cmd exceeds last lba %llu " "(lba %llu, sectors %u)\n", end_lba, cmd->t_task_lba, sectors); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, sectors); } - ret = target_cmd_size_check(cmd, size); - if (ret < 0) - return ret; - - return 0; - -out_unsupported_cdb: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - return -EINVAL; -out_invalid_cdb_field: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return target_cmd_size_check(cmd, size); } EXPORT_SYMBOL(sbc_parse_cdb); diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index f9c2bd0..4b3c183 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -69,7 +69,8 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf) spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); } -static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) +static sense_reason_t +spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) { struct se_lun *lun = cmd->se_lun; struct se_device *dev = cmd->se_dev; @@ -108,7 +109,8 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) } /* unit serial number */ -static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; u16 len = 0; @@ -161,7 +163,8 @@ static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, * Device identification VPD, for a complete list of * DESIGNATOR TYPEs see spc4r17 Table 459. */ -static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; struct se_lun *lun = cmd->se_lun; @@ -406,7 +409,8 @@ check_scsi_name: } /* Extended INQUIRY Data VPD Page */ -static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) { buf[3] = 0x3c; /* Set HEADSUP, ORDSUP, SIMPSUP */ @@ -419,7 +423,8 @@ static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) } /* Block Limits VPD page */ -static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; u32 max_sectors; @@ -490,7 +495,8 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) } /* Block Device Characteristics VPD page */ -static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; @@ -502,7 +508,8 @@ static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) } /* Thin Provisioning VPD */ -static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; @@ -552,11 +559,12 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) return 0; } -static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); +static sense_reason_t +spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); static struct { uint8_t page; - int (*emulate)(struct se_cmd *, unsigned char *); + sense_reason_t (*emulate)(struct se_cmd *, unsigned char *); } evpd_handlers[] = { { .page = 0x00, .emulate = spc_emulate_evpd_00 }, { .page = 0x80, .emulate = spc_emulate_evpd_80 }, @@ -568,7 +576,8 @@ static struct { }; /* supported vital product data pages */ -static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) { int p; @@ -586,14 +595,16 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) return 0; } -static int spc_emulate_inquiry(struct se_cmd *cmd) +static sense_reason_t +spc_emulate_inquiry(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; unsigned char *rbuf; unsigned char *cdb = cmd->t_task_cdb; unsigned char buf[SE_INQUIRY_BUF]; - int p, ret; + sense_reason_t ret; + int p; memset(buf, 0, SE_INQUIRY_BUF); @@ -606,8 +617,7 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) if (cdb[2]) { pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", cdb[2]); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } @@ -624,15 +634,15 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) } pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; out: rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); if (!ret) target_complete_cmd(cmd, GOOD); @@ -834,7 +844,7 @@ static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 bloc return 17; } -static int spc_emulate_modesense(struct se_cmd *cmd) +static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; char *cdb = cmd->t_task_cdb; @@ -851,7 +861,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) int i; map_buf = transport_kmap_data_sg(cmd); - + if (!map_buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we * know we actually allocated a full page. Otherwise, if the @@ -864,8 +875,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd) buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); if (!buf) { transport_kunmap_data_sg(cmd); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } } else { buf = map_buf; @@ -920,9 +930,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd) if (page == 0x3f) { if (subpage != 0x00 && subpage != 0xff) { - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - length = -EINVAL; - goto out; + pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); + kfree(buf); + transport_kunmap_data_sg(cmd); + return TCM_INVALID_CDB_FIELD; } for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) { @@ -958,8 +969,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", page, subpage); - cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; - return -EINVAL; + transport_kunmap_data_sg(cmd); + return TCM_UNKNOWN_MODE_PAGE; set_length: if (ten) @@ -967,7 +978,6 @@ set_length: else buf[0] = length - 1; -out: if (buf != map_buf) { memcpy(map_buf, buf, cmd->data_length); kfree(buf); @@ -978,7 +988,7 @@ out: return 0; } -static int spc_emulate_modeselect(struct se_cmd *cmd) +static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; char *cdb = cmd->t_task_cdb; @@ -993,10 +1003,11 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) int i; buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; if (!pf) { - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } @@ -1011,15 +1022,12 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) goto check_contents; } - cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; - ret = -EINVAL; + ret = TCM_UNKNOWN_MODE_PAGE; goto out; check_contents: - if (memcmp(buf + off, tbuf, length)) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - } + if (memcmp(buf + off, tbuf, length)) + ret = TCM_INVALID_PARAMETER_LIST; out: transport_kunmap_data_sg(cmd); @@ -1029,7 +1037,7 @@ out: return ret; } -static int spc_emulate_request_sense(struct se_cmd *cmd) +static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; unsigned char *rbuf; @@ -1041,19 +1049,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" " supported\n"); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -ENOSYS; + return TCM_INVALID_CDB_FIELD; } rbuf = transport_kmap_data_sg(cmd); - if (cmd->scsi_sense_reason != 0) { - /* - * Out of memory. We will fail with CHECK CONDITION, so - * we must not clear the unit attention condition. - */ - target_complete_cmd(cmd, CHECK_CONDITION); - return 0; - } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* * CURRENT ERROR, UNIT ATTENTION */ @@ -1080,16 +1083,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[7] = 0x0A; } - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } -int spc_emulate_report_luns(struct se_cmd *cmd) +sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) { struct se_dev_entry *deve; struct se_session *sess = cmd->se_sess; @@ -1099,13 +1100,12 @@ int spc_emulate_report_luns(struct se_cmd *cmd) if (cmd->data_length < 16) { pr_warn("REPORT LUNS allocation length %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); if (!buf) - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * If no struct se_session pointer is present, this struct se_cmd is @@ -1153,13 +1153,15 @@ done: } EXPORT_SYMBOL(spc_emulate_report_luns); -static int spc_emulate_testunitready(struct se_cmd *cmd) +static sense_reason_t +spc_emulate_testunitready(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); return 0; } -int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) +sense_reason_t +spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -1300,9 +1302,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" " 0x%02x, sending CHECK_CONDITION.\n", cmd->se_tfo->get_fabric_name(), cdb[0]); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - return -EINVAL; + return TCM_UNSUPPORTED_SCSI_OPCODE; } return 0; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c4c931b..98044bf 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -557,7 +557,8 @@ static void target_complete_failure_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - transport_generic_request_failure(cmd); + transport_generic_request_failure(cmd, + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE); } /* @@ -625,7 +626,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) complete(&cmd->t_transport_stop_comp); return; } else if (cmd->transport_state & CMD_T_FAILED) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; INIT_WORK(&cmd->work, target_complete_failure_work); } else { INIT_WORK(&cmd->work, target_complete_ok_work); @@ -976,7 +976,8 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83) } EXPORT_SYMBOL(transport_set_vpd_ident); -int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) +sense_reason_t +target_cmd_size_check(struct se_cmd *cmd, unsigned int size) { struct se_device *dev = cmd->se_dev; @@ -991,7 +992,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) if (cmd->data_direction == DMA_TO_DEVICE) { pr_err("Rejecting underflow/overflow" " WRITE data\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } /* * Reject READ_* or WRITE_* with overflow/underflow for @@ -1002,7 +1003,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) " CDB on non 512-byte sector setup subsystem" " plugin: %s\n", dev->transport->name); /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } /* * For the overflow case keep the existing fabric provided @@ -1022,10 +1023,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) return 0; -out_invalid_cdb_field: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; } /* @@ -1065,7 +1062,8 @@ void transport_init_se_cmd( } EXPORT_SYMBOL(transport_init_se_cmd); -static int transport_check_alloc_task_attr(struct se_cmd *cmd) +static sense_reason_t +transport_check_alloc_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1079,7 +1077,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) if (cmd->sam_task_attr == MSG_ACA_TAG) { pr_debug("SAM Task Attribute ACA" " emulation is not supported\n"); - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } /* * Used to determine when ORDERED commands should go from @@ -1093,17 +1091,12 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) return 0; } -/* target_setup_cmd_from_cdb(): - * - * Called from fabric RX Thread. - */ -int target_setup_cmd_from_cdb( - struct se_cmd *cmd, - unsigned char *cdb) +sense_reason_t +target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) { struct se_device *dev = cmd->se_dev; unsigned long flags; - int ret; + sense_reason_t ret; /* * Ensure that the received CDB is less than the max (252 + 8) bytes @@ -1113,9 +1106,7 @@ int target_setup_cmd_from_cdb( pr_err("Received SCSI CDB with command_size: %d that" " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } /* * If the received CDB is larger than TCM_MAX_COMMAND_SIZE, @@ -1130,10 +1121,7 @@ int target_setup_cmd_from_cdb( " %u > sizeof(cmd->__t_task_cdb): %lu ops\n", scsi_command_size(cdb), (unsigned long)sizeof(cmd->__t_task_cdb)); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_OUT_OF_RESOURCES; } } else cmd->t_task_cdb = &cmd->__t_task_cdb[0]; @@ -1145,50 +1133,30 @@ int target_setup_cmd_from_cdb( /* * Check for an existing UNIT ATTENTION condition */ - if (core_scsi3_ua_check(cmd, cdb) < 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION; - return -EINVAL; - } + ret = target_scsi3_ua_check(cmd); + if (ret) + return ret; ret = target_alua_state_check(cmd); - if (ret) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - if (ret > 0) - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; - else - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } + if (ret) + return ret; - /* - * Check status for SPC-3 Persistent Reservations - */ ret = target_check_reservation(cmd); - if (ret) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + if (ret) return ret; - } ret = dev->transport->parse_cdb(cmd); - if (ret < 0) + if (ret) + return ret; + + ret = transport_check_alloc_task_attr(cmd); + if (ret) return ret; spin_lock_irqsave(&cmd->t_state_lock, flags); cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; spin_unlock_irqrestore(&cmd->t_state_lock, flags); - /* - * Check for SAM Task Attribute Emulation - */ - if (transport_check_alloc_task_attr(cmd) < 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } spin_lock(&cmd->se_lun->lun_sep_lock); if (cmd->se_lun->lun_sep) cmd->se_lun->lun_sep->sep_stats.cmd_pdus++; @@ -1204,7 +1172,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb); int transport_handle_cdb_direct( struct se_cmd *cmd) { - int ret; + sense_reason_t ret; if (!cmd->se_lun) { dump_stack(); @@ -1234,13 +1202,41 @@ int transport_handle_cdb_direct( * and call transport_generic_request_failure() if necessary.. */ ret = transport_generic_new_cmd(cmd); - if (ret < 0) - transport_generic_request_failure(cmd); - + if (ret) + transport_generic_request_failure(cmd, ret); return 0; } EXPORT_SYMBOL(transport_handle_cdb_direct); +static sense_reason_t +transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, + u32 sgl_count, struct scatterlist *sgl_bidi, u32 sgl_bidi_count) +{ + if (!sgl || !sgl_count) + return 0; + + /* + * Reject SCSI data overflow with map_mem_to_cmd() as incoming + * scatterlists already have been set to follow what the fabric + * passes for the original expected data transfer length. + */ + if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { + pr_warn("Rejecting SCSI DATA overflow for fabric using" + " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); + return TCM_INVALID_CDB_FIELD; + } + + cmd->t_data_sg = sgl; + cmd->t_data_nents = sgl_count; + + if (sgl_bidi && sgl_bidi_count) { + cmd->t_bidi_data_sg = sgl_bidi; + cmd->t_bidi_data_nents = sgl_bidi_count; + } + cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; + return 0; +} + /* * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized * se_cmd + use pre-allocated SGL memory. @@ -1273,7 +1269,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess struct scatterlist *sgl_bidi, u32 sgl_bidi_count) { struct se_portal_group *se_tpg; - int rc; + sense_reason_t rc; + int ret; se_tpg = se_sess->se_tpg; BUG_ON(!se_tpg); @@ -1294,9 +1291,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess * for fabrics using TARGET_SCF_ACK_KREF that expect a second * kref_put() to happen during fabric packet acknowledgement. */ - rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); - if (rc) - return rc; + ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); + if (ret) + return ret; /* * Signal bidirectional data payloads to target-core */ @@ -1305,16 +1302,16 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess /* * Locate se_lun pointer and attach it to struct se_cmd */ - if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { - transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); + rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun); + if (rc) { + transport_send_check_condition_and_sense(se_cmd, rc, 0); target_put_sess_cmd(se_sess, se_cmd); return 0; } rc = target_setup_cmd_from_cdb(se_cmd, cdb); if (rc != 0) { - transport_generic_request_failure(se_cmd); + transport_generic_request_failure(se_cmd, rc); return 0; } /* @@ -1349,7 +1346,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count, sgl_bidi, sgl_bidi_count); if (rc != 0) { - transport_generic_request_failure(se_cmd); + transport_generic_request_failure(se_cmd, rc); return 0; } } @@ -1495,16 +1492,17 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags) /* * Handle SAM-esque emulation for generic transport request failures. */ -void transport_generic_request_failure(struct se_cmd *cmd) +void transport_generic_request_failure(struct se_cmd *cmd, + sense_reason_t sense_reason) { int ret = 0; pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" " CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), cmd->t_task_cdb[0]); - pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n", + pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n", cmd->se_tfo->get_cmd_state(cmd), - cmd->t_state, cmd->scsi_sense_reason); + cmd->t_state, sense_reason); pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n", (cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_STOP) != 0, @@ -1515,7 +1513,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) */ transport_complete_task_attr(cmd); - switch (cmd->scsi_sense_reason) { + switch (sense_reason) { case TCM_NON_EXISTENT_LUN: case TCM_UNSUPPORTED_SCSI_OPCODE: case TCM_INVALID_CDB_FIELD: @@ -1528,6 +1526,9 @@ void transport_generic_request_failure(struct se_cmd *cmd) case TCM_CHECK_CONDITION_UNIT_ATTENTION: case TCM_CHECK_CONDITION_NOT_READY: break; + case TCM_OUT_OF_RESOURCES: + sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + break; case TCM_RESERVATION_CONFLICT: /* * No SENSE Data payload for this case, set SCSI Status @@ -1555,13 +1556,12 @@ void transport_generic_request_failure(struct se_cmd *cmd) goto check_stop; default: pr_err("Unknown transport error for CDB 0x%02x: %d\n", - cmd->t_task_cdb[0], cmd->scsi_sense_reason); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + cmd->t_task_cdb[0], sense_reason); + sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; break; } - ret = transport_send_check_condition_and_sense(cmd, - cmd->scsi_sense_reason, 0); + ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0); if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; @@ -1579,21 +1579,21 @@ EXPORT_SYMBOL(transport_generic_request_failure); static void __target_execute_cmd(struct se_cmd *cmd) { - int error = 0; + sense_reason_t ret; spin_lock_irq(&cmd->t_state_lock); cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT); spin_unlock_irq(&cmd->t_state_lock); - if (cmd->execute_cmd) - error = cmd->execute_cmd(cmd); - - if (error) { - spin_lock_irq(&cmd->t_state_lock); - cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); - spin_unlock_irq(&cmd->t_state_lock); + if (cmd->execute_cmd) { + ret = cmd->execute_cmd(cmd); + if (ret) { + spin_lock_irq(&cmd->t_state_lock); + cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); + spin_unlock_irq(&cmd->t_state_lock); - transport_generic_request_failure(cmd); + transport_generic_request_failure(cmd, ret); + } } } @@ -1987,53 +1987,6 @@ out_busy: spin_unlock_irqrestore(&cmd->t_state_lock, flags); } -/* - * transport_generic_map_mem_to_cmd - Use fabric-alloced pages instead of - * allocating in the core. - * @cmd: Associated se_cmd descriptor - * @mem: SGL style memory for TCM WRITE / READ - * @sg_mem_num: Number of SGL elements - * @mem_bidi_in: SGL style memory for TCM BIDI READ - * @sg_mem_bidi_num: Number of BIDI READ SGL elements - * - * Return: nonzero return cmd was rejected for -ENOMEM or inproper usage - * of parameters. - */ -int transport_generic_map_mem_to_cmd( - struct se_cmd *cmd, - struct scatterlist *sgl, - u32 sgl_count, - struct scatterlist *sgl_bidi, - u32 sgl_bidi_count) -{ - if (!sgl || !sgl_count) - return 0; - - /* - * Reject SCSI data overflow with map_mem_to_cmd() as incoming - * scatterlists already have been set to follow what the fabric - * passes for the original expected data transfer length. - */ - if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { - pr_warn("Rejecting SCSI DATA overflow for fabric using" - " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - - cmd->t_data_sg = sgl; - cmd->t_data_nents = sgl_count; - - if (sgl_bidi && sgl_bidi_count) { - cmd->t_bidi_data_sg = sgl_bidi; - cmd->t_bidi_data_nents = sgl_bidi_count; - } - cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; - return 0; -} -EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); - void *transport_kmap_data_sg(struct se_cmd *cmd) { struct scatterlist *sg = cmd->t_data_sg; @@ -2054,10 +2007,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) /* >1 page. use vmap */ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); - if (!pages) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!pages) return NULL; - } /* convert sg[] to pages[] */ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2066,10 +2017,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); kfree(pages); - if (!cmd->t_data_vmap) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!cmd->t_data_vmap) return NULL; - } return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } @@ -2135,7 +2084,8 @@ out: * might not have the payload yet, so notify the fabric via a call to * ->write_pending instead. Otherwise place it on the execution queue. */ -int transport_generic_new_cmd(struct se_cmd *cmd) +sense_reason_t +transport_generic_new_cmd(struct se_cmd *cmd) { int ret = 0; @@ -2148,7 +2098,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) cmd->data_length) { ret = transport_generic_get_mem(cmd); if (ret < 0) - goto out_fail; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } atomic_inc(&cmd->t_fe_count); @@ -2174,14 +2124,11 @@ int transport_generic_new_cmd(struct se_cmd *cmd) if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; - if (ret < 0) - return ret; - return 1; + /* fabric drivers should only return -EAGAIN or -ENOMEM as error */ + WARN_ON(ret); + + return 0; -out_fail: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; queue_full: pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); cmd->t_state = TRANSPORT_COMPLETE_QF_WP; @@ -2625,10 +2572,9 @@ static int transport_get_sense_codes( return 0; } -int transport_send_check_condition_and_sense( - struct se_cmd *cmd, - u8 reason, - int from_transport) +int +transport_send_check_condition_and_sense(struct se_cmd *cmd, + sense_reason_t reason, int from_transport) { unsigned char *buffer = cmd->sense_buffer; unsigned long flags; diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 59c95ee..60c8f41 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -38,9 +38,8 @@ #include "target_core_pr.h" #include "target_core_ua.h" -int core_scsi3_ua_check( - struct se_cmd *cmd, - unsigned char *cdb) +sense_reason_t +target_scsi3_ua_check(struct se_cmd *cmd) { struct se_dev_entry *deve; struct se_session *sess = cmd->se_sess; @@ -71,16 +70,14 @@ int core_scsi3_ua_check( * was received, then the device server shall process the command * and either: */ - switch (cdb[0]) { + switch (cmd->t_task_cdb[0]) { case INQUIRY: case REPORT_LUNS: case REQUEST_SENSE: return 0; default: - return -EINVAL; + return TCM_CHECK_CONDITION_UNIT_ATTENTION; } - - return -EINVAL; } int core_scsi3_ua_allocate( diff --git a/drivers/target/target_core_ua.h b/drivers/target/target_core_ua.h index 6e6b034..0204952 100644 --- a/drivers/target/target_core_ua.h +++ b/drivers/target/target_core_ua.h @@ -26,7 +26,7 @@ extern struct kmem_cache *se_ua_cache; -extern int core_scsi3_ua_check(struct se_cmd *, unsigned char *); +extern sense_reason_t target_scsi3_ua_check(struct se_cmd *); extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8); extern void core_scsi3_ua_release_all(struct se_dev_entry *); extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *); diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index aa31692..6a69bf5 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c @@ -541,10 +541,6 @@ static void tcm_vhost_submission_work(struct work_struct *work) if (tv_cmd->tvc_sgl_count) { sg_ptr = tv_cmd->tvc_sgl; - /* - * For BIDI commands, pass in the extra READ buffer - * to transport_generic_map_mem_to_cmd() below.. - */ /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ #if 0 if (se_cmd->se_cmd_flags & SCF_BIDI) { diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index e57f738..aa86809 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -31,17 +31,17 @@ struct se_subsystem_api { struct scatterlist *, unsigned char *); - int (*parse_cdb)(struct se_cmd *cmd); + sense_reason_t (*parse_cdb)(struct se_cmd *cmd); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); unsigned char *(*get_sense_buffer)(struct se_cmd *); }; struct sbc_ops { - int (*execute_rw)(struct se_cmd *cmd); - int (*execute_sync_cache)(struct se_cmd *cmd); - int (*execute_write_same)(struct se_cmd *cmd); - int (*execute_unmap)(struct se_cmd *cmd); + sense_reason_t (*execute_rw)(struct se_cmd *cmd); + sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); + sense_reason_t (*execute_write_same)(struct se_cmd *cmd); + sense_reason_t (*execute_unmap)(struct se_cmd *cmd); }; int transport_subsystem_register(struct se_subsystem_api *); @@ -49,11 +49,11 @@ void transport_subsystem_release(struct se_subsystem_api *); void target_complete_cmd(struct se_cmd *, u8); -int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); -int spc_emulate_report_luns(struct se_cmd *cmd); +sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); +sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd); -int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); +sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); u32 sbc_get_device_rev(struct se_device *dev); u32 sbc_get_device_type(struct se_device *dev); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 11b0a68..5350f6e 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -144,8 +144,6 @@ enum se_cmd_flags_table { SCF_EMULATED_TASK_SENSE = 0x00000004, SCF_SCSI_DATA_CDB = 0x00000008, SCF_SCSI_TMR_CDB = 0x00000010, - SCF_SCSI_CDB_EXCEPTION = 0x00000020, - SCF_SCSI_RESERVATION_CONFLICT = 0x00000040, SCF_FUA = 0x00000080, SCF_SE_LUN_CMD = 0x00000100, SCF_BIDI = 0x00000400, @@ -167,27 +165,32 @@ enum transport_lunflags_table { }; /* - * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason + * Used by transport_send_check_condition_and_sense() * to signal which ASC/ASCQ sense payload should be built. */ +typedef unsigned __bitwise__ sense_reason_t; + enum tcm_sense_reason_table { - TCM_NON_EXISTENT_LUN = 0x01, - TCM_UNSUPPORTED_SCSI_OPCODE = 0x02, - TCM_INCORRECT_AMOUNT_OF_DATA = 0x03, - TCM_UNEXPECTED_UNSOLICITED_DATA = 0x04, - TCM_SERVICE_CRC_ERROR = 0x05, - TCM_SNACK_REJECTED = 0x06, - TCM_SECTOR_COUNT_TOO_MANY = 0x07, - TCM_INVALID_CDB_FIELD = 0x08, - TCM_INVALID_PARAMETER_LIST = 0x09, - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = 0x0a, - TCM_UNKNOWN_MODE_PAGE = 0x0b, - TCM_WRITE_PROTECTED = 0x0c, - TCM_CHECK_CONDITION_ABORT_CMD = 0x0d, - TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, - TCM_CHECK_CONDITION_NOT_READY = 0x0f, - TCM_RESERVATION_CONFLICT = 0x10, - TCM_ADDRESS_OUT_OF_RANGE = 0x11, +#define R(x) (__force sense_reason_t )(x) + TCM_NON_EXISTENT_LUN = R(0x01), + TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02), + TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03), + TCM_UNEXPECTED_UNSOLICITED_DATA = R(0x04), + TCM_SERVICE_CRC_ERROR = R(0x05), + TCM_SNACK_REJECTED = R(0x06), + TCM_SECTOR_COUNT_TOO_MANY = R(0x07), + TCM_INVALID_CDB_FIELD = R(0x08), + TCM_INVALID_PARAMETER_LIST = R(0x09), + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = R(0x0a), + TCM_UNKNOWN_MODE_PAGE = R(0x0b), + TCM_WRITE_PROTECTED = R(0x0c), + TCM_CHECK_CONDITION_ABORT_CMD = R(0x0d), + TCM_CHECK_CONDITION_UNIT_ATTENTION = R(0x0e), + TCM_CHECK_CONDITION_NOT_READY = R(0x0f), + TCM_RESERVATION_CONFLICT = R(0x10), + TCM_ADDRESS_OUT_OF_RANGE = R(0x11), + TCM_OUT_OF_RESOURCES = R(0x12), +#undef R }; enum target_sc_flags_table { @@ -407,7 +410,6 @@ struct se_cmd { u8 scsi_status; u8 scsi_asc; u8 scsi_ascq; - u8 scsi_sense_reason; u16 scsi_sense_length; /* Delay for ALUA Active/NonOptimized state access in milliseconds */ int alua_nonop_delay; @@ -445,7 +447,7 @@ struct se_cmd { struct completion cmd_wait_comp; struct kref cmd_kref; struct target_core_fabric_ops *se_tfo; - int (*execute_cmd)(struct se_cmd *); + sense_reason_t (*execute_cmd)(struct se_cmd *); void (*transport_complete_callback)(struct se_cmd *); unsigned char *t_task_cdb; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 81ddb4a..9087b20 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -98,8 +98,8 @@ void transport_deregister_session(struct se_session *); void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, struct se_session *, u32, int, int, unsigned char *); -int transport_lookup_cmd_lun(struct se_cmd *, u32); -int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); +sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32); +sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, unsigned char *, unsigned char *, u32, u32, int, int, int, struct scatterlist *, u32, struct scatterlist *, u32); @@ -110,9 +110,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, void *fabric_tmr_ptr, unsigned char tm_type, gfp_t, unsigned int, int); int transport_handle_cdb_direct(struct se_cmd *); -int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, - struct scatterlist *, u32, struct scatterlist *, u32); -int transport_generic_new_cmd(struct se_cmd *); +sense_reason_t transport_generic_new_cmd(struct se_cmd *); void target_execute_cmd(struct se_cmd *cmd); @@ -120,7 +118,8 @@ void transport_generic_free_cmd(struct se_cmd *, int); bool transport_wait_for_tasks(struct se_cmd *); int transport_check_aborted_status(struct se_cmd *, int); -int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); +int transport_send_check_condition_and_sense(struct se_cmd *, + sense_reason_t, int); int target_put_sess_cmd(struct se_session *, struct se_cmd *); void target_sess_cmd_list_set_waiting(struct se_session *); @@ -131,7 +130,7 @@ int core_alua_check_nonop_delay(struct se_cmd *); int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t); void core_tmr_release_req(struct se_tmr_req *); int transport_generic_handle_tmr(struct se_cmd *); -void transport_generic_request_failure(struct se_cmd *); +void transport_generic_request_failure(struct se_cmd *, sense_reason_t); int transport_lookup_tmr_lun(struct se_cmd *, u32); struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, -- cgit v0.10.2 From a2e85d18146857ffddea4dfe3b245055af8e3db3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 6 Nov 2012 12:36:12 -0800 Subject: target: Fix incorrect inversion of TPGS_EXPLICT_ALUA check Fix a bug introduced with patch "target: pass sense_reason as a return value" in for-3.8 code where only target port groups with TPGS_EXPLICT_ALUA set need to be allowed to perform explictly ALUA. Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index e62dc52..4c8eea2 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -251,7 +251,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) } spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); - if (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) { + if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)) { pr_debug("Unable to process SET_TARGET_PORT_GROUPS" " while TPGS_EXPLICT_ALUA is disabled\n"); rc = TCM_UNSUPPORTED_SCSI_OPCODE; -- cgit v0.10.2 From b69c1fcf0a7cb2b7dff12ce4e8506b395431a52c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 6 Nov 2012 15:43:53 -0800 Subject: target: Fix possible TFO->write_pending() sense_reason_t silent WRITE corruption This patch fixes a possible case in transport_generic_new_cmd() where a failure from TFO->write_pending() from a fabric module return something other than -EAGAIN or -ENOMEM would cause a failed WRITE to silently succeed. Go ahead and return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE for this special case instead of only just making noise with WARN_ON(). (v2: Fix incorrect exception return for all cases) Cc: Christoph Hellwig Cc: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 98044bf..63d7848 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2127,7 +2127,7 @@ transport_generic_new_cmd(struct se_cmd *cmd) /* fabric drivers should only return -EAGAIN or -ENOMEM as error */ WARN_ON(ret); - return 0; + return (!ret) ? 0 : TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; queue_full: pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); -- cgit v0.10.2 From bb7a8c8eb9678666fb05f3bc542581365399a161 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 6 Nov 2012 15:46:25 -0800 Subject: target: Fix exception path pr_reg put regression for PR RELEASE Fix a regression bug in core_scsi3_emulate_pro_release() where should still be getting released via core_scsi3_put_pr_reg() during No persistent reservation, with returing GOOD status. Use goto statement here to follow converted code from hch. Cc: Christoph Hellwig Cc: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index ffbe0ea..d7101a4 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2604,7 +2604,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, * No persistent reservation, return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - return 0; + goto out_put_pr_reg; } if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) -- cgit v0.10.2 From 998866b0740f128fd2c107c167c8385406dadae0 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 5 Nov 2012 18:02:40 -0800 Subject: iscsi-target: Fix potential deadlock on lock taken in timer We need to disable BHs when taking sess_idr_lock because the iscsit_handle_time2retain_timeout() timer function takes se_tpg->session_lock, and iscsit_close_session() nests sess_idr_lock inside se_tpg->session_lock. So if the timer can run inside sess_idr_lock, we have a potential AB-BA deadlock. Fix this by disabling BHs when taking sess_idr_lock. This was found because of a lockdep warning, but it looks like a real (if highly theoretical) deadlock. In any case avoiding lockdep spew so that we can find other issues is a worthy cause. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index f8dbec0..3f34ecf 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -254,9 +254,9 @@ static int iscsi_login_zero_tsih_s1( kfree(sess); return -ENOMEM; } - spin_lock(&sess_idr_lock); + spin_lock_bh(&sess_idr_lock); ret = idr_get_new(&sess_idr, NULL, &sess->session_index); - spin_unlock(&sess_idr_lock); + spin_unlock_bh(&sess_idr_lock); if (ret < 0) { pr_err("idr_get_new() for sess_idr failed\n"); -- cgit v0.10.2 From 64c13330a38935120501b19c97a3e6095747c7a1 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Mon, 5 Nov 2012 18:02:41 -0800 Subject: iscsi-target: Fix bug in handling of ExpStatSN ACK during u32 wrap-around This patch fixes a bug in the hanlding of initiator provided ExpStatSN and individual iscsi_cmd->stat_sn comparision during iscsi_conn->stat_sn wrap-around within iscsit_ack_from_expstatsn() code. This bug would manifest itself as iscsi_cmd descriptors not being Acked by a lower ExpStatSn, causing them to be leaked until an iSCSI connection or session reinstatement event occurs to release all commands. Also fix up two other uses of incorrect CmdSN SNA comparison to use wrapper usage from include/scsi/iscsi_proto.h. Signed-off-by: Steve Hodgson Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 093fb60..4ad14ac 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -735,7 +735,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn) list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { spin_lock(&cmd->istate_lock); if ((cmd->i_state == ISTATE_SENT_STATUS) && - (cmd->stat_sn < exp_statsn)) { + iscsi_sna_lt(cmd->stat_sn, exp_statsn)) { cmd->i_state = ISTATE_REMOVE; spin_unlock(&cmd->istate_lock); iscsit_add_cmd_to_immediate_queue(cmd, conn, diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 17d8c20..9ac4c151 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c @@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) * made generic here. */ if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && - (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) { + iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { list_del(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd); diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c index 4a99820..9d4417a 100644 --- a/drivers/target/iscsi/iscsi_target_tmr.c +++ b/drivers/target/iscsi/iscsi_target_tmr.c @@ -50,8 +50,8 @@ u8 iscsit_tmr_abort_task( if (!ref_cmd) { pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" " %hu.\n", hdr->rtt, conn->cid); - return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn && - be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ? + return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) && + iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ? ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; } if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { -- cgit v0.10.2 From 1c5c12c666fda27c7c494b34934a0a0631a48130 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 5 Nov 2012 18:02:42 -0800 Subject: iscsi-target: Always send a response before terminating iSCSI connection There are some cases, for example when the initiator sends an out-of-bounds ErrorRecoveryLevel value, where the iSCSI target terminates the connection without sending back any error. Audit the login path and add appropriate iscsit_tx_login_rsp() calls to make sure this doesn't happen. Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 3f34ecf..7bf9ccc 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -127,13 +127,13 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) initiatorname_param = iscsi_find_param_from_key( INITIATORNAME, conn->param_list); - if (!initiatorname_param) - return -1; - sessiontype_param = iscsi_find_param_from_key( SESSIONTYPE, conn->param_list); - if (!sessiontype_param) + if (!initiatorname_param || !sessiontype_param) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_MISSING_FIELDS); return -1; + } sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index e9053a0..9d902ae 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -620,8 +620,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log login->req_buf, payload_length, conn); - if (ret < 0) + if (ret < 0) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_INIT_ERR); return -1; + } if (login->first_request) if (iscsi_target_check_first_request(conn, login) < 0) @@ -636,8 +639,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log login->rsp_buf, &login->rsp_length, conn->param_list); - if (ret < 0) + if (ret < 0) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_INIT_ERR); return -1; + } if (!login->auth_complete && ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { -- cgit v0.10.2 From 314da1aa57c3f2be8a07f3d944a541b595e8cb7d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 5 Nov 2012 15:04:34 -0800 Subject: sbp-target: remove depends on CONFIG_EXPERIMENTAL The CONFIG_EXPERIMENTAL config item has not carried much meaning for a while now and is almost always enabled by default. As agreed during the Linux kernel summit, remove it from any "depends on" lines in Kconfigs. CC: Chris Boot CC: "Nicholas A. Bellinger" Signed-off-by: Kees Cook Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/sbp/Kconfig b/drivers/target/sbp/Kconfig index 132da54..1614bc7 100644 --- a/drivers/target/sbp/Kconfig +++ b/drivers/target/sbp/Kconfig @@ -1,6 +1,6 @@ config SBP_TARGET tristate "FireWire SBP-2 fabric module" - depends on FIREWIRE && EXPERIMENTAL + depends on FIREWIRE help Say Y or M here to enable SCSI target functionality over FireWire. This enables you to expose SCSI devices to other nodes on the FireWire -- cgit v0.10.2 From 1920ed61fbbbb38919edfb2427b0b1fd4e4ad8d9 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 6 Nov 2012 20:59:41 -0800 Subject: target: Change sbc_emulate_noop to return sense_reason_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As reported by Fengguang Wu + 0 day build team, the sense_reason_t conversion in for-next did not catch the recent sbc_emulate_noop() addition in mainline, producing the following build warning in auto-next: drivers/target/target_core_sbc.c: In function ‘sbc_parse_cdb’: drivers/target/target_core_sbc.c:555: warning: assignment from incompatible pointer type Go ahead and remove duplicate sbc_emulate_verify(), and change VERIFY to use sbc_emulate_noop() as well. Reported-by: Fengguang Wu Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 3929fa2..b802421 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -134,13 +134,7 @@ int spc_get_write_same_sectors(struct se_cmd *cmd) EXPORT_SYMBOL(spc_get_write_same_sectors); static sense_reason_t -sbc_emulate_verify(struct se_cmd *cmd) -{ - target_complete_cmd(cmd, GOOD); - return 0; -} - -static int sbc_emulate_noop(struct se_cmd *cmd) +sbc_emulate_noop(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); return 0; @@ -540,7 +534,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) break; case VERIFY: size = 0; - cmd->execute_cmd = sbc_emulate_verify; + cmd->execute_cmd = sbc_emulate_noop; break; case REZERO_UNIT: case SEEK_6: -- cgit v0.10.2 From cd063bef414c51d79b9c6ea7a8ef8f9d319529bc Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 7 Nov 2012 20:01:10 -0800 Subject: target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops This patch adds a new sbc_ops->execute_write_same_unmap() caller for use with WRITE_SAME w/ UNMAP=1, and performs the ->execute_cmd() setup based this bit within sbc_setup_write_same() code. Also, makes the changes in sbc_parse_cdb() to handle a sense_reason_t return from sbc_setup_write_same() on error. Reported-by: Christoph Hellwig Cc: Martin K. Petersen Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index b802421..a5a8f46 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -235,26 +235,30 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; } -static int sbc_write_same_supported(struct se_device *dev, - unsigned char *flags) +static sense_reason_t +sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) { if ((flags[0] & 0x04) || (flags[0] & 0x02)) { pr_err("WRITE_SAME PBDATA and LBDATA" " bits not supported for Block Discard" " Emulation\n"); - return -ENOSYS; + return TCM_UNSUPPORTED_SCSI_OPCODE; } - /* - * Currently for the emulated case we only accept - * tpws with the UNMAP=1 bit set. + * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting + * translated into block discard requests within backend code. */ - if (!(flags[0] & 0x08)) { - pr_err("WRITE_SAME w/o UNMAP bit not" - " supported for Block Discard Emulation\n"); - return -ENOSYS; + if (flags[0] & 0x08) { + if (!ops->execute_write_same_unmap) + return TCM_UNSUPPORTED_SCSI_OPCODE; + + cmd->execute_cmd = ops->execute_write_same_unmap; + return 0; } + if (!ops->execute_write_same) + return TCM_UNSUPPORTED_SCSI_OPCODE; + cmd->execute_cmd = ops->execute_write_same; return 0; } @@ -418,9 +422,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->se_cmd_flags |= SCF_FUA; break; case WRITE_SAME_32: - if (!ops->execute_write_same) - return TCM_UNSUPPORTED_SCSI_OPCODE; - sectors = transport_get_sectors_32(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" @@ -431,9 +432,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[12]); - if (sbc_write_same_supported(dev, &cdb[10]) < 0) - return TCM_UNSUPPORTED_SCSI_OPCODE; - cmd->execute_cmd = ops->execute_write_same; + ret = sbc_setup_write_same(cmd, &cdb[10], ops); + if (ret < 0) + return ret; break; default: pr_err("VARIABLE_LENGTH_CMD service action" @@ -495,9 +496,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->execute_cmd = ops->execute_unmap; break; case WRITE_SAME_16: - if (!ops->execute_write_same) - return TCM_UNSUPPORTED_SCSI_OPCODE; - sectors = transport_get_sectors_16(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); @@ -507,14 +505,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[2]); - if (sbc_write_same_supported(dev, &cdb[1]) < 0) - return TCM_UNSUPPORTED_SCSI_OPCODE; - cmd->execute_cmd = ops->execute_write_same; + ret = sbc_setup_write_same(cmd, &cdb[1], ops); + if (ret < 0) + return ret; break; case WRITE_SAME: - if (!ops->execute_write_same) - return TCM_UNSUPPORTED_SCSI_OPCODE; - sectors = transport_get_sectors_10(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); @@ -528,9 +523,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) * Follow sbcr26 with WRITE_SAME (10) and check for the existence * of byte 1 bit 3 UNMAP instead of original reserved field */ - if (sbc_write_same_supported(dev, &cdb[1]) < 0) - return TCM_UNSUPPORTED_SCSI_OPCODE; - cmd->execute_cmd = ops->execute_write_same; + ret = sbc_setup_write_same(cmd, &cdb[1], ops); + if (ret < 0) + return ret; break; case VERIFY: size = 0; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index aa86809..3393ab1 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -41,6 +41,7 @@ struct sbc_ops { sense_reason_t (*execute_rw)(struct se_cmd *cmd); sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); sense_reason_t (*execute_write_same)(struct se_cmd *cmd); + sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd); sense_reason_t (*execute_unmap)(struct se_cmd *cmd); }; -- cgit v0.10.2 From 773cbaf7460aa58c67d4dca83c3f8bca10323bbe Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 15 Nov 2012 11:02:49 -0800 Subject: target: Add/check max_write_same_len device attribute + update block limits VPD This patch adds a new max_write_same_len device attribute for use with WRITE_SAME w/ UNMAP=0 backend emulation. This can be useful for lowering the default backend value (IBLOCK uses 0xFFFF). Also, update block limits VPD emulation code in spc_emulate_evpd_b0() to report MAXIMUM WRITE SAME LENGTH, and enforce max_write_same_len during sbc_parse() -> sbc_setup_write_same() CDB sanity checking for all emulated WRITE_SAME w/ UNMAP=0 cases. (Robert: Move max_write_same_len check in sbc_setup_write_same() to check both WRITE_SAME w/ UNMAP=1 and w/ UNMAP=0 cases) Cc: Christoph Hellwig Cc: Martin K. Petersen Cc: Robert Elliott Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 7b473b6..2b14164 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -676,6 +676,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(unmap_granularity_alignment); SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(max_write_same_len); +SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR); + CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); static struct configfs_attribute *target_core_dev_attrib_attrs[] = { @@ -701,6 +704,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { &target_core_dev_attrib_max_unmap_block_desc_count.attr, &target_core_dev_attrib_unmap_granularity.attr, &target_core_dev_attrib_unmap_granularity_alignment.attr, + &target_core_dev_attrib_max_write_same_len.attr, NULL, }; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 599374e..54439bc 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -706,6 +706,16 @@ int se_dev_set_unmap_granularity_alignment( return 0; } +int se_dev_set_max_write_same_len( + struct se_device *dev, + u32 max_write_same_len) +{ + dev->dev_attrib.max_write_same_len = max_write_same_len; + pr_debug("dev[%p]: Set max_write_same_len: %u\n", + dev, dev->dev_attrib.max_write_same_len); + return 0; +} + int se_dev_set_emulate_dpo(struct se_device *dev, int flag) { if (flag != 0 && flag != 1) { @@ -1393,6 +1403,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; dev->dev_attrib.unmap_granularity_alignment = DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; + dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index bc9c522..93e9c1f 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -24,6 +24,7 @@ int se_dev_set_max_unmap_lba_count(struct se_device *, u32); int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); int se_dev_set_unmap_granularity(struct se_device *, u32); int se_dev_set_unmap_granularity_alignment(struct se_device *, u32); +int se_dev_set_max_write_same_len(struct se_device *, u32); int se_dev_set_emulate_dpo(struct se_device *, int); int se_dev_set_emulate_fua_write(struct se_device *, int); int se_dev_set_emulate_fua_read(struct se_device *, int); diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a5a8f46..45e11d0 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -238,12 +238,19 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) static sense_reason_t sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) { + unsigned int sectors = spc_get_write_same_sectors(cmd); + if ((flags[0] & 0x04) || (flags[0] & 0x02)) { pr_err("WRITE_SAME PBDATA and LBDATA" " bits not supported for Block Discard" " Emulation\n"); return TCM_UNSUPPORTED_SCSI_OPCODE; } + if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) { + pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n", + sectors, cmd->se_dev->dev_attrib.max_write_same_len); + return TCM_INVALID_CDB_FIELD; + } /* * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting * translated into block discard requests within backend code. diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4b3c183..cf1b8bb 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -465,7 +465,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) * Exit now if we don't support TP. */ if (!have_tp) - return 0; + goto max_write_same; /* * Set MAXIMUM UNMAP LBA COUNT @@ -491,6 +491,12 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) if (dev->dev_attrib.unmap_granularity_alignment != 0) buf[32] |= 0x80; /* Set the UGAVALID bit */ + /* + * MAXIMUM WRITE SAME LENGTH + */ +max_write_same: + put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); + return 0; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5350f6e..645d90a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -71,6 +71,8 @@ #define DA_UNMAP_GRANULARITY_DEFAULT 0 /* Default unmap_granularity_alignment */ #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0 +/* Default max_write_same_len, disabled by default */ +#define DA_MAX_WRITE_SAME_LEN 0 /* Default max transfer length */ #define DA_FABRIC_MAX_SECTORS 8192 /* Emulation for Direct Page Out */ @@ -609,6 +611,7 @@ struct se_dev_attrib { u32 max_unmap_block_desc_count; u32 unmap_granularity; u32 unmap_granularity_alignment; + u32 max_write_same_len; struct se_device *da_dev; struct config_group da_group; }; -- cgit v0.10.2 From f6970ad31d42fceb38b5595cbad093a4d0bfcc43 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 7 Nov 2012 20:08:38 -0800 Subject: target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support This patch adds support for emulation of WRITE_SAME w/ UNMAP=0 within iblock_execute_write_same() backend code. The emulation uses a bio_add_page() call for each sector, and by default enforces a limit of max_write_same_len=0xFFFF (65536) sectors following what scsi_debug reports per default for MAXIMUM WRITE SAME LENGTH. It also sets max_write_same_len to the operational default at setup -> iblock_configure_device() time. (hch: Move unmap logic into iblock_execute_write_same_unmap + add check for single sector SGLs in iblock_execute_write_same) (mkp: Update comment for 0xFFFF magic constant) (nab: drop left-over max_write_same_len check in iblock_execute_write_same) Cc: Christoph Hellwig Cc: Martin K. Petersen Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 53f4501..6646046 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -151,6 +151,11 @@ static int iblock_configure_device(struct se_device *dev) pr_debug("IBLOCK: BLOCK Discard support available," " disabled by default\n"); } + /* + * Enable write same emulation for IBLOCK and use 0xFFFF as + * the smaller WRITE_SAME(10) only has a two-byte block count. + */ + dev->dev_attrib.max_write_same_len = 0xFFFF; if (blk_queue_nonrot(q)) dev->dev_attrib.is_nonrot = 1; @@ -375,17 +380,20 @@ err: return ret; } +static struct bio *iblock_get_bio(struct se_cmd *, sector_t, u32); +static void iblock_submit_bios(struct bio_list *, int); +static void iblock_complete_cmd(struct se_cmd *); + static sense_reason_t -iblock_execute_write_same(struct se_cmd *cmd) +iblock_execute_write_same_unmap(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); - int ret; + int rc; - ret = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba, - spc_get_write_same_sectors(cmd), GFP_KERNEL, - 0); - if (ret < 0) { - pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); + rc = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba, + spc_get_write_same_sectors(cmd), GFP_KERNEL, 0); + if (rc < 0) { + pr_warn("blkdev_issue_discard() failed: %d\n", rc); return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } @@ -393,6 +401,69 @@ iblock_execute_write_same(struct se_cmd *cmd) return 0; } +static sense_reason_t +iblock_execute_write_same(struct se_cmd *cmd) +{ + struct iblock_req *ibr; + struct scatterlist *sg; + struct bio *bio; + struct bio_list list; + sector_t block_lba = cmd->t_task_lba; + unsigned int sectors = spc_get_write_same_sectors(cmd); + + sg = &cmd->t_data_sg[0]; + + if (cmd->t_data_nents > 1 || + sg->length != cmd->se_dev->dev_attrib.block_size) { + pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u" + " block_size: %u\n", cmd->t_data_nents, sg->length, + cmd->se_dev->dev_attrib.block_size); + return TCM_INVALID_CDB_FIELD; + } + + ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); + if (!ibr) + goto fail; + cmd->priv = ibr; + + bio = iblock_get_bio(cmd, block_lba, 1); + if (!bio) + goto fail_free_ibr; + + bio_list_init(&list); + bio_list_add(&list, bio); + + atomic_set(&ibr->pending, 1); + + while (sectors) { + while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) + != sg->length) { + + bio = iblock_get_bio(cmd, block_lba, 1); + if (!bio) + goto fail_put_bios; + + atomic_inc(&ibr->pending); + bio_list_add(&list, bio); + } + + /* Always in 512 byte units for Linux/Block */ + block_lba += sg->length >> IBLOCK_LBA_SHIFT; + sectors -= 1; + } + + iblock_submit_bios(&list, WRITE); + return 0; + +fail_put_bios: + while ((bio = bio_list_pop(&list))) + bio_put(bio); +fail_free_ibr: + kfree(ibr); +fail: + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +} + enum { Opt_udev_path, Opt_readonly, Opt_force, Opt_err }; @@ -701,6 +772,7 @@ static struct sbc_ops iblock_sbc_ops = { .execute_rw = iblock_execute_rw, .execute_sync_cache = iblock_execute_sync_cache, .execute_write_same = iblock_execute_write_same, + .execute_write_same_unmap = iblock_execute_write_same_unmap, .execute_unmap = iblock_execute_unmap, }; -- cgit v0.10.2 From fd9a11d7076e1d534a760032d2b8f3b59e10f9b5 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 9 Nov 2012 14:51:48 -0800 Subject: target: Update copyright information to 2012 v2: Use correct target_core_stat.c 2006 copyright year v3: Drop extra unnessary legal verbage from header (hch) Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 4c8eea2..85140f7 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -3,8 +3,7 @@ * * This file contains SPC-3 compliant asymmetric logical unit assigntment (ALUA) * - * Copyright (c) 2009-2010 Rising Tide Systems - * Copyright (c) 2009-2010 Linux-iSCSI.org + * (c) Copyright 2009-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 2b14164..10d4bfe 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3,8 +3,7 @@ * * This file contains ConfigFS logic for the Generic Target Engine project. * - * Copyright (c) 2008-2011 Rising Tide Systems - * Copyright (c) 2008-2011 Linux-iSCSI.org + * (c) Copyright 2008-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 54439bc..3f60439 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -4,10 +4,7 @@ * This file contains the TCM Virtual Device and Disk Transport * agnostic related functions. * - * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005-2006 SBE, Inc. All Rights Reserved. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2003-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index aa67313..816347c 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -4,10 +4,9 @@ * This file contains generic fabric module configfs infrastructure for * TCM v4.x code * - * Copyright (c) 2010,2011 Rising Tide Systems - * Copyright (c) 2010,2011 Linux-iSCSI.org + * (c) Copyright 2010-2012 RisingTide Systems LLC. * - * Copyright (c) Nicholas A. Bellinger + * Nicholas A. Bellinger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c index e460d62..687b0b0 100644 --- a/drivers/target/target_core_fabric_lib.c +++ b/drivers/target/target_core_fabric_lib.c @@ -4,8 +4,7 @@ * This file contains generic high level protocol identifier and PR * handlers for TCM fabric modules * - * Copyright (c) 2010 Rising Tide Systems, Inc. - * Copyright (c) 2010 Linux-iSCSI.org + * (c) Copyright 2010-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 3ccef83..8f6dae0 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -3,10 +3,7 @@ * * This file contains the Storage Engine <-> FILEIO transport specific functions * - * Copyright (c) 2005 PyX Technologies, Inc. - * Copyright (c) 2005-2006 SBE, Inc. All Rights Reserved. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2005-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index 048b7b4..d2616cd 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c @@ -3,10 +3,7 @@ * * This file contains the TCM HBA Transport related functions. * - * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2003-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 6646046..16f48e1 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -4,10 +4,7 @@ * This file contains the Storage Engine <-> Linux BlockIO transport * specific functions. * - * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2003-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index d7101a4..e35dbf8 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -4,8 +4,7 @@ * This file contains SPC-3 compliant persistent reservations and * legacy SPC-2 reservations with compatible reservation handling (CRH=1) * - * Copyright (c) 2009, 2010 Rising Tide Systems - * Copyright (c) 2009, 2010 Linux-iSCSI.org + * (c) Copyright 2009-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index b5c722b..2bcfd79 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -3,10 +3,7 @@ * * This file contains the generic target mode <-> Linux SCSI subsystem plugin. * - * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2003-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 126529c..0457de3 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -4,10 +4,7 @@ * This file contains the Storage Engine <-> Ramdisk transport * specific functions. * - * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2003-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 45e11d0..39ced25 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -1,10 +1,7 @@ /* * SCSI Block Commands (SBC) parsing and emulation. * - * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2002-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index cf1b8bb..84f9e96 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1,10 +1,7 @@ /* * SCSI Primary Commands (SPC) parsing and emulation. * - * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2002-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c index 9bbb017..d154ce7 100644 --- a/drivers/target/target_core_stat.c +++ b/drivers/target/target_core_stat.c @@ -1,13 +1,10 @@ /******************************************************************************* * Filename: target_core_stat.c * - * Copyright (c) 2011 Rising Tide Systems - * Copyright (c) 2011 Linux-iSCSI.org - * * Modern ConfigFS group context specific statistics based on original * target_core_mib.c code * - * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved. + * (c) Copyright 2006-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 2aaceae..c6e0293 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -3,8 +3,7 @@ * * This file contains SPC-3 task management infrastructure * - * Copyright (c) 2009,2010 Rising Tide Systems - * Copyright (c) 2009,2010 Linux-iSCSI.org + * (c) Copyright 2009-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index a531fe2..d84cc0a 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -3,10 +3,7 @@ * * This file contains generic Target Portal Group related functions. * - * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2002-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 63d7848..4b062c8 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3,10 +3,7 @@ * * This file contains the Generic Target Engine Core. * - * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. - * Copyright (c) 2005, 2006, 2007 SBE, Inc. - * Copyright (c) 2007-2010 Rising Tide Systems - * Copyright (c) 2008-2010 Linux-iSCSI.org + * (c) Copyright 2002-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 60c8f41..bf0e390 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -3,8 +3,7 @@ * * This file contains logic for SPC-3 Unit Attention emulation * - * Copyright (c) 2009,2010 Rising Tide Systems - * Copyright (c) 2009,2010 Linux-iSCSI.org + * (c) Copyright 2009-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger * -- cgit v0.10.2 From 06e97b489006f28e23bb028febfa1c01c266d676 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Fri, 16 Nov 2012 08:06:17 -0800 Subject: qla2xxx: Look up LUN for abort requests Search through the list of pending commands on the session list to find the command the initiator is actually aborting, so that we can pass the correct LUN to the core TMR handling code. (nab: Allow abort requests to work to LUN=0 with mainline target code) Signed-off-by: Steve Hodgson Signed-off-by: Roland Dreier Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 62aa558..661d33e 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1264,8 +1264,27 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) { struct qla_hw_data *ha = vha->hw; + struct se_session *se_sess = sess->se_sess; struct qla_tgt_mgmt_cmd *mcmd; + struct se_cmd *se_cmd; + u32 lun = 0; int rc; + bool found_lun = false; + + spin_lock(&se_sess->sess_cmd_lock); + list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { + struct qla_tgt_cmd *cmd = + container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + if (cmd->tag == abts->exchange_addr_to_abort) { + lun = cmd->unpacked_lun; + found_lun = true; + break; + } + } + spin_unlock(&se_sess->sess_cmd_lock); + + if (!found_lun) + return -ENOENT; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, "qla_target(%d): task abort (tag=%d)\n", @@ -1283,7 +1302,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, mcmd->sess = sess; memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); - rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, + rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK, abts->exchange_addr_to_abort); if (rc != 0) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, -- cgit v0.10.2 From d9ed69473a345d69cf15831e8db22f159b13cdd2 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 16 Nov 2012 08:06:18 -0800 Subject: target: Clean up logic in transport_put_cmd() No need to have a goto where a return is clearer. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4b062c8..7e7fa58 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1966,9 +1966,10 @@ static void transport_put_cmd(struct se_cmd *cmd) unsigned long flags; spin_lock_irqsave(&cmd->t_state_lock, flags); - if (atomic_read(&cmd->t_fe_count)) { - if (!atomic_dec_and_test(&cmd->t_fe_count)) - goto out_busy; + if (atomic_read(&cmd->t_fe_count) && + !atomic_dec_and_test(&cmd->t_fe_count)) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return; } if (cmd->transport_state & CMD_T_DEV_ACTIVE) { @@ -1980,8 +1981,6 @@ static void transport_put_cmd(struct se_cmd *cmd) transport_free_pages(cmd); transport_release_cmd(cmd); return; -out_busy: - spin_unlock_irqrestore(&cmd->t_state_lock, flags); } void *transport_kmap_data_sg(struct se_cmd *cmd) -- cgit v0.10.2 From c18bc7d8d34103d4bae47db180b508413f98dc36 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 16 Nov 2012 08:06:19 -0800 Subject: target: Clean up flow in transport_check_aborted_status() Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7e7fa58..1ebde4c5 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2761,23 +2761,19 @@ EXPORT_SYMBOL(transport_send_check_condition_and_sense); int transport_check_aborted_status(struct se_cmd *cmd, int send_status) { - int ret = 0; + if (!(cmd->transport_state & CMD_T_ABORTED)) + return 0; - if (cmd->transport_state & CMD_T_ABORTED) { - if (!send_status || - (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) - return 1; + if (!send_status || (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) + return 1; - pr_debug("Sending delayed SAM_STAT_TASK_ABORTED" - " status for CDB: 0x%02x ITT: 0x%08x\n", - cmd->t_task_cdb[0], - cmd->se_tfo->get_task_tag(cmd)); + pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n", + cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); - cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; - cmd->se_tfo->queue_status(cmd); - ret = 1; - } - return ret; + cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; + cmd->se_tfo->queue_status(cmd); + + return 1; } EXPORT_SYMBOL(transport_check_aborted_status); -- cgit v0.10.2 From 3a41d85febdd3ab060bd8a074862280c4aea29d5 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 17 Nov 2012 14:27:55 -0800 Subject: target/iblock: Forward declare bio helpers Go ahead and forward declare the handful of helper functions required for bio submission code in order to avoid the extra function prototypes. Reported-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 16f48e1..34f258b 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -55,8 +55,6 @@ static inline struct iblock_dev *IBLOCK_DEV(struct se_device *dev) static struct se_subsystem_api iblock_template; -static void iblock_bio_done(struct bio *, int); - /* iblock_attach_hba(): (Part of se_subsystem_api_t template) * * @@ -255,6 +253,87 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( return blocks_long; } +static void iblock_complete_cmd(struct se_cmd *cmd) +{ + struct iblock_req *ibr = cmd->priv; + u8 status; + + if (!atomic_dec_and_test(&ibr->pending)) + return; + + if (atomic_read(&ibr->ib_bio_err_cnt)) + status = SAM_STAT_CHECK_CONDITION; + else + status = SAM_STAT_GOOD; + + target_complete_cmd(cmd, status); + kfree(ibr); +} + +static void iblock_bio_done(struct bio *bio, int err) +{ + struct se_cmd *cmd = bio->bi_private; + struct iblock_req *ibr = cmd->priv; + + /* + * Set -EIO if !BIO_UPTODATE and the passed is still err=0 + */ + if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err) + err = -EIO; + + if (err != 0) { + pr_err("test_bit(BIO_UPTODATE) failed for bio: %p," + " err: %d\n", bio, err); + /* + * Bump the ib_bio_err_cnt and release bio. + */ + atomic_inc(&ibr->ib_bio_err_cnt); + smp_mb__after_atomic_inc(); + } + + bio_put(bio); + + iblock_complete_cmd(cmd); +} + +static struct bio * +iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) +{ + struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); + struct bio *bio; + + /* + * Only allocate as many vector entries as the bio code allows us to, + * we'll loop later on until we have handled the whole request. + */ + if (sg_num > BIO_MAX_PAGES) + sg_num = BIO_MAX_PAGES; + + bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set); + if (!bio) { + pr_err("Unable to allocate memory for bio\n"); + return NULL; + } + + bio->bi_bdev = ib_dev->ibd_bd; + bio->bi_private = cmd; + bio->bi_end_io = &iblock_bio_done; + bio->bi_sector = lba; + + return bio; +} + +static void iblock_submit_bios(struct bio_list *list, int rw) +{ + struct blk_plug plug; + struct bio *bio; + + blk_start_plug(&plug); + while ((bio = bio_list_pop(list))) + submit_bio(rw, bio); + blk_finish_plug(&plug); +} + static void iblock_end_io_flush(struct bio *bio, int err) { struct se_cmd *cmd = bio->bi_private; @@ -377,10 +456,6 @@ err: return ret; } -static struct bio *iblock_get_bio(struct se_cmd *, sector_t, u32); -static void iblock_submit_bios(struct bio_list *, int); -static void iblock_complete_cmd(struct se_cmd *); - static sense_reason_t iblock_execute_write_same_unmap(struct se_cmd *cmd) { @@ -565,60 +640,6 @@ static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b) return bl; } -static void iblock_complete_cmd(struct se_cmd *cmd) -{ - struct iblock_req *ibr = cmd->priv; - u8 status; - - if (!atomic_dec_and_test(&ibr->pending)) - return; - - if (atomic_read(&ibr->ib_bio_err_cnt)) - status = SAM_STAT_CHECK_CONDITION; - else - status = SAM_STAT_GOOD; - - target_complete_cmd(cmd, status); - kfree(ibr); -} - -static struct bio * -iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) -{ - struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); - struct bio *bio; - - /* - * Only allocate as many vector entries as the bio code allows us to, - * we'll loop later on until we have handled the whole request. - */ - if (sg_num > BIO_MAX_PAGES) - sg_num = BIO_MAX_PAGES; - - bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set); - if (!bio) { - pr_err("Unable to allocate memory for bio\n"); - return NULL; - } - - bio->bi_bdev = ib_dev->ibd_bd; - bio->bi_private = cmd; - bio->bi_end_io = &iblock_bio_done; - bio->bi_sector = lba; - return bio; -} - -static void iblock_submit_bios(struct bio_list *list, int rw) -{ - struct blk_plug plug; - struct bio *bio; - - blk_start_plug(&plug); - while ((bio = bio_list_pop(list))) - submit_bio(rw, bio); - blk_finish_plug(&plug); -} - static sense_reason_t iblock_execute_rw(struct se_cmd *cmd) { @@ -739,32 +760,6 @@ static sector_t iblock_get_blocks(struct se_device *dev) return iblock_emulate_read_cap_with_block_size(dev, bd, q); } -static void iblock_bio_done(struct bio *bio, int err) -{ - struct se_cmd *cmd = bio->bi_private; - struct iblock_req *ibr = cmd->priv; - - /* - * Set -EIO if !BIO_UPTODATE and the passed is still err=0 - */ - if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err) - err = -EIO; - - if (err != 0) { - pr_err("test_bit(BIO_UPTODATE) failed for bio: %p," - " err: %d\n", bio, err); - /* - * Bump the ib_bio_err_cnt and release bio. - */ - atomic_inc(&ibr->ib_bio_err_cnt); - smp_mb__after_atomic_inc(); - } - - bio_put(bio); - - iblock_complete_cmd(cmd); -} - static struct sbc_ops iblock_sbc_ops = { .execute_rw = iblock_execute_rw, .execute_sync_cache = iblock_execute_sync_cache, -- cgit v0.10.2 From b07c28aab52edffb592429637fed846c48dca0a8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 21 Nov 2012 16:14:40 +0530 Subject: iscsi_target: Remove redundant null check before kfree kfree on null pointer is a no-op. Signed-off-by: Sachin Kamat Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 7bf9ccc..fdb632f 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1118,10 +1118,8 @@ new_sess_out: idr_remove(&sess_idr, conn->sess->session_index); spin_unlock_bh(&sess_idr_lock); } - if (conn->sess->sess_ops) - kfree(conn->sess->sess_ops); - if (conn->sess) - kfree(conn->sess); + kfree(conn->sess->sess_ops); + kfree(conn->sess); old_sess_out: iscsi_stop_login_thread_timer(np); /* -- cgit v0.10.2 From 3c989d7603872bf878840f7ce3ea49b73bea4c6c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 23 Nov 2012 12:07:39 +0800 Subject: iscsit: use GFP_ATOMIC under spin lock The function iscsit_build_conn_drop_async_message() is called from iscsit_close_connection() with spin lock 'sess->conn_lock' held, so we should use GFP_ATOMIC instead of GFP_KERNEL. Signed-off-by: Wei Yongjun Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 4ad14ac..339f97f 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -2336,7 +2336,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) if (!conn_p) return; - cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); + cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); if (!cmd) { iscsit_dec_conn_usage_count(conn_p); return; -- cgit v0.10.2 From 6b64e1fe2ba80ac3ce12a21f1200bac594fa1a1c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 27 Nov 2012 17:27:01 +0300 Subject: target: update error handling for sbc_setup_write_same() We recently changed this to return positive subsystem error codes so the error handling needs to be updated. Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 39ced25..94fd004 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -437,7 +437,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->t_task_lba = get_unaligned_be64(&cdb[12]); ret = sbc_setup_write_same(cmd, &cdb[10], ops); - if (ret < 0) + if (ret) return ret; break; default: @@ -510,7 +510,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->t_task_lba = get_unaligned_be64(&cdb[2]); ret = sbc_setup_write_same(cmd, &cdb[1], ops); - if (ret < 0) + if (ret) return ret; break; case WRITE_SAME: @@ -528,7 +528,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) * of byte 1 bit 3 UNMAP instead of original reserved field */ ret = sbc_setup_write_same(cmd, &cdb[1], ops); - if (ret < 0) + if (ret) return ret; break; case VERIFY: -- cgit v0.10.2 From 1c98d2f439f3f945c5040fd648d817e86314f2fa Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 27 Nov 2012 18:54:19 +0100 Subject: target/configfs: allocate pointers instead of full struct for default_groups default_groups is defined as struct config_group **default_groups so we don't need to allocate a whole struct but only enough space for a pointer that points there. (nab: Fix up minor apply breakage in for-next) Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index ff6fd4f..7c4243e 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -803,7 +803,7 @@ static struct se_node_acl *lio_target_make_nodeacl( acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl); stats_cg = &se_nacl->acl_fabric_stat_group; - stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + stats_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!stats_cg->default_groups) { pr_err("Unable to allocate memory for" @@ -1268,7 +1268,7 @@ static struct se_wwn *lio_target_call_coreaddtiqn( */ stats_cg = &tiqn->tiqn_wwn.fabric_stat_group; - stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 6, + stats_cg->default_groups = kzalloc(sizeof(struct config_group *) * 6, GFP_KERNEL); if (!stats_cg->default_groups) { pr_err("Unable to allocate memory for" diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 10d4bfe..02fd55d 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -2496,7 +2496,7 @@ static struct config_group *target_core_make_subdev( dev_cg = &dev->dev_group; - dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, + dev_cg->default_groups = kzalloc(sizeof(struct config_group *) * 7, GFP_KERNEL); if (!dev_cg->default_groups) goto out_free_device; @@ -2528,7 +2528,7 @@ static struct config_group *target_core_make_subdev( dev->t10_alua.default_tg_pt_gp = tg_pt_gp; tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; - tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!tg_pt_gp_cg->default_groups) { pr_err("Unable to allocate tg_pt_gp_cg->" @@ -2544,7 +2544,7 @@ static struct config_group *target_core_make_subdev( * Add core/$HBA/$DEV/statistics/ default groups */ dev_stat_grp = &dev->dev_stat_grps.stat_group; - dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, + dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 4, GFP_KERNEL); if (!dev_stat_grp->default_groups) { pr_err("Unable to allocate dev_stat_grp->default_groups\n"); @@ -2829,7 +2829,7 @@ static int __init target_core_init_configfs(void) * and ALUA Logical Unit Group and Target Port Group infrastructure. */ target_cg = &subsys->su_group; - target_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + target_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); @@ -2845,7 +2845,7 @@ static int __init target_core_init_configfs(void) * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/ */ hba_cg = &target_core_hbagroup; - hba_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + hba_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!hba_cg->default_groups) { pr_err("Unable to allocate hba_cg->default_groups\n"); @@ -2861,7 +2861,7 @@ static int __init target_core_init_configfs(void) * groups under /sys/kernel/config/target/core/alua/ */ alua_cg = &alua_group; - alua_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + alua_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!alua_cg->default_groups) { pr_err("Unable to allocate alua_cg->default_groups\n"); @@ -2883,7 +2883,7 @@ static int __init target_core_init_configfs(void) } lu_gp_cg = &alua_lu_gps_group; - lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lu_gp_cg->default_groups) { pr_err("Unable to allocate lu_gp_cg->default_groups\n"); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 816347c..efe31a0 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -357,7 +357,7 @@ static struct config_group *target_fabric_make_mappedlun( } lacl_cg = &lacl->se_lun_group; - lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + lacl_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lacl_cg->default_groups) { pr_err("Unable to allocate lacl_cg->default_groups\n"); @@ -373,7 +373,7 @@ static struct config_group *target_fabric_make_mappedlun( lacl_cg->default_groups[1] = NULL; ml_stat_grp = &lacl->ml_stat_grps.stat_group; - ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, + ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 3, GFP_KERNEL); if (!ml_stat_grp->default_groups) { pr_err("Unable to allocate ml_stat_grp->default_groups\n"); @@ -858,7 +858,7 @@ static struct config_group *target_fabric_make_lun( return ERR_PTR(-EINVAL); lun_cg = &lun->lun_group; - lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + lun_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lun_cg->default_groups) { pr_err("Unable to allocate lun_cg->default_groups\n"); -- cgit v0.10.2 From a5675c8a8b72efdd09ccd1b0975c4670675775ef Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 27 Nov 2012 17:49:44 -0800 Subject: target/configfs: allocate only 6 slots for dev_cg->default_groups Only slots 0-5 are used so 6 slots should be enough. I don't see anyone writting anything else than NULL into ->default_groups[5] so a "late" initialisation should not happen here. (nab: Fix up minor apply breakage in for-next) Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 02fd55d..f6fc258 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -2496,7 +2496,7 @@ static struct config_group *target_core_make_subdev( dev_cg = &dev->dev_group; - dev_cg->default_groups = kzalloc(sizeof(struct config_group *) * 7, + dev_cg->default_groups = kzalloc(sizeof(struct config_group *) * 6, GFP_KERNEL); if (!dev_cg->default_groups) goto out_free_device; -- cgit v0.10.2 From 13f6a91479b06133eb99f1f43be02608eb867313 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 27 Nov 2012 18:54:21 +0100 Subject: target/configfs: use kmalloc() instead of kzalloc() for default groups All elements are assigned even the NULL member at the end so there is no reason to allocate zeroed memory. (nab: Fix up minor apply breakage in for-next) Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 7c4243e..542641c 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -803,7 +803,7 @@ static struct se_node_acl *lio_target_make_nodeacl( acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl); stats_cg = &se_nacl->acl_fabric_stat_group; - stats_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!stats_cg->default_groups) { pr_err("Unable to allocate memory for" @@ -1268,7 +1268,7 @@ static struct se_wwn *lio_target_call_coreaddtiqn( */ stats_cg = &tiqn->tiqn_wwn.fabric_stat_group; - stats_cg->default_groups = kzalloc(sizeof(struct config_group *) * 6, + stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6, GFP_KERNEL); if (!stats_cg->default_groups) { pr_err("Unable to allocate memory for" diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index f6fc258..4efb61b 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -2496,7 +2496,7 @@ static struct config_group *target_core_make_subdev( dev_cg = &dev->dev_group; - dev_cg->default_groups = kzalloc(sizeof(struct config_group *) * 6, + dev_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6, GFP_KERNEL); if (!dev_cg->default_groups) goto out_free_device; @@ -2528,7 +2528,7 @@ static struct config_group *target_core_make_subdev( dev->t10_alua.default_tg_pt_gp = tg_pt_gp; tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; - tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + tg_pt_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!tg_pt_gp_cg->default_groups) { pr_err("Unable to allocate tg_pt_gp_cg->" @@ -2544,7 +2544,7 @@ static struct config_group *target_core_make_subdev( * Add core/$HBA/$DEV/statistics/ default groups */ dev_stat_grp = &dev->dev_stat_grps.stat_group; - dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 4, + dev_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 4, GFP_KERNEL); if (!dev_stat_grp->default_groups) { pr_err("Unable to allocate dev_stat_grp->default_groups\n"); @@ -2829,7 +2829,7 @@ static int __init target_core_init_configfs(void) * and ALUA Logical Unit Group and Target Port Group infrastructure. */ target_cg = &subsys->su_group; - target_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + target_cg->default_groups = kmalloc(sizeof(struct config_group) * 2, GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); @@ -2845,7 +2845,7 @@ static int __init target_core_init_configfs(void) * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/ */ hba_cg = &target_core_hbagroup; - hba_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + hba_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!hba_cg->default_groups) { pr_err("Unable to allocate hba_cg->default_groups\n"); @@ -2861,7 +2861,7 @@ static int __init target_core_init_configfs(void) * groups under /sys/kernel/config/target/core/alua/ */ alua_cg = &alua_group; - alua_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + alua_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!alua_cg->default_groups) { pr_err("Unable to allocate alua_cg->default_groups\n"); @@ -2883,7 +2883,7 @@ static int __init target_core_init_configfs(void) } lu_gp_cg = &alua_lu_gps_group; - lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + lu_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lu_gp_cg->default_groups) { pr_err("Unable to allocate lu_gp_cg->default_groups\n"); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index efe31a0..9c67917 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -357,7 +357,7 @@ static struct config_group *target_fabric_make_mappedlun( } lacl_cg = &lacl->se_lun_group; - lacl_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lacl_cg->default_groups) { pr_err("Unable to allocate lacl_cg->default_groups\n"); @@ -373,7 +373,7 @@ static struct config_group *target_fabric_make_mappedlun( lacl_cg->default_groups[1] = NULL; ml_stat_grp = &lacl->ml_stat_grps.stat_group; - ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 3, + ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3, GFP_KERNEL); if (!ml_stat_grp->default_groups) { pr_err("Unable to allocate ml_stat_grp->default_groups\n"); @@ -858,7 +858,7 @@ static struct config_group *target_fabric_make_lun( return ERR_PTR(-EINVAL); lun_cg = &lun->lun_group; - lun_cg->default_groups = kzalloc(sizeof(struct config_group *) * 2, + lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lun_cg->default_groups) { pr_err("Unable to allocate lun_cg->default_groups\n"); -- cgit v0.10.2 From ffe0067544f93c0e71c793d7f17240486d091a3c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 27 Nov 2012 19:07:52 -0800 Subject: target: Make spc_get_write_same_sectors return sector_t We already expect TFO->get_blocks() to return sector_t for zero value case when doing WRITE_SAME to the end of the backend device, so go ahead and return sector_t from spc_get_write_same_sectors() to handle this case properly. Also, update the single iblock_execute_write_same() caller of this code. Cc: Christoph Hellwig Cc: Martin K. Petersen Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 34f258b..b526d23 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -481,7 +481,7 @@ iblock_execute_write_same(struct se_cmd *cmd) struct bio *bio; struct bio_list list; sector_t block_lba = cmd->t_task_lba; - unsigned int sectors = spc_get_write_same_sectors(cmd); + sector_t sectors = spc_get_write_same_sectors(cmd); sg = &cmd->t_data_sg[0]; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 94fd004..26a6d18 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -107,7 +107,7 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd) return 0; } -int spc_get_write_same_sectors(struct se_cmd *cmd) +sector_t spc_get_write_same_sectors(struct se_cmd *cmd) { u32 num_blocks; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 3393ab1..5079109 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -52,7 +52,7 @@ void target_complete_cmd(struct se_cmd *, u8); sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd); -int spc_get_write_same_sectors(struct se_cmd *cmd); +sector_t spc_get_write_same_sectors(struct se_cmd *cmd); sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); u32 sbc_get_device_rev(struct se_device *dev); -- cgit v0.10.2 From 9474b043132f41ee03bd3d8dcb076f8569ae69d3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 27 Nov 2012 23:55:57 -0800 Subject: ib_srpt: Convert I/O path to target_submit_cmd + drop legacy ioctx->kref This patch converts the main srpt_handle_cmd() I/O path to use modern target_submit_cmd() with TARGET_SCF_ACK_KREF flag usage. This includes dropping the original internal ioctx->kref + srpt_put_send_ioctx() usage in favor of target_put_sess_cmd() w/ se_cmd_t->cmd_kref within ib_srpt response callbacks. It also updates srpt_abort_cmd() to call target_put_sess_cmd() for completion of aborted commands, and adds target_wait_for_sess_cmds() into srpt_release_channel_work() to allow outstanding I/O to complete during session shutdown. Also, go ahead and update srpt_handle_tsk_mgmt() to make the remaining transport_init_se_cmd() to setup the ioctx->cmd with se_tmr_req. Cc: Christoph Hellwig Cc: Bart Van Assche Cc: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index e6fafc62..77b6368 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1269,7 +1269,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) return ioctx; BUG_ON(ioctx->ch != ch); - kref_init(&ioctx->kref); spin_lock_init(&ioctx->spinlock); ioctx->state = SRPT_STATE_NEW; ioctx->n_rbuf = 0; @@ -1291,39 +1290,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) } /** - * srpt_put_send_ioctx() - Free up resources. - */ -static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx) -{ - struct srpt_rdma_ch *ch; - unsigned long flags; - - BUG_ON(!ioctx); - ch = ioctx->ch; - BUG_ON(!ch); - - WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE); - - srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); - transport_generic_free_cmd(&ioctx->cmd, 0); - - if (ioctx->n_rbuf > 1) { - kfree(ioctx->rbufs); - ioctx->rbufs = NULL; - ioctx->n_rbuf = 0; - } - - spin_lock_irqsave(&ch->spinlock, flags); - list_add(&ioctx->free_list, &ch->free_list); - spin_unlock_irqrestore(&ch->spinlock, flags); -} - -static void srpt_put_send_ioctx_kref(struct kref *kref) -{ - srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref)); -} - -/** * srpt_abort_cmd() - Abort a SCSI command. * @ioctx: I/O context associated with the SCSI command. * @context: Preferred execution context. @@ -1359,8 +1325,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) } spin_unlock_irqrestore(&ioctx->spinlock, flags); - if (state == SRPT_STATE_DONE) + if (state == SRPT_STATE_DONE) { + struct srpt_rdma_ch *ch = ioctx->ch; + + BUG_ON(ch->sess == NULL); + + target_put_sess_cmd(ch->sess, &ioctx->cmd); goto out; + } pr_debug("Aborting cmd with state %d and tag %lld\n", state, ioctx->tag); @@ -1395,11 +1367,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags); ioctx->cmd.transport_state |= CMD_T_LUN_STOP; spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); break; case SRPT_STATE_MGMT_RSP_SENT: srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); break; default: WARN_ON("ERROR: unexpected command state"); @@ -1457,11 +1429,13 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, && state != SRPT_STATE_DONE)) pr_debug("state = %d\n", state); - if (state != SRPT_STATE_DONE) - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); - else + if (state != SRPT_STATE_DONE) { + srpt_unmap_sg_to_ib_sge(ch, ioctx); + transport_generic_free_cmd(&ioctx->cmd, 0); + } else { printk(KERN_ERR "IB completion has been received too late for" " wr_id = %u.\n", ioctx->ioctx.index); + } } /** @@ -1712,10 +1686,10 @@ out_err: static int srpt_check_stop_free(struct se_cmd *cmd) { - struct srpt_send_ioctx *ioctx; + struct srpt_send_ioctx *ioctx = container_of(cmd, + struct srpt_send_ioctx, cmd); - ioctx = container_of(cmd, struct srpt_send_ioctx, cmd); - return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); } /** @@ -1731,11 +1705,11 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, u64 data_len; enum dma_data_direction dir; sense_reason_t ret; + int rc; BUG_ON(!send_ioctx); srp_cmd = recv_ioctx->ioctx.buf; - kref_get(&send_ioctx->kref); cmd = &send_ioctx->cmd; send_ioctx->tag = srp_cmd->tag; @@ -1759,30 +1733,18 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", srp_cmd->tag); ret = TCM_INVALID_CDB_FIELD; - kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; } - cmd->data_length = data_len; - cmd->data_direction = dir; unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, sizeof(srp_cmd->lun)); - ret = transport_lookup_cmd_lun(cmd, unpacked_lun); - if (ret) { - kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); + rc = target_submit_cmd(cmd, ch->sess, srp_cmd->cdb, + &send_ioctx->sense_data[0], unpacked_lun, data_len, + MSG_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF); + if (rc != 0) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto send_sense; } - ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb); - if (ret) { - kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); - if (ret == TCM_RESERVATION_CONFLICT) { - srpt_queue_status(cmd); - return 0; - } - goto send_sense; - } - - transport_handle_cdb_direct(cmd); return 0; send_sense: @@ -1884,6 +1846,9 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; goto fail; } + transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess, + 0, DMA_NONE, MSG_SIMPLE_TAG, send_ioctx->sense_data); + res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); if (res < 0) { send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; @@ -1902,11 +1867,9 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); - kref_get(&send_ioctx->kref); transport_generic_handle_tmr(&send_ioctx->cmd); return; fail: - kref_get(&send_ioctx->kref); transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: } @@ -1949,10 +1912,6 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch, } } - transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess, - 0, DMA_NONE, MSG_SIMPLE_TAG, - send_ioctx->sense_data); - switch (srp_cmd->opcode) { case SRP_CMD: srpt_handle_cmd(ch, recv_ioctx, send_ioctx); @@ -2358,6 +2317,7 @@ static void srpt_release_channel_work(struct work_struct *w) { struct srpt_rdma_ch *ch; struct srpt_device *sdev; + struct se_session *se_sess; ch = container_of(w, struct srpt_rdma_ch, release_work); pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess, @@ -2366,8 +2326,13 @@ static void srpt_release_channel_work(struct work_struct *w) sdev = ch->sport->sdev; BUG_ON(!sdev); - transport_deregister_session_configfs(ch->sess); - transport_deregister_session(ch->sess); + se_sess = ch->sess; + BUG_ON(!se_sess); + + target_wait_for_sess_cmds(se_sess, 0); + + transport_deregister_session_configfs(se_sess); + transport_deregister_session(se_sess); ch->sess = NULL; srpt_destroy_ch_ib(ch); @@ -3092,7 +3057,7 @@ static int srpt_queue_response(struct se_cmd *cmd) ioctx->tag); srpt_unmap_sg_to_ib_sge(ch, ioctx); srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); } out: @@ -3483,6 +3448,23 @@ static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg) static void srpt_release_cmd(struct se_cmd *se_cmd) { + struct srpt_send_ioctx *ioctx = container_of(se_cmd, + struct srpt_send_ioctx, cmd); + struct srpt_rdma_ch *ch = ioctx->ch; + unsigned long flags; + + WARN_ON(ioctx->state != SRPT_STATE_DONE); + WARN_ON(ioctx->mapped_sg_count != 0); + + if (ioctx->n_rbuf > 1) { + kfree(ioctx->rbufs); + ioctx->rbufs = NULL; + ioctx->n_rbuf = 0; + } + + spin_lock_irqsave(&ch->spinlock, flags); + list_add(&ioctx->free_list, &ch->free_list); + spin_unlock_irqrestore(&ch->spinlock, flags); } /** diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index 61e52b8..4caf55c 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -228,7 +228,6 @@ struct srpt_recv_ioctx { struct srpt_send_ioctx { struct srpt_ioctx ioctx; struct srpt_rdma_ch *ch; - struct kref kref; struct rdma_iu *rdma_ius; struct srp_direct_buf *rbufs; struct srp_direct_buf single_rbuf; -- cgit v0.10.2 From 3e4f574857eebce60bb56d7524f3f9eaa2a126d0 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 28 Nov 2012 01:38:04 -0800 Subject: ib_srpt: Convert TMR path to target_submit_tmr This patch converts the TMR path in srpt_handle_tsk_mgmt() to use target_submit_tmr() with TARGET_SCF_ACK_KREF flag usage. v2: Drop ununused res in target_submit_tmr (Fengguang.Wu) Cc: Christoph Hellwig Cc: Bart Van Assche Cc: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 77b6368..c09d41b 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1825,9 +1825,11 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, { struct srp_tsk_mgmt *srp_tsk; struct se_cmd *cmd; + struct se_session *sess = ch->sess; uint64_t unpacked_lun; + uint32_t tag = 0; int tcm_tmr; - int res; + int rc; BUG_ON(!send_ioctx); @@ -1846,28 +1848,25 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; goto fail; } - transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess, - 0, DMA_NONE, MSG_SIMPLE_TAG, send_ioctx->sense_data); - - res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); - if (res < 0) { - send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; - goto fail; - } - unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, sizeof(srp_tsk->lun)); - res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun); - if (res) { - pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun); - send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; + + if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) { + rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); + if (rc < 0) { + send_ioctx->cmd.se_tmr_req->response = + TMR_TASK_DOES_NOT_EXIST; + goto fail; + } + tag = srp_tsk->task_tag; + } + rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun, + srp_tsk, tcm_tmr, GFP_KERNEL, tag, + TARGET_SCF_ACK_KREF); + if (rc != 0) { + send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; goto fail; } - - if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) - srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); - - transport_generic_handle_tmr(&send_ioctx->cmd); return; fail: transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: -- cgit v0.10.2 From 0ff8754981261a80f4b77db2536dfea92c2d4539 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 4 Dec 2012 23:43:57 -0800 Subject: target: Add link_magic for fabric allow_link destination target_items This patch adds [dev,lun]_link_magic value assignment + checks within generic target_fabric_port_link() and target_fabric_mappedlun_link() code to ensure destination config_item *target_item sent from configfs_symlink() -> config_item_operations->allow_link() is the underlying se_device->dev_group and se_lun->lun_group that we expect to symlink. Reported-by: Sebastian Andrzej Siewior Cc: Sebastian Andrzej Siewior Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 3f60439..e269510 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1352,6 +1352,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) if (!dev) return NULL; + dev->dev_link_magic = SE_DEV_LINK_MAGIC; dev->se_hba = hba; dev->transport = hba->transport; diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 9c67917..810263d 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -70,6 +70,12 @@ static int target_fabric_mappedlun_link( struct se_portal_group *se_tpg; struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; int ret = 0, lun_access; + + if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { + pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" + " %p to struct lun: %p\n", lun_ci, lun); + return -EFAULT; + } /* * Ensure that the source port exists */ @@ -742,6 +748,12 @@ static int target_fabric_port_link( struct target_fabric_configfs *tf; int ret; + if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { + pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" + " %p to struct se_device: %p\n", se_dev_ci, dev); + return -EFAULT; + } + tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; se_tpg = container_of(to_config_group(tpg_ci), struct se_portal_group, tpg_group); diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index d84cc0a..0163309 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -669,6 +669,7 @@ int core_tpg_register( for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { lun = se_tpg->tpg_lun_list[i]; lun->unpacked_lun = i; + lun->lun_link_magic = SE_LUN_LINK_MAGIC; lun->lun_status = TRANSPORT_LUN_STATUS_FREE; atomic_set(&lun->lun_acl_count, 0); init_completion(&lun->lun_shutdown_comp); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 645d90a..1346ee0 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -624,6 +624,8 @@ struct se_dev_stat_grps { }; struct se_device { +#define SE_DEV_LINK_MAGIC 0xfeeddeef + u32 dev_link_magic; /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ @@ -722,6 +724,8 @@ struct se_port_stat_grps { }; struct se_lun { +#define SE_LUN_LINK_MAGIC 0xffff7771 + u32 lun_link_magic; /* See transport_lun_status_table */ enum transport_lun_status_table lun_status; u32 lun_access; -- cgit v0.10.2 From 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Dec 2012 12:08:29 +0100 Subject: target/file: Fix 32-bit highmem breakage for SGL -> iovec mapping This patch changes vectored file I/O to use kmap + kunmap when mapping incoming SGL memory -> struct iovec in order to properly support 32-bit highmem configurations. This is because an extra bounce buffer may be required when processing scatterlist pages allocated with GFP_KERNEL. Signed-off-by: Sebastian Andrzej Siewior Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 8f6dae0..1fc5825 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -236,7 +236,7 @@ static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, for_each_sg(sgl, sg, sgl_nents, i) { iov[i].iov_len = sg->length; - iov[i].iov_base = sg_virt(sg); + iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; } old_fs = get_fs(); @@ -244,6 +244,8 @@ static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); set_fs(old_fs); + for_each_sg(sgl, sg, sgl_nents, i) + kunmap(sg_page(sg)); kfree(iov); /* * Return zeros and GOOD status even if the READ did not return @@ -288,7 +290,7 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, for_each_sg(sgl, sg, sgl_nents, i) { iov[i].iov_len = sg->length; - iov[i].iov_base = sg_virt(sg); + iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; } old_fs = get_fs(); @@ -296,6 +298,9 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); set_fs(old_fs); + for_each_sg(sgl, sg, sgl_nents, i) + kunmap(sg_page(sg)); + kfree(iov); if (ret < 0 || ret != cmd->data_length) { -- cgit v0.10.2 From 778229af95977a4aca8656143d457401c2bb8f96 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Dec 2012 13:09:45 -0800 Subject: target/file: merge fd_do_readv() and fd_do_writev() Those two functions are almost identical so merge them. Noticed this while fixing the highmem in both cases. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 1fc5825..b9c8849 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -216,8 +216,8 @@ static void fd_free_device(struct se_device *dev) kfree(fd_dev); } -static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, - u32 sgl_nents) +static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl, + u32 sgl_nents, int is_write) { struct se_device *se_dev = cmd->se_dev; struct fd_dev *dev = FD_DEV(se_dev); @@ -241,73 +241,45 @@ static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl, old_fs = get_fs(); set_fs(get_ds()); - ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); + + if (is_write) + ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); + else + ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); + set_fs(old_fs); for_each_sg(sgl, sg, sgl_nents, i) kunmap(sg_page(sg)); + kfree(iov); - /* - * Return zeros and GOOD status even if the READ did not return - * the expected virt_size for struct file w/o a backing struct - * block_device. - */ - if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) { + + if (is_write) { if (ret < 0 || ret != cmd->data_length) { - pr_err("vfs_readv() returned %d," - " expecting %d for S_ISBLK\n", ret, - (int)cmd->data_length); + pr_err("%s() write returned %d\n", __func__, ret); return (ret < 0 ? ret : -EINVAL); } } else { - if (ret < 0) { - pr_err("vfs_readv() returned %d for non" - " S_ISBLK\n", ret); - return ret; + /* + * Return zeros and GOOD status even if the READ did not return + * the expected virt_size for struct file w/o a backing struct + * block_device. + */ + if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) { + if (ret < 0 || ret != cmd->data_length) { + pr_err("%s() returned %d, expecting %u for " + "S_ISBLK\n", __func__, ret, + cmd->data_length); + return (ret < 0 ? ret : -EINVAL); + } + } else { + if (ret < 0) { + pr_err("%s() returned %d for non S_ISBLK\n", + __func__, ret); + return ret; + } } } - - return 1; -} - -static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, - u32 sgl_nents) -{ - struct se_device *se_dev = cmd->se_dev; - struct fd_dev *dev = FD_DEV(se_dev); - struct file *fd = dev->fd_file; - struct scatterlist *sg; - struct iovec *iov; - mm_segment_t old_fs; - loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size); - int ret, i = 0; - - iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL); - if (!iov) { - pr_err("Unable to allocate fd_do_writev iov[]\n"); - return -ENOMEM; - } - - for_each_sg(sgl, sg, sgl_nents, i) { - iov[i].iov_len = sg->length; - iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; - } - - old_fs = get_fs(); - set_fs(get_ds()); - ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); - set_fs(old_fs); - - for_each_sg(sgl, sg, sgl_nents, i) - kunmap(sg_page(sg)); - - kfree(iov); - - if (ret < 0 || ret != cmd->data_length) { - pr_err("vfs_writev() returned %d\n", ret); - return (ret < 0 ? ret : -EINVAL); - } - return 1; } @@ -370,9 +342,9 @@ fd_execute_rw(struct se_cmd *cmd) * physical memory addresses to struct iovec virtual memory. */ if (data_direction == DMA_FROM_DEVICE) { - ret = fd_do_readv(cmd, sgl, sgl_nents); + ret = fd_do_rw(cmd, sgl, sgl_nents, 0); } else { - ret = fd_do_writev(cmd, sgl, sgl_nents); + ret = fd_do_rw(cmd, sgl, sgl_nents, 1); /* * Perform implict vfs_fsync_range() for fd_do_writev() ops * for SCSI WRITEs with Forced Unit Access (FUA) set. -- cgit v0.10.2 From ed72a4d52add345595f09b360d6ac5f20428d361 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 29 Nov 2012 20:29:01 +0100 Subject: iscsi-target: use kstrdup() for iscsi_param The kmalloc() + strlen() + memcpy() block is what kstrdup() does as well. While here I also removed the "to NULL assignment" of pointers which are fed to kfree or thrown away anyway. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 90b7400..839def0 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -154,22 +154,18 @@ static struct iscsi_param *iscsi_set_default_param(struct iscsi_param_list *para } INIT_LIST_HEAD(¶m->p_list); - param->name = kzalloc(strlen(name) + 1, GFP_KERNEL); + param->name = kstrdup(name, GFP_KERNEL); if (!param->name) { pr_err("Unable to allocate memory for parameter name.\n"); goto out; } - param->value = kzalloc(strlen(value) + 1, GFP_KERNEL); + param->value = kstrdup(value, GFP_KERNEL); if (!param->value) { pr_err("Unable to allocate memory for parameter value.\n"); goto out; } - memcpy(param->name, name, strlen(name)); - param->name[strlen(name)] = '\0'; - memcpy(param->value, value, strlen(value)); - param->value[strlen(value)] = '\0'; param->phase = phase; param->scope = scope; param->sender = sender; @@ -635,11 +631,8 @@ void iscsi_release_param_list(struct iscsi_param_list *param_list) list_del(¶m->p_list); kfree(param->name); - param->name = NULL; kfree(param->value); - param->value = NULL; kfree(param); - param = NULL; } iscsi_release_extra_responses(param_list); @@ -687,15 +680,12 @@ int iscsi_update_param_value(struct iscsi_param *param, char *value) { kfree(param->value); - param->value = kzalloc(strlen(value) + 1, GFP_KERNEL); + param->value = kstrdup(value, GFP_KERNEL); if (!param->value) { pr_err("Unable to allocate memory for value.\n"); return -ENOMEM; } - memcpy(param->value, value, strlen(value)); - param->value[strlen(value)] = '\0'; - pr_debug("iSCSI Parameter updated to %s=%s\n", param->name, param->value); return 0; -- cgit v0.10.2 From 37419d674ca99739dbee5ada28b50aacc29c94e1 Mon Sep 17 00:00:00 2001 From: Chris Boot Date: Tue, 11 Dec 2012 21:58:47 +0000 Subject: sbp-target: use simple assignment in tgt_agent_rw_agent_state() There is no need to memcpy() a 32-bit integer. The data pointer is guaranteed to be quadlet aligned by the FireWire stack so we can replace the memcpy() with an assignment. Thanks to Stefan Richter. Signed-off-by: Chris Boot Cc: Stefan Richter Cc: Andy Grover Cc: Clemens Ladisch Cc: Nicholas A. Bellinger Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index 0d6d7c1..f0a2a1d 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c @@ -704,16 +704,17 @@ static void session_maintenance_work(struct work_struct *work) static int tgt_agent_rw_agent_state(struct fw_card *card, int tcode, void *data, struct sbp_target_agent *agent) { - __be32 state; + int state; switch (tcode) { case TCODE_READ_QUADLET_REQUEST: pr_debug("tgt_agent AGENT_STATE READ\n"); spin_lock_bh(&agent->lock); - state = cpu_to_be32(agent->state); + state = agent->state; spin_unlock_bh(&agent->lock); - memcpy(data, &state, sizeof(state)); + + *(__be32 *)data = cpu_to_be32(state); return RCODE_COMPLETE; -- cgit v0.10.2 From e1fe2060d7e8f58a69374135e32e90f0bb79a7fd Mon Sep 17 00:00:00 2001 From: Chris Boot Date: Tue, 11 Dec 2012 21:58:48 +0000 Subject: sbp-target: fix error path in sbp_make_tpg() If the TPG memory is allocated successfully, but we fail further along in the function, a dangling pointer to freed memory is left in the TPort structure. This is mostly harmless, but does prevent re-trying the operation without first removing the TPort altogether. Reported-by: Chen Gang Signed-off-by: Chris Boot Cc: Andy Grover Cc: Nicholas A. Bellinger Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index f0a2a1d..2e8d06f 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c @@ -2208,20 +2208,23 @@ static struct se_portal_group *sbp_make_tpg( tport->mgt_agt = sbp_management_agent_register(tport); if (IS_ERR(tport->mgt_agt)) { ret = PTR_ERR(tport->mgt_agt); - kfree(tpg); - return ERR_PTR(ret); + goto out_free_tpg; } ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn, &tpg->se_tpg, (void *)tpg, TRANSPORT_TPG_TYPE_NORMAL); - if (ret < 0) { - sbp_management_agent_unregister(tport->mgt_agt); - kfree(tpg); - return ERR_PTR(ret); - } + if (ret < 0) + goto out_unreg_mgt_agt; return &tpg->se_tpg; + +out_unreg_mgt_agt: + sbp_management_agent_unregister(tport->mgt_agt); +out_free_tpg: + tport->tpg = NULL; + kfree(tpg); + return ERR_PTR(ret); } static void sbp_drop_tpg(struct se_portal_group *se_tpg) -- cgit v0.10.2 From 9f4ad44b264f8bb61ffdd607148215566568430d Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Mon, 10 Dec 2012 17:04:00 -0800 Subject: target/tcm_fc: fix the lockdep warning due to inconsistent lock state The lockdep warning below is in theory correct but it will be in really weird rare situation that ends up that deadlock since the tcm fc session is hashed based the rport id. Nonetheless, the complaining below is about rcu callback that does the transport_deregister_session() is happening in softirq, where transport_register_session() that happens earlier is not. This triggers the lockdep warning below. So, just fix this to make lockdep happy by disabling the soft irq before calling transport_register_session() in ft_prli. BTW, this was found in FCoE VN2VN over two VMs, couple of create and destroy would get this triggered. v1: was enforcing register to be in softirq context which was not righ. See, http://www.spinics.net/lists/target-devel/msg03614.html v2: following comments from Roland&Nick (thanks), it seems we don't have to do transport_deregister_session() in rcu callback, so move it into ft_sess_free() but still do kfree() of the corresponding ft_sess struct in rcu callback to make sure the ft_sess is not freed till the rcu callback. ... [ 1328.370592] scsi2 : FCoE Driver [ 1328.383429] fcoe: No FDMI support. [ 1328.384509] host2: libfc: Link up on port (000000) [ 1328.934229] host2: Assigned Port ID 00a292 [ 1357.232132] host2: rport 00a393: Remove port [ 1357.232568] host2: rport 00a393: Port sending LOGO from Ready state [ 1357.233692] host2: rport 00a393: Delete port [ 1357.234472] host2: rport 00a393: work event 3 [ 1357.234969] host2: rport 00a393: callback ev 3 [ 1357.235979] host2: rport 00a393: Received a LOGO response closed [ 1357.236706] host2: rport 00a393: work delete [ 1357.237481] [ 1357.237631] ================================= [ 1357.238064] [ INFO: inconsistent lock state ] [ 1357.238450] 3.7.0-rc7-yikvm+ #3 Tainted: G O [ 1357.238450] --------------------------------- [ 1357.238450] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 1357.238450] ksoftirqd/0/3 [HC0[0]:SC1[1]:HE0:SE0] takes: [ 1357.238450] (&(&se_tpg->session_lock)->rlock){+.?...}, at: [] transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] {SOFTIRQ-ON-W} state was registered at: [ 1357.238450] [] mark_held_locks+0x6d/0x95 [ 1357.238450] [] trace_hardirqs_on_caller+0x12d/0x197 [ 1357.238450] [] trace_hardirqs_on+0xd/0xf [ 1357.238450] [] _raw_spin_unlock_irq+0x2d/0x45 [ 1357.238450] [] __transport_register_session+0xb8/0x122 [target_core_mod] [ 1357.238450] [] transport_register_session+0x44/0x5a [target_core_mod] [ 1357.238450] [] ft_prli+0x1e3/0x275 [tcm_fc] [ 1357.238450] [] fc_rport_recv_req+0x95e/0xdc5 [libfc] [ 1357.238450] [] fc_lport_recv_els_req+0xc4/0xd5 [libfc] [ 1357.238450] [] fc_lport_recv_req+0x12f/0x18f [libfc] [ 1357.238450] [] fc_exch_recv+0x8ba/0x981 [libfc] [ 1357.238450] [] fcoe_percpu_receive_thread+0x47a/0x4e2 [fcoe] [ 1357.238450] [] kthread+0xb1/0xb9 [ 1357.238450] [] ret_from_fork+0x7c/0xb0 [ 1357.238450] irq event stamp: 275411 [ 1357.238450] hardirqs last enabled at (275410): [] rcu_process_callbacks+0x229/0x42a [ 1357.238450] hardirqs last disabled at (275411): [] _raw_spin_lock_irqsave+0x22/0x8e [ 1357.238450] softirqs last enabled at (275394): [] __do_softirq+0x246/0x26f [ 1357.238450] softirqs last disabled at (275399): [] run_ksoftirqd+0x29/0x62 [ 1357.238450] [ 1357.238450] other info that might help us debug this: [ 1357.238450] Possible unsafe locking scenario: [ 1357.238450] [ 1357.238450] CPU0 [ 1357.238450] ---- [ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); [ 1357.238450] [ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); [ 1357.238450] [ 1357.238450] *** DEADLOCK *** [ 1357.238450] [ 1357.238450] no locks held by ksoftirqd/0/3. [ 1357.238450] [ 1357.238450] stack backtrace: [ 1357.238450] Pid: 3, comm: ksoftirqd/0 Tainted: G O 3.7.0-rc7-yikvm+ #3 [ 1357.238450] Call Trace: [ 1357.238450] [] print_usage_bug+0x1f5/0x206 [ 1357.238450] [] ? save_stack_trace+0x2c/0x49 [ 1357.238450] [] ? print_irq_inversion_bug.part.14+0x1ae/0x1ae [ 1357.238450] [] mark_lock+0x106/0x258 [ 1357.238450] [] __lock_acquire+0x2e7/0xe53 [ 1357.238450] [] ? pvclock_clocksource_read+0x48/0xb4 [ 1357.238450] [] ? rcu_process_gp_end+0xc0/0xc9 [ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] lock_acquire+0x119/0x143 [ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] _raw_spin_lock_irqsave+0x54/0x8e [ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] ? rcu_process_callbacks+0x229/0x42a [ 1357.238450] [] ft_sess_rcu_free+0x17/0x24 [tcm_fc] [ 1357.238450] [] ? ft_sess_free+0x1b/0x1b [tcm_fc] [ 1357.238450] [] rcu_process_callbacks+0x260/0x42a [ 1357.238450] [] __do_softirq+0x13a/0x26f [ 1357.238450] [] ? __schedule+0x65f/0x68e [ 1357.238450] [] run_ksoftirqd+0x29/0x62 [ 1357.238450] [] smpboot_thread_fn+0x1a5/0x1aa [ 1357.238450] [] ? smpboot_unregister_percpu_thread+0x47/0x47 [ 1357.238450] [] kthread+0xb1/0xb9 [ 1357.238450] [] ? wait_for_common+0xbb/0x10a [ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 [ 1357.238450] [] ret_from_fork+0x7c/0xb0 [ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 [ 1417.440099] rport-2:0-0: blocked FC remote port time out: removing rport Signed-off-by: Yi Zou Cc: Open-FCoE Cc: Nicholas A. Bellinger Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 9585010..12d6fa2 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -430,7 +430,6 @@ static void ft_sess_rcu_free(struct rcu_head *rcu) { struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); - transport_deregister_session(sess->se_sess); kfree(sess); } @@ -438,6 +437,7 @@ static void ft_sess_free(struct kref *kref) { struct ft_sess *sess = container_of(kref, struct ft_sess, kref); + transport_deregister_session(sess->se_sess); call_rcu(&sess->rcu, ft_sess_rcu_free); } -- cgit v0.10.2 From 79e62fc3827bd437c304c1810f36896fc1e717b1 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 11 Dec 2012 16:30:53 -0800 Subject: target/iscsi_target: Add NodeACL tags for initiator group support Thanks for reviews, looking a lot better. ---- 8< ---- Initiator access config could be easier. The way other storage vendors have addressed this is to support initiator groups: the admin adds initiator WWNs to the group, and then LUN permissions can be granted for the entire group at once. Instead of changing ktarget's configfs interface, this patch keeps the configfs interface per-initiator-wwn and just adds a 'tag' field for each. This should be enough for user tools like targetcli to group initiator ACLs and sync their configurations. acl_tag is not used internally, but needs to be kept in configfs so that all user tools can avoid dependencies on each other. Code tested to work, although userspace pieces still to be implemented. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 542641c..5201d5e 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -754,9 +754,33 @@ static ssize_t lio_target_nacl_store_cmdsn_depth( TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR); +static ssize_t lio_target_nacl_show_tag( + struct se_node_acl *se_nacl, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%s", se_nacl->acl_tag); +} + +static ssize_t lio_target_nacl_store_tag( + struct se_node_acl *se_nacl, + const char *page, + size_t count) +{ + int ret; + + ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page); + + if (ret < 0) + return ret; + return count; +} + +TF_NACL_BASE_ATTR(lio_target, tag, S_IRUGO | S_IWUSR); + static struct configfs_attribute *lio_target_initiator_attrs[] = { &lio_target_nacl_info.attr, &lio_target_nacl_cmdsn_depth.attr, + &lio_target_nacl_tag.attr, NULL, }; diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 0163309..5192ac0 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -616,6 +616,29 @@ int core_tpg_set_initiator_node_queue_depth( } EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); +/* core_tpg_set_initiator_node_tag(): + * + * Initiator nodeacl tags are not used internally, but may be used by + * userspace to emulate aliases or groups. + * Returns length of newly-set tag or -EINVAL. + */ +int core_tpg_set_initiator_node_tag( + struct se_portal_group *tpg, + struct se_node_acl *acl, + const char *new_tag) +{ + if (strlen(new_tag) >= MAX_ACL_TAG_SIZE) + return -EINVAL; + + if (!strncmp("NULL", new_tag, 4)) { + acl->acl_tag[0] = '\0'; + return 0; + } + + return snprintf(acl->acl_tag, MAX_ACL_TAG_SIZE, "%s", new_tag); +} +EXPORT_SYMBOL(core_tpg_set_initiator_node_tag); + static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) { /* Set in core_dev_setup_virtual_lun0() */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1346ee0..7cae236 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -507,6 +507,8 @@ struct se_node_acl { bool acl_stop:1; u32 queue_depth; u32 acl_index; +#define MAX_ACL_TAG_SIZE 64 + char acl_tag[MAX_ACL_TAG_SIZE]; u64 num_cmds; u64 read_bytes; u64 write_bytes; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 9087b20..aaa1ee6 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -142,6 +142,8 @@ int core_tpg_del_initiator_node_acl(struct se_portal_group *, struct se_node_acl *, int); int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *, unsigned char *, u32, int); +int core_tpg_set_initiator_node_tag(struct se_portal_group *, + struct se_node_acl *, const char *); int core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *, struct se_portal_group *, void *, int); int core_tpg_deregister(struct se_portal_group *); -- cgit v0.10.2