Commit 3ed8a843 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

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



# By Paolo Bonzini (3) and others
# Via Paolo Bonzini
* bonzini/scsi-next:
  iscsi: reorganize iscsi_readcapacity_sync
  iscsi: simplify freeing of tasks
  vhost-scsi: fix k->set_guest_notifiers() NULL dereference
  scsi-disk: scsi-block device for scsi pass-through should not be removable
  scsi-generic: check the return value of bdrv_aio_ioctl in execute_command
  scsi-generic: fix sign extension of READ CAPACITY(10) data
  scsi: reset cdrom tray statuses on scsi_disk_reset

Message-id: 1371565016-2643-1-git-send-email-pbonzini@redhat.com
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parents 7d8f4b34 1288844e
Loading
Loading
Loading
Loading
+56 −73
Original line number Diff line number Diff line
@@ -218,10 +218,8 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
        if (status == SCSI_STATUS_CHECK_CONDITION
            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
            && acb->retries-- > 0) {
            if (acb->task != NULL) {
            scsi_free_scsi_task(acb->task);
            acb->task = NULL;
            }
            if (iscsi_aio_writev_acb(acb) == 0) {
                iscsi_set_events(acb->iscsilun);
                return;
@@ -303,6 +301,7 @@ iscsi_aio_writev_acb(IscsiAIOCB *acb)
                                   acb);
#endif
    if (ret != 0) {
        scsi_free_scsi_task(acb->task);
        g_free(acb->buf);
        return -1;
    }
@@ -333,9 +332,6 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
    acb->retries     = ISCSI_CMD_RETRIES;

    if (iscsi_aio_writev_acb(acb) != 0) {
        if (acb->task) {
            scsi_free_scsi_task(acb->task);
        }
        qemu_aio_release(acb);
        return NULL;
    }
@@ -364,10 +360,8 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
        if (status == SCSI_STATUS_CHECK_CONDITION
            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
            && acb->retries-- > 0) {
            if (acb->task != NULL) {
            scsi_free_scsi_task(acb->task);
            acb->task = NULL;
            }
            if (iscsi_aio_readv_acb(acb) == 0) {
                iscsi_set_events(acb->iscsilun);
                return;
@@ -445,6 +439,7 @@ iscsi_aio_readv_acb(IscsiAIOCB *acb)
                                   NULL,
                                   acb);
    if (ret != 0) {
        scsi_free_scsi_task(acb->task);
        return -1;
    }

@@ -480,9 +475,6 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
    acb->retries     = ISCSI_CMD_RETRIES;

    if (iscsi_aio_readv_acb(acb) != 0) {
        if (acb->task) {
            scsi_free_scsi_task(acb->task);
        }
        qemu_aio_release(acb);
        return NULL;
    }
@@ -509,10 +501,8 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
        if (status == SCSI_STATUS_CHECK_CONDITION
            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
            && acb->retries-- > 0) {
            if (acb->task != NULL) {
            scsi_free_scsi_task(acb->task);
            acb->task = NULL;
            }
            if (iscsi_aio_flush_acb(acb) == 0) {
                iscsi_set_events(acb->iscsilun);
                return;
@@ -589,10 +579,8 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
        if (status == SCSI_STATUS_CHECK_CONDITION
            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
            && acb->retries-- > 0) {
            if (acb->task != NULL) {
            scsi_free_scsi_task(acb->task);
            acb->task = NULL;
            }
            if (iscsi_aio_discard_acb(acb) == 0) {
                iscsi_set_events(acb->iscsilun);
                return;
@@ -647,9 +635,6 @@ iscsi_aio_discard(BlockDriverState *bs,
    acb->retries     = ISCSI_CMD_RETRIES;

    if (iscsi_aio_discard_acb(acb) != 0) {
        if (acb->task) {
            scsi_free_scsi_task(acb->task);
        }
        qemu_aio_release(acb);
        return NULL;
    }
@@ -946,43 +931,34 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
    int ret = 0;
    int retries = ISCSI_CMD_RETRIES; 

try_again:
    do {
        if (task != NULL) {
            scsi_free_scsi_task(task);
            task = NULL;
        }

        switch (iscsilun->type) {
        case TYPE_DISK:
            task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
            if (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
                    && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
                    && retries-- > 0) {
                scsi_free_scsi_task(task);
                goto try_again;
            }
            error_report("iSCSI: failed to send readcapacity16 command.");
            ret = -EINVAL;
            goto out;
        }
            if (task != NULL && task->status == SCSI_STATUS_GOOD) {
                rc16 = scsi_datain_unmarshall(task);
                if (rc16 == NULL) {
                    error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
                    ret = -EINVAL;
            goto out;
        }
                } else {
                    iscsilun->block_size = rc16->block_length;
                    iscsilun->num_blocks = rc16->returned_lba + 1;
                }
            }
            break;
        case TYPE_ROM:
            task = iscsi_readcapacity10_sync(iscsilun->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;
        }
            if (task != NULL && task->status == SCSI_STATUS_GOOD) {
                rc10 = scsi_datain_unmarshall(task);
                if (rc10 == NULL) {
                    error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
                    ret = -EINVAL;
            goto out;
        }
                } else {
                    iscsilun->block_size = rc10->block_size;
                    if (rc10->lba == 0) {
                        /* blank disk loaded */
@@ -990,16 +966,23 @@ try_again:
                    } else {
                        iscsilun->num_blocks = rc10->lba + 1;
                    }
                }
            }
            break;
        default:
        break;
            return 0;
        }
    } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
             && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
             && retries-- > 0);

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

    return ret;
}

+14 −3
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ typedef struct SCSIDiskReq {

#define SCSI_DISK_F_REMOVABLE             0
#define SCSI_DISK_F_DPOFUA                1
#define SCSI_DISK_F_NO_REMOVABLE_DEVOPS   2

struct SCSIDiskState
{
@@ -1984,6 +1985,9 @@ static void scsi_disk_reset(DeviceState *dev)
        nb_sectors--;
    }
    s->qdev.max_lba = nb_sectors;
    /* reset tray statuses */
    s->tray_locked = 0;
    s->tray_open = 0;
}

static void scsi_destroy(SCSIDevice *dev)
@@ -2107,7 +2111,8 @@ static int scsi_initfn(SCSIDevice *dev)
        return -1;
    }

    if (s->features & (1 << SCSI_DISK_F_REMOVABLE)) {
    if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) &&
            !(s->features & (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS))) {
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_removable_block_ops, s);
    } else {
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_block_ops, s);
@@ -2319,6 +2324,12 @@ static int scsi_block_initfn(SCSIDevice *dev)
    } else {
        s->qdev.blocksize = 512;
    }

    /* Makes the scsi-block device not removable by using HMP and QMP eject
     * command.
     */
    s->features |= (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS);

    return scsi_initfn(&s->qdev);
}

+6 −2
Original line number Diff line number Diff line
@@ -174,6 +174,9 @@ static int execute_command(BlockDriverState *bdrv,
    r->io_header.flags |= SG_FLAG_DIRECT_IO;

    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
    if (r->req.aiocb == NULL) {
        return -EIO;
    }

    return 0;
}
@@ -198,9 +201,10 @@ static void scsi_read_complete(void * opaque, int ret)
        scsi_command_complete(r, 0);
    } else {
        /* Snoop READ CAPACITY output to set the blocksize.  */
        if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
        if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
            (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
            s->blocksize = ldl_be_p(&r->buf[4]);
            s->max_lba = ldl_be_p(&r->buf[0]);
            s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
            s->blocksize = ldl_be_p(&r->buf[8]);
+1 −1
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ static void vhost_scsi_stop(VHostSCSI *s)
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
    int ret = 0;

    if (!k->set_guest_notifiers) {
    if (k->set_guest_notifiers) {
        ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
        if (ret < 0) {
                error_report("vhost guest notifier cleanup failed: %d\n", ret);