예제 #1
0
파일: tcm_loop.c 프로젝트: 383530895/linux
static struct se_portal_group *tcm_loop_make_naa_tpg(
	struct se_wwn *wwn,
	struct config_group *group,
	const char *name)
{
	struct tcm_loop_hba *tl_hba = container_of(wwn,
			struct tcm_loop_hba, tl_hba_wwn);
	struct tcm_loop_tpg *tl_tpg;
	char *tpgt_str, *end_ptr;
	int ret;
	unsigned short int tpgt;

	tpgt_str = strstr(name, "tpgt_");
	if (!tpgt_str) {
		pr_err("Unable to locate \"tpgt_#\" directory"
				" group\n");
		return ERR_PTR(-EINVAL);
	}
	tpgt_str += 5; /* Skip ahead of "tpgt_" */
	tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);

	if (tpgt >= TL_TPGS_PER_HBA) {
		pr_err("Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
				" %u\n", tpgt, TL_TPGS_PER_HBA);
		return ERR_PTR(-EINVAL);
	}
	tl_tpg = &tl_hba->tl_hba_tpgs[tpgt];
	tl_tpg->tl_hba = tl_hba;
	tl_tpg->tl_tpgt = tpgt;
	/*
	 * Register the tl_tpg as a emulated SAS TCM Target Endpoint
	 */
	ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
			wwn, &tl_tpg->tl_se_tpg, tl_tpg,
			TRANSPORT_TPG_TYPE_NORMAL);
	if (ret < 0)
		return ERR_PTR(-ENOMEM);

	pr_debug("TCM_Loop_ConfigFS: Allocated Emulated %s"
		" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
		config_item_name(&wwn->wwn_group.cg_item), tpgt);

	return &tl_tpg->tl_se_tpg;
}
예제 #2
0
파일: tcm_loop.c 프로젝트: Chong-Li/cse522
static struct se_portal_group *tcm_loop_make_naa_tpg(
	struct se_wwn *wwn,
	struct config_group *group,
	const char *name)
{
	struct tcm_loop_hba *tl_hba = container_of(wwn,
			struct tcm_loop_hba, tl_hba_wwn);
	struct tcm_loop_tpg *tl_tpg;
	int ret;
	unsigned long tpgt;

	if (strstr(name, "tpgt_") != name) {
		pr_err("Unable to locate \"tpgt_#\" directory"
				" group\n");
		return ERR_PTR(-EINVAL);
	}
	if (kstrtoul(name+5, 10, &tpgt))
		return ERR_PTR(-EINVAL);

	if (tpgt >= TL_TPGS_PER_HBA) {
		pr_err("Passed tpgt: %lu exceeds TL_TPGS_PER_HBA:"
				" %u\n", tpgt, TL_TPGS_PER_HBA);
		return ERR_PTR(-EINVAL);
	}
	tl_tpg = &tl_hba->tl_hba_tpgs[tpgt];
	tl_tpg->tl_hba = tl_hba;
	tl_tpg->tl_tpgt = tpgt;
	/*
	 * Register the tl_tpg as a emulated TCM Target Endpoint
	 */
	ret = core_tpg_register(wwn, &tl_tpg->tl_se_tpg, tl_hba->tl_proto_id);
	if (ret < 0)
		return ERR_PTR(-ENOMEM);

	pr_debug("TCM_Loop_ConfigFS: Allocated Emulated %s"
		" Target Port %s,t,0x%04lx\n", tcm_loop_dump_proto_id(tl_hba),
		config_item_name(&wwn->wwn_group.cg_item), tpgt);

	return &tl_tpg->tl_se_tpg;
}
예제 #3
0
static int tcm_loop_drop_nexus(
	struct tcm_loop_tpg *tpg)
{
	struct se_session *se_sess;
	struct tcm_loop_nexus *tl_nexus;
	struct tcm_loop_hba *tl_hba = tpg->tl_hba;

	if (!tl_hba)
		return -ENODEV;

	tl_nexus = tl_hba->tl_nexus;
	if (!tl_nexus)
		return -ENODEV;

	se_sess = tl_nexus->se_sess;
	if (!se_sess)
		return -ENODEV;

	if (atomic_read(&tpg->tl_tpg_port_count)) {
		pr_err("Unable to remove TCM_Loop I_T Nexus with"
			" active TPG port count: %d\n",
			atomic_read(&tpg->tl_tpg_port_count));
		return -EPERM;
	}

	pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
		" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
		tl_nexus->se_sess->se_node_acl->initiatorname);
	/*
	 * Release the SCSI I_T Nexus to the emulated SAS Target Port
	 */
	transport_deregister_session(tl_nexus->se_sess);
	tpg->tl_hba->tl_nexus = NULL;
	kfree(tl_nexus);
	return 0;
}
예제 #4
0
void tcm_loop_drop_naa_tpg(
	struct se_portal_group *se_tpg)
{
	struct se_wwn *wwn = se_tpg->se_tpg_wwn;
	struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
				struct tcm_loop_tpg, tl_se_tpg);
	struct tcm_loop_hba *tl_hba;
	unsigned short tpgt;

	tl_hba = tl_tpg->tl_hba;
	tpgt = tl_tpg->tl_tpgt;
	/*
	 * Release the I_T Nexus for the Virtual SAS link if present
	 */
	tcm_loop_drop_nexus(tl_tpg);
	/*
	 * Deregister the tl_tpg as a emulated SAS TCM Target Endpoint
	 */
	core_tpg_deregister(se_tpg);

	pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s"
		" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
		config_item_name(&wwn->wwn_group.cg_item), tpgt);
}
예제 #5
0
struct se_wwn *tcm_loop_make_scsi_hba(
    struct target_fabric_configfs *tf,
    struct config_group *group,
    const char *name)
{
    struct tcm_loop_hba *tl_hba;
    struct Scsi_Host *sh;
    char *ptr;
    int ret, off = 0;

    tl_hba = kzalloc(sizeof(struct tcm_loop_hba), GFP_KERNEL);
    if (!tl_hba) {
        pr_err("Unable to allocate struct tcm_loop_hba\n");
        return ERR_PTR(-ENOMEM);
    }
    /*
     * Determine the emulated Protocol Identifier and Target Port Name
     * based on the incoming configfs directory name.
     */
    ptr = strstr(name, "naa.");
    if (ptr) {
        tl_hba->tl_proto_id = SCSI_PROTOCOL_SAS;
        goto check_len;
    }
    ptr = strstr(name, "fc.");
    if (ptr) {
        tl_hba->tl_proto_id = SCSI_PROTOCOL_FCP;
        off = 3; /* Skip over "fc." */
        goto check_len;
    }
    ptr = strstr(name, "iqn.");
    if (!ptr) {
        pr_err("Unable to locate prefix for emulated Target "
               "Port: %s\n", name);
        ret = -EINVAL;
        goto out;
    }
    tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;

check_len:
    if (strlen(name) >= TL_WWN_ADDR_LEN) {
        pr_err("Emulated NAA %s Address: %s, exceeds"
               " max: %d\n", name, tcm_loop_dump_proto_id(tl_hba),
               TL_WWN_ADDR_LEN);
        ret = -EINVAL;
        goto out;
    }
    snprintf(&tl_hba->tl_wwn_address[0], TL_WWN_ADDR_LEN, "%s", &name[off]);

    /*
     * Call device_register(tl_hba->dev) to register the emulated
     * Linux/SCSI LLD of type struct Scsi_Host at tl_hba->sh after
     * device_register() callbacks in tcm_loop_driver_probe()
     */
    ret = tcm_loop_setup_hba_bus(tl_hba, tcm_loop_hba_no_cnt);
    if (ret)
        goto out;

    sh = tl_hba->sh;
    tcm_loop_hba_no_cnt++;
    pr_debug("TCM_Loop_ConfigFS: Allocated emulated Target"
             " %s Address: %s at Linux/SCSI Host ID: %d\n",
             tcm_loop_dump_proto_id(tl_hba), name, sh->host_no);

    return &tl_hba->tl_hba_wwn;
out:
    kfree(tl_hba);
    return ERR_PTR(ret);
}
예제 #6
0
static ssize_t tcm_loop_tpg_store_nexus(
    struct se_portal_group *se_tpg,
    const char *page,
    size_t count)
{
    struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
                                  struct tcm_loop_tpg, tl_se_tpg);
    struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
    unsigned char i_port[TL_WWN_ADDR_LEN], *ptr, *port_ptr;
    int ret;
    /*
     * Shutdown the active I_T nexus if 'NULL' is passed..
     */
    if (!strncmp(page, "NULL", 4)) {
        ret = tcm_loop_drop_nexus(tl_tpg);
        return (!ret) ? count : ret;
    }
    /*
     * Otherwise make sure the passed virtual Initiator port WWN matches
     * the fabric protocol_id set in tcm_loop_make_scsi_hba(), and call
     * tcm_loop_make_nexus()
     */
    if (strlen(page) >= TL_WWN_ADDR_LEN) {
        pr_err("Emulated NAA Sas Address: %s, exceeds"
               " max: %d\n", page, TL_WWN_ADDR_LEN);
        return -EINVAL;
    }
    snprintf(&i_port[0], TL_WWN_ADDR_LEN, "%s", page);

    ptr = strstr(i_port, "naa.");
    if (ptr) {
        if (tl_hba->tl_proto_id != SCSI_PROTOCOL_SAS) {
            pr_err("Passed SAS Initiator Port %s does not"
                   " match target port protoid: %s\n", i_port,
                   tcm_loop_dump_proto_id(tl_hba));
            return -EINVAL;
        }
        port_ptr = &i_port[0];
        goto check_newline;
    }
    ptr = strstr(i_port, "fc.");
    if (ptr) {
        if (tl_hba->tl_proto_id != SCSI_PROTOCOL_FCP) {
            pr_err("Passed FCP Initiator Port %s does not"
                   " match target port protoid: %s\n", i_port,
                   tcm_loop_dump_proto_id(tl_hba));
            return -EINVAL;
        }
        port_ptr = &i_port[3]; /* Skip over "fc." */
        goto check_newline;
    }
    ptr = strstr(i_port, "iqn.");
    if (ptr) {
        if (tl_hba->tl_proto_id != SCSI_PROTOCOL_ISCSI) {
            pr_err("Passed iSCSI Initiator Port %s does not"
                   " match target port protoid: %s\n", i_port,
                   tcm_loop_dump_proto_id(tl_hba));
            return -EINVAL;
        }
        port_ptr = &i_port[0];
        goto check_newline;
    }
    pr_err("Unable to locate prefix for emulated Initiator Port:"
           " %s\n", i_port);
    return -EINVAL;
    /*
     * Clear any trailing newline for the NAA WWN
     */
check_newline:
    if (i_port[strlen(i_port)-1] == '\n')
        i_port[strlen(i_port)-1] = '\0';

    ret = tcm_loop_make_nexus(tl_tpg, port_ptr);
    if (ret < 0)
        return ret;

    return count;
}