Example #1
0
void list_luns(const char *target, const char *portal)
{
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_reportluns_list *list;
	int full_report_size;
	int i;

	iscsi = iscsi_create_context(initiator);
	if (iscsi == NULL) {
		printf("Failed to create context\n");
		exit(10);
	}
	if (iscsi_set_targetname(iscsi, target)) {
		fprintf(stderr, "Failed to set target name\n");
		exit(10);
	}
	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	if (iscsi_connect_sync(iscsi, portal) != 0) {
		printf("iscsi_connect failed. %s\n", iscsi_get_error(iscsi));
		exit(10);
	}

	if (iscsi_login_sync(iscsi) != 0) {
		fprintf(stderr, "login failed :%s\n", iscsi_get_error(iscsi));
		exit(10);
	}


	/* get initial reportluns data, all targets can report 16 bytes but some
	 * fail if we ask for too much.
	 */
	if ((task = iscsi_reportluns_sync(iscsi, 0, 16)) == NULL) {
		fprintf(stderr, "reportluns failed : %s\n", iscsi_get_error(iscsi));
		exit(10);
	}
	full_report_size = scsi_datain_getfullsize(task);
	if (full_report_size > task->datain.size) {
		scsi_free_scsi_task(task);

		/* we need more data for the full list */
		if ((task = iscsi_reportluns_sync(iscsi, 0, full_report_size)) == NULL) {
			fprintf(stderr, "reportluns failed : %s\n", iscsi_get_error(iscsi));
			exit(10);
		}
	}

	list = scsi_datain_unmarshall(task);
	if (list == NULL) {
		fprintf(stderr, "failed to unmarshall reportluns datain blob\n");
		exit(10);
	}
	for (i=0; i < (int)list->num; i++) {
		show_lun(iscsi, list->luns[i]);
	}

	scsi_free_scsi_task(task);
	iscsi_destroy_context(iscsi);
}
Example #2
0
static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
{
    QemuOptsList *list;
    QemuOpts *opts;
    const char *digest = NULL;

    list = qemu_find_opts("iscsi");
    if (!list) {
        return;
    }

    opts = qemu_opts_find(list, target);
    if (opts == NULL) {
        opts = QTAILQ_FIRST(&list->head);
        if (!opts) {
            return;
        }
    }

    digest = qemu_opt_get(opts, "header-digest");
    if (!digest) {
        return;
    }

    if (!strcmp(digest, "CRC32C")) {
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
    } else if (!strcmp(digest, "NONE")) {
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
    } else if (!strcmp(digest, "CRC32C-NONE")) {
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
    } else if (!strcmp(digest, "NONE-CRC32C")) {
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
    } else {
        error_report("Invalid header-digest setting : %s", digest);
    }
}
Example #3
0
/*
 * We support iscsi url's on the form
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 */
static int iscsi_open(BlockDriverState *bs, QDict *options, int flags)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = NULL;
    struct iscsi_url *iscsi_url = NULL;
    struct scsi_task *task = NULL;
    struct scsi_inquiry_standard *inq = NULL;
    char *initiator_name = NULL;
    QemuOpts *opts;
    Error *local_err = NULL;
    const char *filename;
    int ret;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {
        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
                     "of 512", BDRV_SECTOR_SIZE);
        return -EINVAL;
    }

    opts = qemu_opts_create_nofail(&runtime_opts);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        ret = -EINVAL;
        goto out;
    }

    filename = qemu_opt_get(opts, "filename");


    iscsi_url = iscsi_parse_full_url(iscsi, filename);
    if (iscsi_url == NULL) {
        error_report("Failed to parse URL : %s", filename);
        ret = -EINVAL;
        goto out;
    }

    memset(iscsilun, 0, sizeof(IscsiLun));

    initiator_name = parse_initiator_name(iscsi_url->target);

    iscsi = iscsi_create_context(initiator_name);
    if (iscsi == NULL) {
        error_report("iSCSI: Failed to create iSCSI context.");
        ret = -ENOMEM;
        goto out;
    }

    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
        error_report("iSCSI: Failed to set target name.");
        ret = -EINVAL;
        goto out;
    }

    if (iscsi_url->user != NULL) {
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
                                              iscsi_url->passwd);
        if (ret != 0) {
            error_report("Failed to set initiator username and password");
            ret = -EINVAL;
            goto out;
        }
    }

    /* check if we got CHAP username/password via the options */
    if (parse_chap(iscsi, iscsi_url->target) != 0) {
        error_report("iSCSI: Failed to set CHAP user/password");
        ret = -EINVAL;
        goto out;
    }

    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
        error_report("iSCSI: Failed to set session type to normal.");
        ret = -EINVAL;
        goto out;
    }

    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

    /* check if we got HEADER_DIGEST via the options */
    parse_header_digest(iscsi, iscsi_url->target);

    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
        error_report("iSCSI: Failed to connect to LUN : %s",
            iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto out;
    }

    iscsilun->iscsi = iscsi;
    iscsilun->lun   = iscsi_url->lun;

    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);

    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
        error_report("iSCSI: failed to send inquiry command.");
        ret = -EINVAL;
        goto out;
    }

    inq = scsi_datain_unmarshall(task);
    if (inq == NULL) {
        error_report("iSCSI: Failed to unmarshall inquiry data.");
        ret = -EINVAL;
        goto out;
    }

    iscsilun->type = inq->periperal_device_type;

    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
        goto out;
    }
    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

    /* Medium changer or tape. We dont have any emulation for this so this must
     * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
     * to read from the device to guess the image format.
     */
    if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
        iscsilun->type == TYPE_TAPE) {
        bs->sg = 1;
    }

#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
    /* Set up a timer for sending out iSCSI NOPs */
    iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
    qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
#endif

out:
    qemu_opts_del(opts);
    if (initiator_name != NULL) {
        g_free(initiator_name);
    }
    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    if (task != NULL) {
        scsi_free_scsi_task(task);
    }

    if (ret) {
        if (iscsi != NULL) {
            iscsi_destroy_context(iscsi);
        }
        memset(iscsilun, 0, sizeof(IscsiLun));
    }
    return ret;
}
Example #4
0
File: iscsi.c Project: breuerr/qemu
/*
 * We support iscsi url's on the form
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 */
static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = NULL;
    struct iscsi_url *iscsi_url = NULL;
    struct IscsiTask task;
    char *initiator_name = NULL;
    int ret;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {
        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
                     "of 512", BDRV_SECTOR_SIZE);
        return -EINVAL;
    }

    iscsi_url = iscsi_parse_full_url(iscsi, filename);
    if (iscsi_url == NULL) {
        error_report("Failed to parse URL : %s %s", filename,
                     iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto failed;
    }

    memset(iscsilun, 0, sizeof(IscsiLun));

    initiator_name = parse_initiator_name(iscsi_url->target);

    iscsi = iscsi_create_context(initiator_name);
    if (iscsi == NULL) {
        error_report("iSCSI: Failed to create iSCSI context.");
        ret = -ENOMEM;
        goto failed;
    }

    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
        error_report("iSCSI: Failed to set target name.");
        ret = -EINVAL;
        goto failed;
    }

    if (iscsi_url->user != NULL) {
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
                                              iscsi_url->passwd);
        if (ret != 0) {
            error_report("Failed to set initiator username and password");
            ret = -EINVAL;
            goto failed;
        }
    }

    /* check if we got CHAP username/password via the options */
    if (parse_chap(iscsi, iscsi_url->target) != 0) {
        error_report("iSCSI: Failed to set CHAP user/password");
        ret = -EINVAL;
        goto failed;
    }

    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
        error_report("iSCSI: Failed to set session type to normal.");
        ret = -EINVAL;
        goto failed;
    }

    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

    /* check if we got HEADER_DIGEST via the options */
    parse_header_digest(iscsi, iscsi_url->target);

    task.iscsilun = iscsilun;
    task.status = 0;
    task.complete = 0;
    task.bs = bs;

    iscsilun->iscsi = iscsi;
    iscsilun->lun   = iscsi_url->lun;

    if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
                                 iscsi_connect_cb, &task)
        != 0) {
        error_report("iSCSI: Failed to start async connect.");
        ret = -EINVAL;
        goto failed;
    }

    while (!task.complete) {
        iscsi_set_events(iscsilun);
        qemu_aio_wait();
    }
    if (task.status != 0) {
        error_report("iSCSI: Failed to connect to LUN : %s",
                     iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto failed;
    }

    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    return 0;

failed:
    if (initiator_name != NULL) {
        g_free(initiator_name);
    }
    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    if (iscsi != NULL) {
        iscsi_destroy_context(iscsi);
    }
    memset(iscsilun, 0, sizeof(IscsiLun));
    return ret;
}
Example #5
0
int main(int argc, char *argv[])
{
	struct iscsi_context *iscsi;
	const char *url = NULL;
	struct iscsi_url *iscsi_url = NULL;
	int show_help = 0, show_usage = 0, debug = 0;
	int c;
	int ret = 0;
	int swp = 0;
	struct scsi_task *sense_task = NULL;
	struct scsi_task *select_task = NULL;
	struct scsi_mode_sense *ms;
	struct scsi_mode_page *mp;

	static struct option long_options[] = {
		{"help",           no_argument,          NULL,        'h'},
		{"usage",          no_argument,          NULL,        'u'},
		{"debug",          no_argument,          NULL,        'd'},
		{"initiator-name", required_argument,    NULL,        'i'},
		{"swp",            required_argument,    NULL,        's'},
		{0, 0, 0, 0}
	};
	int option_index;

	while ((c = getopt_long(argc, argv, "h?udi:s:", long_options,
			&option_index)) != -1) {
		switch (c) {
		case 'h':
		case '?':
			show_help = 1;
			break;
		case 'u':
			show_usage = 1;
			break;
		case 'd':
			debug = 1;
			break;
		case 'i':
			initiator = optarg;
			break;
		case 's':
			if (!strcmp(optarg, "on") || !strcmp(optarg, "ON")) {
				swp = 1;
			}
			if (!strcmp(optarg, "off") || !strcmp(optarg, "OFF")) {
				swp = 2;
			}
			break;
		default:
			fprintf(stderr, "Unrecognized option '%c'\n\n", c);
			print_help();
			exit(0);
		}
	}

	if (show_help != 0) {
		print_help();
		exit(0);
	}

	if (show_usage != 0) {
		print_usage();
		exit(0);
	}

	iscsi = iscsi_create_context(initiator);
	if (iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}

	if (debug > 0) {
		iscsi_set_log_level(iscsi, debug);
		iscsi_set_log_fn(iscsi, iscsi_log_to_stderr);
	}

	if (argv[optind] != NULL) {
		url = strdup(argv[optind]);
	}
	if (url == NULL) {
		fprintf(stderr, "You must specify the URL\n");
		print_usage();
		ret = 10;
		goto finished;
	}
	iscsi_url = iscsi_parse_full_url(iscsi, url);
	
	free(discard_const(url));

	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}

	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

	if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}


	sense_task = iscsi_modesense10_sync(iscsi, iscsi_url->lun,
		0, 1, SCSI_MODESENSE_PC_CURRENT,
		SCSI_MODEPAGE_CONTROL,
		0, 255);
	if (sense_task == NULL) {
		printf("Failed to send MODE_SENSE10 command: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}
	if (sense_task->status != SCSI_STATUS_GOOD) {
		printf("MODE_SENSE10 failed: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}
	ms = scsi_datain_unmarshall(sense_task);
	if (ms == NULL) {
		printf("failed to unmarshall mode sense datain blob\n");
		ret = 10;
		goto finished;
	}
	mp = scsi_modesense_get_page(ms, SCSI_MODEPAGE_CONTROL, 0);
	if (mp == NULL) {
		printf("failed to read control mode page\n");
		ret = 10;
		goto finished;
	}

	/* For MODE SELECT PS is reserved and hence must be cleared */
	mp->ps = 0;

	printf("SWP:%d\n", mp->control.swp);

	switch (swp) {
	case 1:
		mp->control.swp = 1;
		break;
	case 2:
		mp->control.swp = 0;
		break;
	default:
		goto finished;
	}

	printf("Turning SWP %s\n", (swp == 1) ? "ON" : "OFF"); 
	select_task = iscsi_modeselect10_sync(iscsi, iscsi_url->lun,
		    1, 0, mp);
	if (select_task == NULL) {
		printf("Failed to send MODE_SELECT10 command: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}
	if (select_task->status != SCSI_STATUS_GOOD) {
		printf("MODE_SELECT10 failed: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}


finished:
	if (sense_task != NULL) {
		scsi_free_scsi_task(sense_task);
	}
	if (select_task != NULL) {
		scsi_free_scsi_task(select_task);
	}
	if (iscsi_url != NULL) {
		iscsi_destroy_url(iscsi_url);
	}
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #6
0
int main(int argc, char *argv[])
{
	struct iscsi_context *iscsi;
	const char *url = NULL;
	struct iscsi_url *iscsi_url = NULL;
	int evpd = 0, pagecode = 0;
	int show_help = 0, show_usage = 0, debug = 0;
	int c;

	static struct option long_options[] = {
		{"help",           no_argument,          NULL,        'h'},
		{"usage",          no_argument,          NULL,        'u'},
		{"debug",          no_argument,          NULL,        'd'},
		{"initiator-name", required_argument,    NULL,        'i'},
		{"evpd",           required_argument,    NULL,        'e'},
		{"pagecode",       required_argument,    NULL,        'c'},
		{0, 0, 0, 0}
	};
	int option_index;

	while ((c = getopt_long(argc, argv, "h?udi:e:c:", long_options,
			&option_index)) != -1) {
		switch (c) {
		case 'h':
		case '?':
			show_help = 1;
			break;
		case 'u':
			show_usage = 1;
			break;
		case 'd':
			debug = 1;
			break;
		case 'i':
			initiator = optarg;
			break;
		case 'e':
			evpd = atoi(optarg);
			break;
		case 'c':
			pagecode = atoi(optarg);
			break;
		default:
			fprintf(stderr, "Unrecognized option '%c'\n\n", c);
			print_help();
			exit(0);
		}
	}

	if (show_help != 0) {
		print_help();
		exit(0);
	}

	if (show_usage != 0) {
		print_usage();
		exit(0);
	}

	iscsi = iscsi_create_context(initiator);
	if (iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}

	if (debug > 0) {
		iscsi_set_log_level(iscsi, debug);
		iscsi_set_log_fn(iscsi, iscsi_log_to_stderr);
	}

	if (argv[optind] != NULL) {
		url = strdup(argv[optind]);
	}
	if (url == NULL) {
		fprintf(stderr, "You must specify the URL\n");
		print_usage();
		exit(10);
	}
	iscsi_url = iscsi_parse_full_url(iscsi, url);
	
	if (url) {
		free(discard_const(url));
	}

	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(iscsi));
		exit(10);
	}

	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

	if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(iscsi));
		iscsi_destroy_url(iscsi_url);
		iscsi_destroy_context(iscsi);
		exit(10);
	}

	do_inquiry(iscsi, iscsi_url->lun, evpd, pagecode);
	iscsi_destroy_url(iscsi_url);

	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return 0;
}
Example #7
0
int main(int argc, const char *argv[])
{
	poptContext pc;
	const char **extra_argv;
	char *src_url = NULL;
	char *dst_url = NULL;
	struct iscsi_url *iscsi_url;
	struct scsi_task *task;
	struct scsi_readcapacity10 *rc10;
	int extra_argc = 0;
	int res;
	struct pollfd pfd[2];
	struct client client;

	struct poptOption popt_options[] = {
		POPT_AUTOHELP
		{ "initiator-name", 'i', POPT_ARG_STRING, &initiator, 0, "Initiatorname to use", "iqn-name" },
		{ "src", 0, POPT_ARG_STRING, &src_url, 0, "SRC lun", "iscsi url" },
		{ "dst", 0, POPT_ARG_STRING, &dst_url, 0, "DST lun", "iscsi url" },
		POPT_TABLEEND
	};

	pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_POSIXMEHARDER);
	if ((res = poptGetNextOpt(pc)) < -1) {
		fprintf(stderr, "Failed to parse option : %s %s\n",
			poptBadOption(pc, 0), poptStrerror(res));
		exit(10);
	}
	extra_argv = poptGetArgs(pc);
	poptFreeContext(pc);

	if (src_url == NULL) {
		fprintf(stderr, "You must specify source url\n");
		fprintf(stderr, "  --src iscsi://<host>[:<port>]/<target-iqn>/<lun>\n", argv[0]);
		exit(10);
	}
	if (dst_url == NULL) {
		fprintf(stderr, "You must specify destination url\n");
		fprintf(stderr, "  --dst iscsi://<host>[:<port>]/<target-iqn>/<lun>\n", argv[0]);
		exit(10);
	}


	memset(&client, 0, sizeof(client));


	client.src_iscsi = iscsi_create_context(initiator);
	if (client.src_iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}
	iscsi_url = iscsi_parse_full_url(client.src_iscsi, src_url);
	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(client.src_iscsi));
		exit(10);
	}
	iscsi_set_targetname(client.src_iscsi, iscsi_url->target);
	iscsi_set_session_type(client.src_iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(client.src_iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	if (iscsi_url->user != NULL) {
		if (iscsi_set_initiator_username_pwd(client.src_iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
			fprintf(stderr, "Failed to set initiator username and password\n");
			exit(10);
		}
	}
	if (iscsi_full_connect_sync(client.src_iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(client.src_iscsi));
		iscsi_destroy_url(iscsi_url);
		iscsi_destroy_context(client.src_iscsi);
		exit(10);
	}
	client.src_lun = iscsi_url->lun;
	iscsi_destroy_url(iscsi_url);

	task = iscsi_readcapacity10_sync(client.src_iscsi, client.src_lun, 0, 0);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "failed to send readcapacity command\n");
		exit(10);
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		fprintf(stderr, "failed to unmarshall readcapacity10 data\n");
		exit(10);
	}
	client.src_blocksize  = rc10->block_size;
	client.src_num_blocks  = rc10->lba;
	scsi_free_scsi_task(task);





	client.dst_iscsi = iscsi_create_context(initiator);
	if (client.dst_iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}
	iscsi_url = iscsi_parse_full_url(client.dst_iscsi, dst_url);
	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(client.dst_iscsi));
		exit(10);
	}
	iscsi_set_targetname(client.dst_iscsi, iscsi_url->target);
	iscsi_set_session_type(client.dst_iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(client.dst_iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	if (iscsi_url->user != NULL) {
		if (iscsi_set_initiator_username_pwd(client.dst_iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
			fprintf(stderr, "Failed to set initiator username and password\n");
			exit(10);
		}
	}
	if (iscsi_full_connect_sync(client.dst_iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(client.dst_iscsi));
		iscsi_destroy_url(iscsi_url);
		iscsi_destroy_context(client.dst_iscsi);
		exit(10);
	}
	client.dst_lun = iscsi_url->lun;
	iscsi_destroy_url(iscsi_url);

	task = iscsi_readcapacity10_sync(client.dst_iscsi, client.dst_lun, 0, 0);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "failed to send readcapacity command\n");
		exit(10);
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		fprintf(stderr, "failed to unmarshall readcapacity10 data\n");
		exit(10);
	}
	client.dst_blocksize  = rc10->block_size;
	client.dst_num_blocks  = rc10->lba;
	scsi_free_scsi_task(task);

	fill_read_queue(&client);

	while (client.finished == 0) {
		pfd[0].fd = iscsi_get_fd(client.src_iscsi);
		pfd[0].events = iscsi_which_events(client.src_iscsi);
		pfd[1].fd = iscsi_get_fd(client.dst_iscsi);
		pfd[1].events = iscsi_which_events(client.dst_iscsi);

		if (poll(&pfd[0], 2, -1) < 0) {
			printf("Poll failed");
			exit(10);
		}
		if (iscsi_service(client.src_iscsi, pfd[0].revents) < 0) {
			printf("iscsi_service failed with : %s\n", iscsi_get_error(client.src_iscsi));
			break;
		}
		if (iscsi_service(client.dst_iscsi, pfd[1].revents) < 0) {
			printf("iscsi_service failed with : %s\n", iscsi_get_error(client.dst_iscsi));
			break;
		}
	}

	iscsi_logout_sync(client.src_iscsi);
	iscsi_destroy_context(client.src_iscsi);
	iscsi_logout_sync(client.dst_iscsi);
	iscsi_destroy_context(client.dst_iscsi);

	return 0;
}
Example #8
0
/*
 * We support iscsi url's on the form
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 */
static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = NULL;
    struct iscsi_url *iscsi_url = NULL;
    struct scsi_task *task = NULL;
    struct scsi_inquiry_standard *inq = NULL;
    struct scsi_readcapacity10 *rc10 = NULL;
    struct scsi_readcapacity16 *rc16 = NULL;
    char *initiator_name = NULL;
    int ret;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {
        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
                     "of 512", BDRV_SECTOR_SIZE);
        return -EINVAL;
    }

    iscsi_url = iscsi_parse_full_url(iscsi, filename);
    if (iscsi_url == NULL) {
        error_report("Failed to parse URL : %s", filename);
        ret = -EINVAL;
        goto out;
    }

    memset(iscsilun, 0, sizeof(IscsiLun));

    initiator_name = parse_initiator_name(iscsi_url->target);

    iscsi = iscsi_create_context(initiator_name);
    if (iscsi == NULL) {
        error_report("iSCSI: Failed to create iSCSI context.");
        ret = -ENOMEM;
        goto out;
    }

    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
        error_report("iSCSI: Failed to set target name.");
        ret = -EINVAL;
        goto out;
    }

    if (iscsi_url->user != NULL) {
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
                                              iscsi_url->passwd);
        if (ret != 0) {
            error_report("Failed to set initiator username and password");
            ret = -EINVAL;
            goto out;
        }
    }

    /* check if we got CHAP username/password via the options */
    if (parse_chap(iscsi, iscsi_url->target) != 0) {
        error_report("iSCSI: Failed to set CHAP user/password");
        ret = -EINVAL;
        goto out;
    }

    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
        error_report("iSCSI: Failed to set session type to normal.");
        ret = -EINVAL;
        goto out;
    }

    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

    /* check if we got HEADER_DIGEST via the options */
    parse_header_digest(iscsi, iscsi_url->target);

    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
        error_report("iSCSI: Failed to connect to LUN : %s",
            iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto out;
    }

    iscsilun->iscsi = iscsi;
    iscsilun->lun   = iscsi_url->lun;

    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);

    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
        error_report("iSCSI: failed to send inquiry command.");
        ret = -EINVAL;
        goto out;
    }

    inq = scsi_datain_unmarshall(task);
    if (inq == NULL) {
        error_report("iSCSI: Failed to unmarshall inquiry data.");
        ret = -EINVAL;
        goto out;
    }

    iscsilun->type = inq->periperal_device_type;

    scsi_free_scsi_task(task);

    switch (iscsilun->type) {
    case TYPE_DISK:
        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
            error_report("iSCSI: failed to send readcapacity16 command.");
            ret = -EINVAL;
            goto out;
        }
        rc16 = scsi_datain_unmarshall(task);
        if (rc16 == NULL) {
            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
            ret = -EINVAL;
            goto out;
        }
        iscsilun->block_size = rc16->block_length;
        iscsilun->num_blocks = rc16->returned_lba + 1;
        break;
    case TYPE_ROM:
        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
            error_report("iSCSI: failed to send readcapacity10 command.");
            ret = -EINVAL;
            goto out;
        }
        rc10 = scsi_datain_unmarshall(task);
        if (rc10 == NULL) {
            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
            ret = -EINVAL;
            goto out;
        }
        iscsilun->block_size = rc10->block_size;
        if (rc10->lba == 0) {
            /* blank disk loaded */
            iscsilun->num_blocks = 0;
        } else {
            iscsilun->num_blocks = rc10->lba + 1;
        }
        break;
    default:
        break;
    }

    bs->total_sectors    = iscsilun->num_blocks *
                           iscsilun->block_size / BDRV_SECTOR_SIZE ;

    /* Medium changer or tape. We dont have any emulation for this so this must
     * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
     * to read from the device to guess the image format.
     */
    if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
        iscsilun->type == TYPE_TAPE) {
        bs->sg = 1;
    }

    ret = 0;

#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
    /* Set up a timer for sending out iSCSI NOPs */
    iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
    qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
#endif

out:
    if (initiator_name != NULL) {
        g_free(initiator_name);
    }
    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    if (task != NULL) {
        scsi_free_scsi_task(task);
    }

    if (ret) {
        if (iscsi != NULL) {
            iscsi_destroy_context(iscsi);
        }
        memset(iscsilun, 0, sizeof(IscsiLun));
    }
    return ret;
}
Example #9
0
int open(const char *path, int flags, mode_t mode)
{
	int fd;

	if (!strncmp(path, "iscsi:", 6)) {
		struct iscsi_context *iscsi;
		struct iscsi_url *iscsi_url;
		struct scsi_task *task;
		struct scsi_readcapacity16 *rc16;

		if (mode & O_NONBLOCK) {
			LD_ISCSI_DPRINTF(0,"Non-blocking I/O is currently not supported");
			errno = EINVAL;
			return -1;
		}

		iscsi = iscsi_create_context(initiator);
		if (iscsi == NULL) {
			LD_ISCSI_DPRINTF(0,"Failed to create context");
			errno = ENOMEM;
			return -1;
		}

		iscsi_url = iscsi_parse_full_url(iscsi, path);
		if (iscsi_url == NULL) {
			LD_ISCSI_DPRINTF(0,"Failed to parse URL: %s\n", iscsi_get_error(iscsi));
			iscsi_destroy_context(iscsi);
			errno = EINVAL;
			return -1;
		}

		iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
		iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

		if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
			LD_ISCSI_DPRINTF(0,"Login Failed. %s\n", iscsi_get_error(iscsi));
			iscsi_destroy_url(iscsi_url);
			iscsi_destroy_context(iscsi);
			errno = EIO;
			return -1;
		}

		task = iscsi_readcapacity16_sync(iscsi, iscsi_url->lun);
		if (task == NULL || task->status != SCSI_STATUS_GOOD) {
			LD_ISCSI_DPRINTF(0,"failed to send readcapacity command");
			iscsi_destroy_url(iscsi_url);
			iscsi_destroy_context(iscsi);
			errno = EIO;
			return -1;
		}

		rc16 = scsi_datain_unmarshall(task);
		if (rc16 == NULL) {
			LD_ISCSI_DPRINTF(0,"failed to unmarshall readcapacity10 data");
			scsi_free_scsi_task(task);
			iscsi_destroy_url(iscsi_url);
			iscsi_destroy_context(iscsi);
			errno = EIO;
			return -1;
		}

        LD_ISCSI_DPRINTF(4,"readcapacity16_sync: block_size: %d, num_blocks: %"PRIu64,rc16->block_length,rc16->returned_lba + 1);

		fd = iscsi_get_fd(iscsi);
		if (fd >= ISCSI_MAX_FD) {
			LD_ISCSI_DPRINTF(0,"Too many files open");
			iscsi_destroy_url(iscsi_url);
			iscsi_destroy_context(iscsi);
			errno = ENFILE;
			return -1;
		}

		iscsi_fd_list[fd].is_iscsi   = 1;
		iscsi_fd_list[fd].dup2fd     = -1;
		iscsi_fd_list[fd].iscsi      = iscsi;
		iscsi_fd_list[fd].block_size = rc16->block_length;
		iscsi_fd_list[fd].num_blocks = rc16->returned_lba + 1;
		iscsi_fd_list[fd].offset     = 0;
		iscsi_fd_list[fd].lun        = iscsi_url->lun;
		iscsi_fd_list[fd].mode       = mode;

		if (getenv("LD_ISCSI_GET_LBA_STATUS") != NULL) {
			iscsi_fd_list[fd].get_lba_status = atoi(getenv("LD_ISCSI_GET_LBA_STATUS"));
			if (rc16->lbpme == 0){
				LD_ISCSI_DPRINTF(1,"Logical unit is fully provisioned. Will skip get_lba_status tasks");
				iscsi_fd_list[fd].get_lba_status = 0;
			}
		}

		scsi_free_scsi_task(task);
		iscsi_destroy_url(iscsi_url);

		return fd;
	}

	return real_open(path, flags, mode);
}
/*
 * Perform a NormalLogin against the target. Note, the target must be fully
 * specified here.
 */
void iSCSILibWrapper::iSCSINormalLogin(void)
{
    // Remove us from the background thread
    iSCSIBackGround::GetInstance().RemoveConnection(*this);

    if (!mClient.connected || mClient.error)
    {
        if (mClient.error)
            mErrorString.Format("%s: previous error prevents login for target %s: %s",
                        __func__,
                        mTarget.c_str(),
                        iscsi_get_error(mIscsi));
        else
            mErrorString.Format("%s: Login to target %s not possible without a connection!",
                               __func__,
                               mTarget.c_str());
        mError = true;
        throw CException(mErrorString);
    }

    mClient.finished = 0;

    iscsi_set_session_type(mIscsi, ISCSI_SESSION_NORMAL);
    iscsi_set_header_digest(mIscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);

    if (iscsi_set_targetname(mIscsi, mTarget.c_str()))
    {
        mErrorString.Format("%s: failed to set target (%s) name: %s",
                           __func__,
                           mTarget.c_str(),
                           iscsi_get_error(mIscsi));
        mError = true;
        throw CException(mErrorString);
    }

    if (iscsi_login_async(mIscsi, discoverylogin_cb, this))
    {
        mErrorString.Format("%s: iscsi_login_async to target %s failed: %s",
                           __func__,
                           mTarget.c_str(),
                           iscsi_get_error(mIscsi));
        mError = true;
        throw CException(mErrorString);
    }

    ServiceISCSIEvents();

    // Add to the background task
    iSCSIBackGround::GetInstance().AddConnection(*this);

    // Now check to see if we have been redirected and recover the new address.
    if (mClient.error)
    {
        std::string errStr(iscsi_get_error(mIscsi));

        if (errStr.find("Target moved temporarily(257)") != 
            std::string::npos)
        {
            mRedirected = true;
            mNewAddress = std::string(iscsi_get_target_address(mIscsi));
        }
    }
}