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); }
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); } }
/* * 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; }
/* * 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; }
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; }
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; }
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; }
/* * 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; }
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)); } } }