static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,

                      Error **errp)

{

    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_inquiry_supported_pages *inq_vpd;

    char *initiator_name = NULL;

    QemuOpts *opts;

    Error *local_err = NULL;

    const char *filename;

    int i, ret;



    if ((BDRV_SECTOR_SIZE % 512) != 0) {

        error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "

                   "BDRV_SECTOR_SIZE(%lld) is not a multiple "

                   "of 512", BDRV_SECTOR_SIZE);

        return -EINVAL;

    }



    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);

    qemu_opts_absorb_qdict(opts, options, &local_err);

    if (local_err) {

        error_propagate(errp, 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_setg(errp, "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_setg(errp, "iSCSI: Failed to create iSCSI context.");

        ret = -ENOMEM;

        goto out;

    }



    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {

        error_setg(errp, "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_setg(errp, "Failed to set initiator username and password");

            ret = -EINVAL;

            goto out;

        }

    }



    /* check if we got CHAP username/password via the options */

    parse_chap(iscsi, iscsi_url->target, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }



    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {

        error_setg(errp, "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, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }



    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {

        error_setg(errp, "iSCSI: Failed to connect to LUN : %s",

            iscsi_get_error(iscsi));

        ret = -EINVAL;

        goto out;

    }



    iscsilun->iscsi = iscsi;

    iscsilun->aio_context = bdrv_get_aio_context(bs);

    iscsilun->lun   = iscsi_url->lun;

    iscsilun->has_write_same = true;



    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0,

                            (void **) &inq, errp);

    if (task == NULL) {

        ret = -EINVAL;

        goto out;

    }

    iscsilun->type = inq->periperal_device_type;

    scsi_free_scsi_task(task);

    task = NULL;



    /* Check the write protect flag of the LUN if we want to write */

    if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&

        iscsi_is_write_protected(iscsilun)) {

        error_setg(errp, "Cannot open a write protected LUN as read-write");

        ret = -EACCES;

        goto out;

    }



    iscsi_readcapacity_sync(iscsilun, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

    bs->request_alignment = iscsilun->block_size;



    /* We don't have any emulation for devices other than disks and CD-ROMs, 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_DISK && iscsilun->type != TYPE_ROM) {

        bs->sg = 1;

    }



    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                            SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,

                            (void **) &inq_vpd, errp);

    if (task == NULL) {

        ret = -EINVAL;

        goto out;

    }

    for (i = 0; i < inq_vpd->num_pages; i++) {

        struct scsi_task *inq_task;

        struct scsi_inquiry_logical_block_provisioning *inq_lbp;

        struct scsi_inquiry_block_limits *inq_bl;

        switch (inq_vpd->pages[i]) {

        case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:

            inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                                        SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,

                                        (void **) &inq_lbp, errp);

            if (inq_task == NULL) {

                ret = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->lbp, inq_lbp,

                   sizeof(struct scsi_inquiry_logical_block_provisioning));

            scsi_free_scsi_task(inq_task);

            break;

        case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:

            inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                                    SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,

                                    (void **) &inq_bl, errp);

            if (inq_task == NULL) {

                ret = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->bl, inq_bl,

                   sizeof(struct scsi_inquiry_block_limits));

            scsi_free_scsi_task(inq_task);

            break;

        default:

            break;

        }

    }

    scsi_free_scsi_task(task);

    task = NULL;



    iscsi_attach_aio_context(bs, iscsilun->aio_context);



    /* Guess the internal cluster (page) size of the iscsi target by the means

     * of opt_unmap_gran. Transfer the unmap granularity only if it has a

     * reasonable size */

    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&

        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {

        iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *

                                     iscsilun->block_size) >> BDRV_SECTOR_BITS;

        if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) {

            iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun);

            if (iscsilun->allocationmap == NULL) {

                ret = -ENOMEM;

            }

        }

    }



out:

    qemu_opts_del(opts);

    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;

}

static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,

                      Error **errp)

{

    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_inquiry_supported_pages *inq_vpd;

    char *initiator_name = NULL;

    QemuOpts *opts;

    Error *local_err = NULL;

    const char *filename;

    int i, ret;



    if ((BDRV_SECTOR_SIZE % 512) != 0) {

        error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "

                   "BDRV_SECTOR_SIZE(%lld) is not a multiple "

                   "of 512", BDRV_SECTOR_SIZE);

        return -EINVAL;

    }



    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);

    qemu_opts_absorb_qdict(opts, options, &local_err);

    if (local_err) {

        error_propagate(errp, 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_setg(errp, "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_setg(errp, "iSCSI: Failed to create iSCSI context.");

        ret = -ENOMEM;

        goto out;

    }



    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {

        error_setg(errp, "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_setg(errp, "Failed to set initiator username and password");

            ret = -EINVAL;

            goto out;

        }

    }



    

    parse_chap(iscsi, iscsi_url->target, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }



    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {

        error_setg(errp, "iSCSI: Failed to set session type to normal.");

        ret = -EINVAL;

        goto out;

    }



    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);



    

    parse_header_digest(iscsi, iscsi_url->target, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }



    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {

        error_setg(errp, "iSCSI: Failed to connect to LUN : %s",

            iscsi_get_error(iscsi));

        ret = -EINVAL;

        goto out;

    }



    iscsilun->iscsi = iscsi;

    iscsilun->aio_context = bdrv_get_aio_context(bs);

    iscsilun->lun   = iscsi_url->lun;

    iscsilun->has_write_same = true;



    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0,

                            (void **) &inq, errp);

    if (task == NULL) {

        ret = -EINVAL;

        goto out;

    }

    iscsilun->type = inq->periperal_device_type;

    scsi_free_scsi_task(task);

    task = NULL;



    

    if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&

        iscsi_is_write_protected(iscsilun)) {

        error_setg(errp, "Cannot open a write protected LUN as read-write");

        ret = -EACCES;

        goto out;

    }



    iscsi_readcapacity_sync(iscsilun, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

    bs->request_alignment = iscsilun->block_size;



    







    if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {

        bs->sg = 1;

    }



    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                            SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,

                            (void **) &inq_vpd, errp);

    if (task == NULL) {

        ret = -EINVAL;

        goto out;

    }

    for (i = 0; i < inq_vpd->num_pages; i++) {

        struct scsi_task *inq_task;

        struct scsi_inquiry_logical_block_provisioning *inq_lbp;

        struct scsi_inquiry_block_limits *inq_bl;

        switch (inq_vpd->pages[i]) {

        case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:

            inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                                        SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,

                                        (void **) &inq_lbp, errp);

            if (inq_task == NULL) {

                ret = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->lbp, inq_lbp,

                   sizeof(struct scsi_inquiry_logical_block_provisioning));

            scsi_free_scsi_task(inq_task);

            break;

        case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:

            inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                                    SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,

                                    (void **) &inq_bl, errp);

            if (inq_task == NULL) {

                ret = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->bl, inq_bl,

                   sizeof(struct scsi_inquiry_block_limits));

            scsi_free_scsi_task(inq_task);

            break;

        default:

            break;

        }

    }

    scsi_free_scsi_task(task);

    task = NULL;



    iscsi_attach_aio_context(bs, iscsilun->aio_context);



    





    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&

        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {

        iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *

                                     iscsilun->block_size) >> BDRV_SECTOR_BITS;

        if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) {

            iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun);

            if (iscsilun->allocationmap == NULL) {

                ret = -ENOMEM;

            }

        }

    }



out:

    qemu_opts_del(opts);

    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 i, ret;
static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2,

                      Error **VAR_3)

{

    IscsiLun *iscsilun = VAR_0->opaque;

    struct iscsi_context *VAR_4 = NULL;

    struct VAR_5 *VAR_5 = NULL;

    struct scsi_task *VAR_6 = NULL;

    struct scsi_inquiry_standard *VAR_7 = NULL;

    struct scsi_inquiry_supported_pages *VAR_8;

    char *VAR_9 = NULL;

    QemuOpts *opts;

    Error *local_err = NULL;

    const char *VAR_10;

    int VAR_11, VAR_12;



    if ((BDRV_SECTOR_SIZE % 512) != 0) {

        error_setg(VAR_3, "iSCSI: Invalid BDRV_SECTOR_SIZE. "

                   "BDRV_SECTOR_SIZE(%lld) is not a multiple "

                   "of 512", BDRV_SECTOR_SIZE);

        return -EINVAL;

    }



    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);

    qemu_opts_absorb_qdict(opts, VAR_1, &local_err);

    if (local_err) {

        error_propagate(VAR_3, local_err);

        VAR_12 = -EINVAL;

        goto out;

    }



    VAR_10 = qemu_opt_get(opts, "VAR_10");



    VAR_5 = iscsi_parse_full_url(VAR_4, VAR_10);

    if (VAR_5 == NULL) {

        error_setg(VAR_3, "Failed to parse URL : %s", VAR_10);

        VAR_12 = -EINVAL;

        goto out;

    }



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



    VAR_9 = parse_initiator_name(VAR_5->target);



    VAR_4 = iscsi_create_context(VAR_9);

    if (VAR_4 == NULL) {

        error_setg(VAR_3, "iSCSI: Failed to create iSCSI context.");

        VAR_12 = -ENOMEM;

        goto out;

    }



    if (iscsi_set_targetname(VAR_4, VAR_5->target)) {

        error_setg(VAR_3, "iSCSI: Failed to set target name.");

        VAR_12 = -EINVAL;

        goto out;

    }



    if (VAR_5->user != NULL) {

        VAR_12 = iscsi_set_initiator_username_pwd(VAR_4, VAR_5->user,

                                              VAR_5->passwd);

        if (VAR_12 != 0) {

            error_setg(VAR_3, "Failed to set initiator username and password");

            VAR_12 = -EINVAL;

            goto out;

        }

    }



    

    parse_chap(VAR_4, VAR_5->target, &local_err);

    if (local_err != NULL) {

        error_propagate(VAR_3, local_err);

        VAR_12 = -EINVAL;

        goto out;

    }



    if (iscsi_set_session_type(VAR_4, ISCSI_SESSION_NORMAL) != 0) {

        error_setg(VAR_3, "iSCSI: Failed to set session type to normal.");

        VAR_12 = -EINVAL;

        goto out;

    }



    iscsi_set_header_digest(VAR_4, ISCSI_HEADER_DIGEST_NONE_CRC32C);



    

    parse_header_digest(VAR_4, VAR_5->target, &local_err);

    if (local_err != NULL) {

        error_propagate(VAR_3, local_err);

        VAR_12 = -EINVAL;

        goto out;

    }



    if (iscsi_full_connect_sync(VAR_4, VAR_5->portal, VAR_5->lun) != 0) {

        error_setg(VAR_3, "iSCSI: Failed to connect to LUN : %s",

            iscsi_get_error(VAR_4));

        VAR_12 = -EINVAL;

        goto out;

    }



    iscsilun->VAR_4 = VAR_4;

    iscsilun->aio_context = bdrv_get_aio_context(VAR_0);

    iscsilun->lun   = VAR_5->lun;

    iscsilun->has_write_same = true;



    VAR_6 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 0, 0,

                            (void **) &VAR_7, VAR_3);

    if (VAR_6 == NULL) {

        VAR_12 = -EINVAL;

        goto out;

    }

    iscsilun->type = VAR_7->periperal_device_type;

    scsi_free_scsi_task(VAR_6);

    VAR_6 = NULL;



    

    if (iscsilun->type == TYPE_DISK && (VAR_2 & BDRV_O_RDWR) &&

        iscsi_is_write_protected(iscsilun)) {

        error_setg(VAR_3, "Cannot open a write protected LUN as read-write");

        VAR_12 = -EACCES;

        goto out;

    }



    iscsi_readcapacity_sync(iscsilun, &local_err);

    if (local_err != NULL) {

        error_propagate(VAR_3, local_err);

        VAR_12 = -EINVAL;

        goto out;

    }

    VAR_0->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

    VAR_0->request_alignment = iscsilun->block_size;



    







    if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {

        VAR_0->sg = 1;

    }



    VAR_6 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 1,

                            SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,

                            (void **) &VAR_8, VAR_3);

    if (VAR_6 == NULL) {

        VAR_12 = -EINVAL;

        goto out;

    }

    for (VAR_11 = 0; VAR_11 < VAR_8->num_pages; VAR_11++) {

        struct scsi_task *VAR_13;

        struct scsi_inquiry_logical_block_provisioning *VAR_14;

        struct scsi_inquiry_block_limits *VAR_15;

        switch (VAR_8->pages[VAR_11]) {

        case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:

            VAR_13 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 1,

                                        SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,

                                        (void **) &VAR_14, VAR_3);

            if (VAR_13 == NULL) {

                VAR_12 = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->lbp, VAR_14,

                   sizeof(struct scsi_inquiry_logical_block_provisioning));

            scsi_free_scsi_task(VAR_13);

            break;

        case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:

            VAR_13 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 1,

                                    SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,

                                    (void **) &VAR_15, VAR_3);

            if (VAR_13 == NULL) {

                VAR_12 = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->bl, VAR_15,

                   sizeof(struct scsi_inquiry_block_limits));

            scsi_free_scsi_task(VAR_13);

            break;

        default:

            break;

        }

    }

    scsi_free_scsi_task(VAR_6);

    VAR_6 = NULL;



    iscsi_attach_aio_context(VAR_0, iscsilun->aio_context);



    





    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&

        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {

        iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *

                                     iscsilun->block_size) >> BDRV_SECTOR_BITS;

        if (iscsilun->lbprz && !(VAR_0->open_flags & BDRV_O_NOCACHE)) {

            iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun);

            if (iscsilun->allocationmap == NULL) {

                VAR_12 = -ENOMEM;

            }

        }

    }



out:

    qemu_opts_del(opts);

    g_free(VAR_9);

    if (VAR_5 != NULL) {

        iscsi_destroy_url(VAR_5);

    }

    if (VAR_6 != NULL) {

        scsi_free_scsi_task(VAR_6);

    }



    if (VAR_12) {

        if (VAR_4 != NULL) {

            iscsi_destroy_context(VAR_4);

        }

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

    }

    return VAR_12;

}

static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2,
Error **VAR_3)
{ IscsiLun *iscsilun = VAR_0->opaque; struct iscsi_context *VAR_4 = NULL; struct VAR_5 *VAR_5 = NULL; struct scsi_task *VAR_6 = NULL; struct scsi_inquiry_standard *VAR_7 = NULL; struct scsi_inquiry_supported_pages *VAR_8; char *VAR_9 = NULL; QemuOpts *opts; Error *local_err = NULL; const char *VAR_10; int VAR_11, VAR_12; if ((BDRV_SECTOR_SIZE % 512) != 0) { error_setg(VAR_3, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
"BDRV_SECTOR_SIZE(%lld) is not a multiple "
"of 512", BDRV_SECTOR_SIZE); return -EINVAL; } opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, VAR_1, &local_err); if (local_err) { error_propagate(VAR_3, local_err); VAR_12 = -EINVAL; goto out; } VAR_10 = qemu_opt_get(opts, "VAR_10"); VAR_5 = iscsi_parse_full_url(VAR_4, VAR_10); if (VAR_5 == NULL) { error_setg(VAR_3, "Failed to parse URL : %s", VAR_10); VAR_12 = -EINVAL; goto out; } memset(iscsilun, 0, sizeof(IscsiLun)); VAR_9 = parse_initiator_name(VAR_5->target); VAR_4 = iscsi_create_context(VAR_9); if (VAR_4 == NULL) { error_setg(VAR_3, "iSCSI: Failed to create iSCSI context."); VAR_12 = -ENOMEM; goto out; } if (iscsi_set_targetname(VAR_4, VAR_5->target)) { error_setg(VAR_3, "iSCSI: Failed to set target name."); VAR_12 = -EINVAL; goto out; } if (VAR_5->user != NULL) { VAR_12 = iscsi_set_initiator_username_pwd(VAR_4, VAR_5->user,
VAR_5->passwd); if (VAR_12 != 0) { error_setg(VAR_3, "Failed to set initiator username and password"); VAR_12 = -EINVAL; goto out; } } parse_chap(VAR_4, VAR_5->target, &local_err); if (local_err != NULL) { error_propagate(VAR_3, local_err); VAR_12 = -EINVAL; goto out; } if (iscsi_set_session_type(VAR_4, ISCSI_SESSION_NORMAL) != 0) { error_setg(VAR_3, "iSCSI: Failed to set session type to normal."); VAR_12 = -EINVAL; goto out; } iscsi_set_header_digest(VAR_4, ISCSI_HEADER_DIGEST_NONE_CRC32C); parse_header_digest(VAR_4, VAR_5->target, &local_err); if (local_err != NULL) { error_propagate(VAR_3, local_err); VAR_12 = -EINVAL; goto out; } if (iscsi_full_connect_sync(VAR_4, VAR_5->portal, VAR_5->lun) != 0) { error_setg(VAR_3, "iSCSI: Failed to connect to LUN : %s",
iscsi_get_error(VAR_4)); VAR_12 = -EINVAL; goto out; } iscsilun->VAR_4 = VAR_4; iscsilun->aio_context = bdrv_get_aio_context(VAR_0); iscsilun->lun   = VAR_5->lun; iscsilun->has_write_same = true; VAR_6 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 0, 0,
(void **) &VAR_7, VAR_3); if (VAR_6 == NULL) { VAR_12 = -EINVAL; goto out; } iscsilun->type = VAR_7->periperal_device_type; scsi_free_scsi_task(VAR_6); VAR_6 = NULL; if (iscsilun->type == TYPE_DISK && (VAR_2 & BDRV_O_RDWR) &&
iscsi_is_write_protected(iscsilun)) { error_setg(VAR_3, "Cannot open a write protected LUN as read-write"); VAR_12 = -EACCES; goto out; } iscsi_readcapacity_sync(iscsilun, &local_err); if (local_err != NULL) { error_propagate(VAR_3, local_err); VAR_12 = -EINVAL; goto out; } VAR_0->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun); VAR_0->request_alignment = iscsilun->block_size; if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) { VAR_0->sg = 1; } VAR_6 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 1,
SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,
(void **) &VAR_8, VAR_3); if (VAR_6 == NULL) { VAR_12 = -EINVAL; goto out; } for (VAR_11 = 0; VAR_11 < VAR_8->num_pages; VAR_11++) { struct scsi_task *VAR_13; struct scsi_inquiry_logical_block_provisioning *VAR_14; struct scsi_inquiry_block_limits *VAR_15; switch (VAR_8->pages[VAR_11]) { case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
VAR_13 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 1,
SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
(void **) &VAR_14, VAR_3); if (VAR_13 == NULL) { VAR_12 = -EINVAL; goto out; } memcpy(&iscsilun->lbp, VAR_14,
sizeof(struct scsi_inquiry_logical_block_provisioning)); scsi_free_scsi_task(VAR_13); break; case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
VAR_13 = iscsi_do_inquiry(iscsilun->VAR_4, iscsilun->lun, 1,
SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,
(void **) &VAR_15, VAR_3); if (VAR_13 == NULL) { VAR_12 = -EINVAL; goto out; } memcpy(&iscsilun->bl, VAR_15,
sizeof(struct scsi_inquiry_block_limits)); scsi_free_scsi_task(VAR_13); break; default:
break; } } scsi_free_scsi_task(VAR_6); VAR_6 = NULL; iscsi_attach_aio_context(VAR_0, iscsilun->aio_context); if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) { iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
iscsilun->block_size) >> BDRV_SECTOR_BITS; if (iscsilun->lbprz && !(VAR_0->open_flags & BDRV_O_NOCACHE)) { iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun); if (iscsilun->allocationmap == NULL) { VAR_12 = -ENOMEM; } } } out:
qemu_opts_del(opts); g_free(VAR_9); if (VAR_5 != NULL) { iscsi_destroy_url(VAR_5); } if (VAR_6 != NULL) { scsi_free_scsi_task(VAR_6); } if (VAR_12) { if (VAR_4 != NULL) { iscsi_destroy_context(VAR_4); } memset(iscsilun, 0, sizeof(IscsiLun)); } return VAR_12; }