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>
This commit is contained in:
commit
3ed8a8430a
131
block/iscsi.c
131
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
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;
|
||||
}
|
||||
} while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION
|
||||
&& retries-- > 0);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user