Commit 739aa555 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/bonzini/scsi-next' into staging



* remotes/bonzini/scsi-next:
  block/iscsi: fix segfault if writesame fails
  scsi-disk: Add support for port WWN and index descriptors in VPD page 83h
  block/iscsi: query for supported VPD pages
  block/iscsi: fix deadlock on scsi check condition
  scsi-bus: Fix transfer length for VERIFY with BYTCHK=11b
  scsi: report thin provisioning errors with werror=report
  scsi: Change scsi sense buf size to 252

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents d47e95c0 d9738fd2
Loading
Loading
Loading
Loading
+71 −62
Original line number Diff line number Diff line
@@ -145,12 +145,13 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,

    if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
        && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
        error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi));
        iTask->do_retry = 1;
        goto out;
    }

    if (status != SCSI_STATUS_GOOD) {
        error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi));
        error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
    }

out:
@@ -325,6 +326,7 @@ retry:
    }

    if (iTask.do_retry) {
        iTask.complete = 0;
        goto retry;
    }

@@ -399,6 +401,7 @@ retry:
    }

    if (iTask.do_retry) {
        iTask.complete = 0;
        goto retry;
    }

@@ -433,6 +436,7 @@ retry:
    }

    if (iTask.do_retry) {
        iTask.complete = 0;
        goto retry;
    }

@@ -683,6 +687,7 @@ retry:
            scsi_free_scsi_task(iTask.task);
            iTask.task = NULL;
        }
        iTask.complete = 0;
        goto retry;
    }

@@ -767,6 +772,7 @@ retry:
    }

    if (iTask.do_retry) {
        iTask.complete = 0;
        goto retry;
    }

@@ -830,24 +836,26 @@ retry:
        qemu_coroutine_yield();
    }

    if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
        iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
        iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
        /* WRITE SAME is not supported by the target */
        iscsilun->has_write_same = false;
        scsi_free_scsi_task(iTask.task);
        return -ENOTSUP;
    }

    if (iTask.task != NULL) {
        scsi_free_scsi_task(iTask.task);
        iTask.task = NULL;
    }

    if (iTask.do_retry) {
        iTask.complete = 0;
        goto retry;
    }

    if (iTask.status != SCSI_STATUS_GOOD) {
        if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
            iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
            iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
            /* WRITE SAME is not supported by the target */
            iscsilun->has_write_same = false;
            return -ENOTSUP;
        }

        return -EIO;
    }

@@ -1060,7 +1068,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;
@@ -1079,14 +1087,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;
}
@@ -1107,11 +1120,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. "
@@ -1197,24 +1211,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) {
@@ -1233,46 +1240,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 */
+6 −1
Original line number Diff line number Diff line
@@ -909,7 +909,7 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
    case VERIFY_16:
        if ((buf[1] & 2) == 0) {
            cmd->xfer = 0;
        } else if ((buf[1] & 4) == 1) {
        } else if ((buf[1] & 4) != 0) {
            cmd->xfer = 1;
        }
        cmd->xfer *= dev->blocksize;
@@ -1367,6 +1367,11 @@ const struct SCSISense sense_code_WRITE_PROTECTED = {
    .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00
};

/* Data Protection, Space Allocation Failed Write Protect */
const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
    .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
};

/*
 * scsi_build_sense
 *
+29 −0
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@ struct SCSIDiskState
    bool media_event;
    bool eject_request;
    uint64_t wwn;
    uint64_t port_wwn;
    uint16_t port_index;
    uint64_t max_unmap_size;
    QEMUBH *bh;
    char *version;
@@ -428,6 +430,9 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
        case EINVAL:
            scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
            break;
        case ENOSPC:
            scsi_check_condition(r, SENSE_CODE(SPACE_ALLOC_FAILED));
            break;
        default:
            scsi_check_condition(r, SENSE_CODE(IO_ERROR));
            break;
@@ -617,6 +622,24 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
                stq_be_p(&outbuf[buflen], s->wwn);
                buflen += 8;
            }

            if (s->port_wwn) {
                outbuf[buflen++] = 0x61; // SAS / Binary
                outbuf[buflen++] = 0x93; // PIV / Target port / NAA
                outbuf[buflen++] = 0;    // reserved
                outbuf[buflen++] = 8;
                stq_be_p(&outbuf[buflen], s->port_wwn);
                buflen += 8;
            }

            if (s->port_index) {
                outbuf[buflen++] = 0x61; // SAS / Binary
                outbuf[buflen++] = 0x94; // PIV / Target port / relative target port
                outbuf[buflen++] = 0;    // reserved
                outbuf[buflen++] = 4;
                stw_be_p(&outbuf[buflen + 2], s->port_index);
                buflen += 4;
            }
            break;
        }
        case 0xb0: /* block limits */
@@ -2536,6 +2559,8 @@ static Property scsi_hd_properties[] = {
    DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
                    SCSI_DISK_F_DPOFUA, false),
    DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0),
    DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0),
    DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0),
    DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size,
                       DEFAULT_MAX_UNMAP_SIZE),
    DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
@@ -2584,6 +2609,8 @@ static const TypeInfo scsi_hd_info = {
static Property scsi_cd_properties[] = {
    DEFINE_SCSI_DISK_PROPERTIES(),
    DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0),
    DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0),
    DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0),
    DEFINE_PROP_END_OF_LIST(),
};

@@ -2647,6 +2674,8 @@ static Property scsi_disk_properties[] = {
    DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
                    SCSI_DISK_F_DPOFUA, false),
    DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0),
    DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0),
    DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0),
    DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size,
                       DEFAULT_MAX_UNMAP_SIZE),
    DEFINE_PROP_END_OF_LIST(),
+0 −2
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
#include <scsi/sg.h>
#include "block/scsi.h"

#define SCSI_SENSE_BUF_SIZE 96

#define SG_ERR_DRIVER_TIMEOUT  0x06
#define SG_ERR_DRIVER_SENSE    0x08

+0 −1
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@
#define VSCSI_MAX_SECTORS       4096
#define VSCSI_REQ_LIMIT         24

#define SCSI_SENSE_BUF_SIZE     96
#define SRP_RSP_SENSE_DATA_LEN  18

typedef union vscsi_crq {
Loading