diff options
Diffstat (limited to 'drivers/target/target_core_configfs.c')
| -rw-r--r-- | drivers/target/target_core_configfs.c | 1167 |
1 files changed, 594 insertions, 573 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 6e043eeb1db..bf55c5a04cf 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-2013 Datera, Inc. * * Nicholas A. Bellinger <nab@kernel.org> * @@ -49,11 +48,12 @@ #include "target_core_alua.h" #include "target_core_pr.h" #include "target_core_rd.h" +#include "target_core_xcopy.h" extern struct t10_alua_lu_gp *default_lu_gp; -static struct list_head g_tf_list; -static struct mutex g_tf_lock; +static LIST_HEAD(g_tf_list); +static DEFINE_MUTEX(g_tf_lock); struct target_core_configfs_attribute { struct configfs_attribute attr; @@ -177,16 +177,16 @@ static struct config_group *target_core_register_fabric( * struct target_fabric_configfs *tf will contain a usage reference. */ pr_debug("Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n", - &TF_CIT_TMPL(tf)->tfc_wwn_cit); + &tf->tf_cit_tmpl.tfc_wwn_cit); tf->tf_group.default_groups = tf->tf_default_groups; tf->tf_group.default_groups[0] = &tf->tf_disc_group; tf->tf_group.default_groups[1] = NULL; config_group_init_type_name(&tf->tf_group, name, - &TF_CIT_TMPL(tf)->tfc_wwn_cit); + &tf->tf_cit_tmpl.tfc_wwn_cit); config_group_init_type_name(&tf->tf_disc_group, "discovery_auth", - &TF_CIT_TMPL(tf)->tfc_discovery_cit); + &tf->tf_cit_tmpl.tfc_discovery_cit); pr_debug("Target_Core_ConfigFS: REGISTER -> Allocated Fabric:" " %s\n", tf->tf_group.cg_item.ci_name); @@ -269,7 +269,7 @@ static struct configfs_subsystem target_core_fabrics = { }, }; -static struct configfs_subsystem *target_core_subsystem[] = { +struct configfs_subsystem *target_core_subsystem[] = { &target_core_fabrics, NULL, }; @@ -421,18 +421,6 @@ static int target_fabric_tf_ops_check( pr_err("Missing tfo->close_session()\n"); return -EINVAL; } - if (!tfo->stop_session) { - pr_err("Missing tfo->stop_session()\n"); - return -EINVAL; - } - if (!tfo->fall_back_to_erl0) { - pr_err("Missing tfo->fall_back_to_erl0()\n"); - return -EINVAL; - } - if (!tfo->sess_logged_in) { - pr_err("Missing tfo->sess_logged_in()\n"); - return -EINVAL; - } if (!tfo->sess_get_index) { pr_err("Missing tfo->sess_get_index()\n"); return -EINVAL; @@ -469,16 +457,8 @@ static int target_fabric_tf_ops_check( pr_err("Missing tfo->queue_tm_rsp()\n"); return -EINVAL; } - if (!tfo->set_fabric_sense_len) { - pr_err("Missing tfo->set_fabric_sense_len()\n"); - return -EINVAL; - } - if (!tfo->get_fabric_sense_len) { - pr_err("Missing tfo->get_fabric_sense_len()\n"); - return -EINVAL; - } - if (!tfo->is_state_remove) { - pr_err("Missing tfo->is_state_remove()\n"); + if (!tfo->aborted_task) { + pr_err("Missing tfo->aborted_task()\n"); return -EINVAL; } /* @@ -589,21 +569,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) \ @@ -612,26 +579,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); \ + ret = kstrtoul(page, 0, &val); \ if (ret < 0) { \ - spin_unlock(&se_dev->se_dev_lock); \ - pr_err("strict_strtoul() failed with" \ + pr_err("kstrtoul() 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; \ } @@ -657,6 +614,9 @@ static struct target_core_dev_attrib_attribute \ __CONFIGFS_EATTR_RO(_name, \ target_core_dev_show_attr_##_name); +DEF_DEV_ATTRIB(emulate_model_alias); +SE_DEV_ATTR(emulate_model_alias, S_IRUGO | S_IWUSR); + DEF_DEV_ATTRIB(emulate_dpo); SE_DEV_ATTR(emulate_dpo, S_IRUGO | S_IWUSR); @@ -681,6 +641,21 @@ SE_DEV_ATTR(emulate_tpu, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(emulate_tpws); SE_DEV_ATTR(emulate_tpws, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(emulate_caw); +SE_DEV_ATTR(emulate_caw, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB(emulate_3pc); +SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB(pi_prot_type); +SE_DEV_ATTR(pi_prot_type, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB_RO(hw_pi_prot_type); +SE_DEV_ATTR_RO(hw_pi_prot_type); + +DEF_DEV_ATTRIB(pi_prot_format); +SE_DEV_ATTR(pi_prot_format, S_IRUGO | S_IWUSR); + DEF_DEV_ATTRIB(enforce_pr_isids); SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); @@ -699,8 +674,8 @@ SE_DEV_ATTR(block_size, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB_RO(hw_max_sectors); SE_DEV_ATTR_RO(hw_max_sectors); -DEF_DEV_ATTRIB(max_sectors); -SE_DEV_ATTR(max_sectors, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(fabric_max_sectors); +SE_DEV_ATTR(fabric_max_sectors, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(optimal_sectors); SE_DEV_ATTR(optimal_sectors, S_IRUGO | S_IWUSR); @@ -723,9 +698,13 @@ 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[] = { + &target_core_dev_attrib_emulate_model_alias.attr, &target_core_dev_attrib_emulate_dpo.attr, &target_core_dev_attrib_emulate_fua_write.attr, &target_core_dev_attrib_emulate_fua_read.attr, @@ -734,13 +713,18 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { &target_core_dev_attrib_emulate_tas.attr, &target_core_dev_attrib_emulate_tpu.attr, &target_core_dev_attrib_emulate_tpws.attr, + &target_core_dev_attrib_emulate_caw.attr, + &target_core_dev_attrib_emulate_3pc.attr, + &target_core_dev_attrib_pi_prot_type.attr, + &target_core_dev_attrib_hw_pi_prot_type.attr, + &target_core_dev_attrib_pi_prot_format.attr, &target_core_dev_attrib_enforce_pr_isids.attr, &target_core_dev_attrib_is_nonrot.attr, &target_core_dev_attrib_emulate_rest_reord.attr, &target_core_dev_attrib_hw_block_size.attr, &target_core_dev_attrib_block_size.attr, &target_core_dev_attrib_hw_max_sectors.attr, - &target_core_dev_attrib_max_sectors.attr, + &target_core_dev_attrib_fabric_max_sectors.attr, &target_core_dev_attrib_optimal_sectors.attr, &target_core_dev_attrib_hw_queue_depth.attr, &target_core_dev_attrib_queue_depth.attr, @@ -748,6 +732,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, }; @@ -788,13 +773,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]); } @@ -804,8 +782,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]; /* @@ -818,7 +795,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; @@ -835,15 +812,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. * @@ -852,12 +827,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; } @@ -871,16 +846,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); @@ -918,16 +887,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) \ @@ -1027,7 +990,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, \ @@ -1039,149 +1002,90 @@ 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; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; 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); + core_pr_dump_initiator_port(pr_reg, i_buf, 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; + se_nacl->initiatorname, i_buf); } -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_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; + int ret; - switch (su_dev->t10_pr.res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr, - page, &len); - break; - case SPC2_RESERVATIONS: - target_core_dev_pr_show_spc2_res(su_dev->se_dev_ptr, - 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); -/* - * 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) - 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; } 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) - 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); @@ -1190,10 +1094,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; @@ -1201,20 +1103,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; - dev = su_dev->se_dev_ptr; - if (!dev) - return -ENODEV; - - if (su_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; @@ -1224,52 +1119,42 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( " Target Node Endpoint: %s\n", tfo->get_fabric_name(), tfo->tpg_get_wwn(se_tpg)); len += sprintf(page+len, "SPC-3 Reservation: Relative Port" - " Identifer Tag: %hu %s Portal Group Tag: %hu" + " Identifier Tag: %hu %s Portal Group Tag: %hu" " %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; } 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; unsigned char buf[384]; char i_buf[PR_REG_ISID_ID_LEN]; 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) - return len; + int reg_count = 0; 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); memset(i_buf, 0, PR_REG_ISID_ID_LEN); tfo = pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); sprintf(buf, "%s Node: %s%s Key: 0x%016Lx PRgen: 0x%08x\n", tfo->get_fabric_name(), - pr_reg->pr_reg_nacl->initiatorname, (prf_isid) ? - &i_buf[0] : "", pr_reg->pr_res_key, + pr_reg->pr_reg_nacl->initiatorname, i_buf, pr_reg->pr_res_key, pr_reg->pr_res_generation); if (len + strlen(buf) >= PAGE_SIZE) @@ -1278,7 +1163,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"); @@ -1288,88 +1173,48 @@ 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) - 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; } 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) { - 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); -/* - * 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->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) 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); @@ -1378,13 +1223,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->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "Ready to process PR APTPL metadata..\n"); @@ -1416,11 +1257,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; @@ -1432,14 +1272,12 @@ 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->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; + if (dev->dev_reservation_flags & DRF_SPC2_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; @@ -1497,9 +1335,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - ret = strict_strtoull(arg_p, 0, &tmp_ll); + ret = kstrtoull(arg_p, 0, &tmp_ll); if (ret < 0) { - pr_err("strict_strtoull() failed for" + pr_err("kstrtoull() failed for" " sa_res_key=\n"); goto out; } @@ -1582,7 +1420,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: @@ -1597,7 +1435,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, @@ -1629,18 +1467,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; } @@ -1657,17 +1491,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 = { @@ -1680,12 +1507,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( @@ -1693,8 +1520,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)) { @@ -1704,19 +1531,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; } @@ -1731,12 +1557,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( @@ -1744,8 +1570,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)) { @@ -1755,19 +1581,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; } @@ -1780,16 +1606,21 @@ static struct target_core_configfs_attribute target_core_attr_dev_udev_path = { .store = target_core_store_dev_udev_path, }; +static ssize_t target_core_show_dev_enable(void *p, char *page) +{ + struct se_device *dev = p; + + return snprintf(page, PAGE_SIZE, "%d\n", !!(dev->dev_flags & DF_CONFIGURED)); +} + static ssize_t target_core_store_dev_enable( void *p, 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) { @@ -1797,58 +1628,32 @@ 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; } static struct target_core_configfs_attribute target_core_attr_dev_enable = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "enable", - .ca_mode = S_IWUSR }, - .show = NULL, + .ca_mode = S_IRUGO | S_IWUSR }, + .show = target_core_show_dev_enable, .store = target_core_store_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) - 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; @@ -1867,24 +1672,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; + lu_gp_mem = dev->dev_alua_lu_gp_mem; + if (!lu_gp_mem) + return 0; - if (su_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)); - return -EINVAL; - } if (count > LU_GROUP_NAME_BUF) { pr_err("ALUA LU Group Alias too large!\n"); return -EINVAL; @@ -1905,14 +1703,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; @@ -1926,7 +1716,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); @@ -1951,7 +1741,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); @@ -1967,6 +1757,176 @@ static struct target_core_configfs_attribute target_core_attr_dev_alua_lu_gp = { .store = target_core_store_alua_lu_gp, }; +static ssize_t target_core_show_dev_lba_map(void *p, char *page) +{ + struct se_device *dev = p; + struct t10_alua_lba_map *map; + struct t10_alua_lba_map_member *mem; + char *b = page; + int bl = 0; + char state; + + spin_lock(&dev->t10_alua.lba_map_lock); + if (!list_empty(&dev->t10_alua.lba_map_list)) + bl += sprintf(b + bl, "%u %u\n", + dev->t10_alua.lba_map_segment_size, + dev->t10_alua.lba_map_segment_multiplier); + list_for_each_entry(map, &dev->t10_alua.lba_map_list, lba_map_list) { + bl += sprintf(b + bl, "%llu %llu", + map->lba_map_first_lba, map->lba_map_last_lba); + list_for_each_entry(mem, &map->lba_map_mem_list, + lba_map_mem_list) { + switch (mem->lba_map_mem_alua_state) { + case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: + state = 'O'; + break; + case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: + state = 'A'; + break; + case ALUA_ACCESS_STATE_STANDBY: + state = 'S'; + break; + case ALUA_ACCESS_STATE_UNAVAILABLE: + state = 'U'; + break; + default: + state = '.'; + break; + } + bl += sprintf(b + bl, " %d:%c", + mem->lba_map_mem_alua_pg_id, state); + } + bl += sprintf(b + bl, "\n"); + } + spin_unlock(&dev->t10_alua.lba_map_lock); + return bl; +} + +static ssize_t target_core_store_dev_lba_map( + void *p, + const char *page, + size_t count) +{ + struct se_device *dev = p; + struct t10_alua_lba_map *lba_map = NULL; + struct list_head lba_list; + char *map_entries, *ptr; + char state; + int pg_num = -1, pg; + int ret = 0, num = 0, pg_id, alua_state; + unsigned long start_lba = -1, end_lba = -1; + unsigned long segment_size = -1, segment_mult = -1; + + map_entries = kstrdup(page, GFP_KERNEL); + if (!map_entries) + return -ENOMEM; + + INIT_LIST_HEAD(&lba_list); + while ((ptr = strsep(&map_entries, "\n")) != NULL) { + if (!*ptr) + continue; + + if (num == 0) { + if (sscanf(ptr, "%lu %lu\n", + &segment_size, &segment_mult) != 2) { + pr_err("Invalid line %d\n", num); + ret = -EINVAL; + break; + } + num++; + continue; + } + if (sscanf(ptr, "%lu %lu", &start_lba, &end_lba) != 2) { + pr_err("Invalid line %d\n", num); + ret = -EINVAL; + break; + } + ptr = strchr(ptr, ' '); + if (!ptr) { + pr_err("Invalid line %d, missing end lba\n", num); + ret = -EINVAL; + break; + } + ptr++; + ptr = strchr(ptr, ' '); + if (!ptr) { + pr_err("Invalid line %d, missing state definitions\n", + num); + ret = -EINVAL; + break; + } + ptr++; + lba_map = core_alua_allocate_lba_map(&lba_list, + start_lba, end_lba); + if (IS_ERR(lba_map)) { + ret = PTR_ERR(lba_map); + break; + } + pg = 0; + while (sscanf(ptr, "%d:%c", &pg_id, &state) == 2) { + switch (state) { + case 'O': + alua_state = ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED; + break; + case 'A': + alua_state = ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED; + break; + case 'S': + alua_state = ALUA_ACCESS_STATE_STANDBY; + break; + case 'U': + alua_state = ALUA_ACCESS_STATE_UNAVAILABLE; + break; + default: + pr_err("Invalid ALUA state '%c'\n", state); + ret = -EINVAL; + goto out; + } + + ret = core_alua_allocate_lba_map_mem(lba_map, + pg_id, alua_state); + if (ret) { + pr_err("Invalid target descriptor %d:%c " + "at line %d\n", + pg_id, state, num); + break; + } + pg++; + ptr = strchr(ptr, ' '); + if (ptr) + ptr++; + else + break; + } + if (pg_num == -1) + pg_num = pg; + else if (pg != pg_num) { + pr_err("Only %d from %d port groups definitions " + "at line %d\n", pg, pg_num, num); + ret = -EINVAL; + break; + } + num++; + } +out: + if (ret) { + core_alua_free_lba_map(&lba_list); + count = ret; + } else + core_alua_set_lba_map(dev, &lba_list, + segment_size, segment_mult); + kfree(map_entries); + return count; +} + +static struct target_core_configfs_attribute target_core_attr_dev_lba_map = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "lba_map", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = target_core_show_dev_lba_map, + .store = target_core_store_dev_lba_map, +}; + static struct configfs_attribute *lio_core_dev_attrs[] = { &target_core_attr_dev_info.attr, &target_core_attr_dev_control.attr, @@ -1974,74 +1934,50 @@ static struct configfs_attribute *lio_core_dev_attrs[] = { &target_core_attr_dev_udev_path.attr, &target_core_attr_dev_enable.attr, &target_core_attr_dev_alua_lu_gp.attr, + &target_core_attr_dev_lba_map.attr, NULL, }; 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 = { @@ -2096,11 +2032,11 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id( unsigned long lu_gp_id; int ret; - ret = strict_strtoul(page, 0, &lu_gp_id); + ret = kstrtoul(page, 0, &lu_gp_id); if (ret < 0) { - pr_err("strict_strtoul() returned %d for" + pr_err("kstrtoul() returned %d for" " lu_gp_id\n", ret); - return -EINVAL; + return ret; } if (lu_gp_id > 0x0000ffff) { pr_err("ALUA lu_gp_id: %lu exceeds maximum:" @@ -2131,7 +2067,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]; @@ -2141,12 +2076,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) { @@ -2284,31 +2218,43 @@ 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; if (!tg_pt_gp->tg_pt_gp_valid_id) { - pr_err("Unable to do implict ALUA on non valid" + pr_err("Unable to do implicit ALUA on non valid" " tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id); return -EINVAL; } + if (!(dev->dev_flags & DF_CONFIGURED)) { + pr_err("Unable to set alua_access_state while device is" + " not configured\n"); + return -ENODEV; + } - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { pr_err("Unable to extract new ALUA access state from" " %s\n", page); - return -EINVAL; + return ret; } new_state = (int)tmp; - if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) { - pr_err("Unable to process implict configfs ALUA" - " transition while TPGS_IMPLICT_ALUA is diabled\n"); + if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) { + pr_err("Unable to process implicit configfs ALUA" + " transition while TPGS_IMPLICIT_ALUA is disabled\n"); + return -EINVAL; + } + if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA && + new_state == ALUA_ACCESS_STATE_LBA_DEPENDENT) { + /* LBA DEPENDENT is only allowed with implicit ALUA */ + pr_err("Unable to process implicit configfs ALUA transition" + " while explicit ALUA management is enabled\n"); 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; } @@ -2341,17 +2287,17 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status( return -EINVAL; } - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { pr_err("Unable to extract new ALUA access status" " from %s\n", page); - return -EINVAL; + return ret; } new_status = (int)tmp; if ((new_status != ALUA_STATUS_NONE) && - (new_status != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) && - (new_status != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) { + (new_status != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && + (new_status != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) { pr_err("Illegal ALUA access status: 0x%02x\n", new_status); return -EINVAL; @@ -2384,6 +2330,90 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type( SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR); /* + * alua_supported_states + */ + +#define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit) \ +static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_support_##_name( \ + struct t10_alua_tg_pt_gp *t, char *p) \ +{ \ + return sprintf(p, "%d\n", !!(t->_var & _bit)); \ +} + +#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit) \ +static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\ + struct t10_alua_tg_pt_gp *t, const char *p, size_t c) \ +{ \ + unsigned long tmp; \ + int ret; \ + \ + if (!t->tg_pt_gp_valid_id) { \ + pr_err("Unable to do set ##_name ALUA state on non" \ + " valid tg_pt_gp ID: %hu\n", \ + t->tg_pt_gp_valid_id); \ + return -EINVAL; \ + } \ + \ + ret = kstrtoul(p, 0, &tmp); \ + if (ret < 0) { \ + pr_err("Invalid value '%s', must be '0' or '1'\n", p); \ + return -EINVAL; \ + } \ + if (tmp > 1) { \ + pr_err("Invalid value '%ld', must be '0' or '1'\n", tmp); \ + return -EINVAL; \ + } \ + if (!tmp) \ + t->_var |= _bit; \ + else \ + t->_var &= ~_bit; \ + \ + return c; \ +} + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(transitioning, + tg_pt_gp_alua_supported_states, ALUA_T_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(transitioning, + tg_pt_gp_alua_supported_states, ALUA_T_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_transitioning, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(offline, + tg_pt_gp_alua_supported_states, ALUA_O_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(offline, + tg_pt_gp_alua_supported_states, ALUA_O_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_offline, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent, + tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent, + tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable, + tg_pt_gp_alua_supported_states, ALUA_U_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(unavailable, + tg_pt_gp_alua_supported_states, ALUA_U_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_unavailable, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(standby, + tg_pt_gp_alua_supported_states, ALUA_S_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(standby, + tg_pt_gp_alua_supported_states, ALUA_S_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_standby, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_optimized, + tg_pt_gp_alua_supported_states, ALUA_AO_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(active_optimized, + tg_pt_gp_alua_supported_states, ALUA_AO_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_optimized, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_nonoptimized, + tg_pt_gp_alua_supported_states, ALUA_AN_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(active_nonoptimized, + tg_pt_gp_alua_supported_states, ALUA_AN_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_nonoptimized, S_IRUGO | S_IWUSR); + +/* * alua_write_metadata */ static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata( @@ -2401,10 +2431,10 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata( unsigned long tmp; int ret; - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { pr_err("Unable to extract alua_write_metadata\n"); - return -EINVAL; + return ret; } if ((tmp != 0) && (tmp != 1)) { @@ -2463,6 +2493,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs( SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR); /* + * implicit_trans_secs + */ +static ssize_t target_core_alua_tg_pt_gp_show_attr_implicit_trans_secs( + struct t10_alua_tg_pt_gp *tg_pt_gp, + char *page) +{ + return core_alua_show_implicit_trans_secs(tg_pt_gp, page); +} + +static ssize_t target_core_alua_tg_pt_gp_store_attr_implicit_trans_secs( + struct t10_alua_tg_pt_gp *tg_pt_gp, + const char *page, + size_t count) +{ + return core_alua_store_implicit_trans_secs(tg_pt_gp, page, count); +} + +SE_DEV_ALUA_TG_PT_ATTR(implicit_trans_secs, S_IRUGO | S_IWUSR); + +/* * preferred */ @@ -2505,11 +2555,11 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id( unsigned long tg_pt_gp_id; int ret; - ret = strict_strtoul(page, 0, &tg_pt_gp_id); + ret = kstrtoul(page, 0, &tg_pt_gp_id); if (ret < 0) { - pr_err("strict_strtoul() returned %d for" + pr_err("kstrtoul() returned %d for" " tg_pt_gp_id\n", ret); - return -EINVAL; + return ret; } if (tg_pt_gp_id > 0x0000ffff) { pr_err("ALUA tg_pt_gp_id: %lu exceeds maximum:" @@ -2583,9 +2633,17 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = { &target_core_alua_tg_pt_gp_alua_access_state.attr, &target_core_alua_tg_pt_gp_alua_access_status.attr, &target_core_alua_tg_pt_gp_alua_access_type.attr, + &target_core_alua_tg_pt_gp_alua_support_transitioning.attr, + &target_core_alua_tg_pt_gp_alua_support_offline.attr, + &target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr, + &target_core_alua_tg_pt_gp_alua_support_unavailable.attr, + &target_core_alua_tg_pt_gp_alua_support_standby.attr, + &target_core_alua_tg_pt_gp_alua_support_active_nonoptimized.attr, + &target_core_alua_tg_pt_gp_alua_support_active_optimized.attr, &target_core_alua_tg_pt_gp_alua_write_metadata.attr, &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, + &target_core_alua_tg_pt_gp_implicit_trans_secs.attr, &target_core_alua_tg_pt_gp_preferred.attr, &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, &target_core_alua_tg_pt_gp_members.attr, @@ -2623,11 +2681,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; @@ -2724,10 +2781,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; @@ -2740,120 +2797,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_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, + dev = target_alloc_device(hba, name); + if (!dev) + goto out_unlock; + + dev_cg = &dev->dev_group; + + dev_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6, 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->default_groups = kzalloc(sizeof(struct config_group) * 2, + tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; + 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->" "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->default_groups = kzalloc(sizeof(struct config_group) * 4, + dev_stat_grp = &dev->dev_stat_grps.stat_group; + 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"); - 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); } @@ -2862,20 +2879,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 se_subsystem_api *t; 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); - t = hba->transport; - 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; @@ -2883,7 +2899,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; @@ -2894,17 +2910,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); @@ -2961,19 +2975,16 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba, if (transport->pmode_enable_hba == NULL) return -EINVAL; - ret = strict_strtoul(page, 0, &mode_flag); + ret = kstrtoul(page, 0, &mode_flag); if (ret < 0) { pr_err("Unable to extract hba mode flag: %d\n", ret); - return -EINVAL; + return ret; } - 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) @@ -3055,11 +3066,11 @@ static struct config_group *target_core_call_addhbatotarget( str++; /* Skip to start of plugin dependent ID */ } - ret = strict_strtoul(str, 0, &plugin_dep_id); + ret = kstrtoul(str, 0, &plugin_dep_id); if (ret < 0) { - pr_err("strict_strtoul() returned %d for" + pr_err("kstrtoul() returned %d for" " plugin_dep_id\n", ret); - return ERR_PTR(-EINVAL); + return ERR_PTR(ret); } /* * Load up TCM subsystem plugins if they have not already been loaded. @@ -3117,8 +3128,6 @@ static int __init target_core_init_configfs(void) config_group_init(&subsys->su_group); mutex_init(&subsys->su_mutex); - INIT_LIST_HEAD(&g_tf_list); - mutex_init(&g_tf_lock); ret = init_se_kmem_caches(); if (ret < 0) return ret; @@ -3127,10 +3136,11 @@ 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"); + ret = -ENOMEM; goto out_global; } @@ -3142,10 +3152,11 @@ 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"); + ret = -ENOMEM; goto out_global; } config_group_init_type_name(&alua_group, @@ -3157,10 +3168,11 @@ 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"); + ret = -ENOMEM; goto out_global; } @@ -3172,14 +3184,17 @@ static int __init target_core_init_configfs(void) * Add core/alua/lu_gps/default_lu_gp */ lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1); - if (IS_ERR(lu_gp)) + if (IS_ERR(lu_gp)) { + ret = -ENOMEM; goto out_global; + } 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"); + ret = -ENOMEM; goto out_global; } @@ -3207,7 +3222,12 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) + goto out; + + ret = target_xcopy_setup_pt(); + if (ret < 0) goto out; return 0; @@ -3282,6 +3302,7 @@ static void __exit target_core_exit_configfs(void) core_dev_release_virtual_lun0(); rd_module_exit(); + target_xcopy_release_pt(); release_se_kmem_caches(); } |
