Commit 24d3bd67 authored by Peter Lieven's avatar Peter Lieven Committed by Paolo Bonzini
Browse files

block/iscsi: query for supported VPD pages



this patch ensures that we only query for block provisioning and
block limits vpd pages if they are advertised. It also cleans
up the inquiry code and eliminates some redundant code.

Signed-off-by: default avatarPeter Lieven <pl@kamp.de>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 837c3901
Loading
Loading
Loading
Loading
+54 −53
Original line number Diff line number Diff line
@@ -1067,7 +1067,7 @@ static QemuOptsList runtime_opts = {
};

static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
                                          int evpd, int pc, Error **errp)
                                          int evpd, int pc, void **inq, Error **errp)
{
    int full_size;
    struct scsi_task *task = NULL;
@@ -1086,14 +1086,19 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
        }
    }

    *inq = scsi_datain_unmarshall(task);
    if (*inq == NULL) {
        error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
        goto fail;
    }

    return task;

fail:
    error_setg(errp, "iSCSI: Inquiry command failed : %s",
               iscsi_get_error(iscsi));
    if (task) {
    if (task != NULL) {
        scsi_free_scsi_task(task);
        return NULL;
    }
    return NULL;
}
@@ -1114,11 +1119,12 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
    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 ret;
    int i, ret;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {
        error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
@@ -1204,24 +1210,17 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,

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

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

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

    inq = scsi_datain_unmarshall(task);
    if (inq == NULL) {
        error_setg(errp, "iSCSI: Failed to unmarshall inquiry data.");
    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;
    iscsilun->has_write_same = true;
    scsi_free_scsi_task(task);
    task = NULL;

    iscsi_readcapacity_sync(iscsilun, &local_err);
    if (local_err != NULL) {
@@ -1240,46 +1239,48 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
        bs->sg = 1;
    }

    if (iscsilun->lbpme) {
        struct scsi_inquiry_logical_block_provisioning *inq_lbp;
    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
                                SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
                                errp);
                            SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,
                            (void **) &inq_vpd, errp);
    if (task == NULL) {
        ret = -EINVAL;
        goto out;
    }
        inq_lbp = scsi_datain_unmarshall(task);
        if (inq_lbp == NULL) {
            error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
    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(task);
        task = NULL;
    }

    if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
        struct scsi_inquiry_block_limits *inq_bl;
        task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
                                SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, errp);
        if (task == NULL) {
            ret = -EINVAL;
            goto out;
        }
        inq_bl = scsi_datain_unmarshall(task);
        if (inq_bl == NULL) {
            error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
            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;
    }

#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
    /* Set up a timer for sending out iSCSI NOPs */