diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2013-06-18 10:06:47 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-06-18 10:06:47 -0500 |
commit | 3ed8a8430a896088db55ae029e9eac200aedbe5c (patch) | |
tree | 59c7a9dbf8cb6ad5b590b07e01beac518e6d20d0 | |
parent | 7d8f4b34a4bb6996d958da211f1dfb2686c7d82b (diff) | |
parent | 1288844e7c4ede59509bf697a4cca0f2215a1ce3 (diff) |
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: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | block/iscsi.c | 129 | ||||
-rw-r--r-- | hw/scsi/scsi-disk.c | 17 | ||||
-rw-r--r-- | hw/scsi/scsi-generic.c | 8 | ||||
-rw-r--r-- | hw/scsi/vhost-scsi.c | 2 |
4 files changed, 77 insertions, 79 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index f7199c1abb..0bbf0b18b4 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -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; - } + 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; - } + 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; - } + 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; - } + 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,60 +931,58 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun) int ret = 0; int retries = ISCSI_CMD_RETRIES; -try_again: - 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; + do { + if (task != NULL) { + scsi_free_scsi_task(task); + task = NULL; } - 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(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; - } - 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; + + switch (iscsilun->type) { + case TYPE_DISK: + task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun); + 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; + } 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) { + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + error_report("iSCSI: Failed to unmarshall readcapacity10 data."); + ret = -EINVAL; + } else { + 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: + return 0; } - break; - default: - break; - } + } 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; } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index c8d2a99593..74e6a14c29 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -61,8 +61,9 @@ typedef struct SCSIDiskReq { BlockAcctCookie acct; } SCSIDiskReq; -#define SCSI_DISK_F_REMOVABLE 0 -#define SCSI_DISK_F_DPOFUA 1 +#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); } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 2a9a561127..8f195bec00 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -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]); diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index d7a1c33183..785e93f545 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -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); |