diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-28 13:19:24 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-28 13:19:24 -0600 |
commit | e6451fd372bbac8123414a88ed6d3296b66d4b5d (patch) | |
tree | 09fcea8a7f9b64dff18d190957a751bea5601a4e | |
parent | 0a6b2ac0cf92a4411cce38a22703d7a34a5b3601 (diff) | |
parent | 863d1050c96cff91dd478767c0da9cc288575919 (diff) | |
download | qemu-e6451fd372bbac8123414a88ed6d3296b66d4b5d.zip qemu-e6451fd372bbac8123414a88ed6d3296b66d4b5d.tar.gz qemu-e6451fd372bbac8123414a88ed6d3296b66d4b5d.tar.bz2 |
Merge remote-tracking branch 'bonzini/scsi-next' into staging
* bonzini/scsi-next:
virtio-scsi: Fix subtle (guest) endian bug
virtio-scsi: Fix some endian bugs with virtio-scsi
iscsi: do not assume device is zero initialized
iscsi: fix deadlock during login
iscsi: fix segfault in url parsing
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | block/iscsi.c | 260 | ||||
-rw-r--r-- | hw/virtio-scsi.c | 12 |
2 files changed, 84 insertions, 188 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index a6a819d..c0b70b3 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -65,13 +65,6 @@ typedef struct IscsiAIOCB { #endif } IscsiAIOCB; -struct IscsiTask { - IscsiLun *iscsilun; - BlockDriverState *bs; - int status; - int complete; -}; - static void iscsi_bh_cb(void *p) { @@ -380,7 +373,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors); break; } - + if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, iscsi_aio_read16_cb, NULL, @@ -665,163 +658,6 @@ iscsi_getlength(BlockDriverState *bs) return len; } -static void -iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, - void *command_data, void *opaque) -{ - struct IscsiTask *itask = opaque; - struct scsi_readcapacity16 *rc16; - struct scsi_task *task = command_data; - - if (status != 0) { - error_report("iSCSI: Failed to read capacity of iSCSI lun. %s", - iscsi_get_error(iscsi)); - itask->status = 1; - itask->complete = 1; - scsi_free_scsi_task(task); - return; - } - - rc16 = scsi_datain_unmarshall(task); - if (rc16 == NULL) { - error_report("iSCSI: Failed to unmarshall readcapacity16 data."); - itask->status = 1; - itask->complete = 1; - scsi_free_scsi_task(task); - return; - } - - itask->iscsilun->block_size = rc16->block_length; - itask->iscsilun->num_blocks = rc16->returned_lba + 1; - itask->bs->total_sectors = itask->iscsilun->num_blocks * - itask->iscsilun->block_size / BDRV_SECTOR_SIZE ; - - itask->status = 0; - itask->complete = 1; - scsi_free_scsi_task(task); -} - -static void -iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status, - void *command_data, void *opaque) -{ - struct IscsiTask *itask = opaque; - struct scsi_readcapacity10 *rc10; - struct scsi_task *task = command_data; - - if (status != 0) { - error_report("iSCSI: Failed to read capacity of iSCSI lun. %s", - iscsi_get_error(iscsi)); - itask->status = 1; - itask->complete = 1; - scsi_free_scsi_task(task); - return; - } - - rc10 = scsi_datain_unmarshall(task); - if (rc10 == NULL) { - error_report("iSCSI: Failed to unmarshall readcapacity10 data."); - itask->status = 1; - itask->complete = 1; - scsi_free_scsi_task(task); - return; - } - - itask->iscsilun->block_size = rc10->block_size; - if (rc10->lba == 0) { - /* blank disk loaded */ - itask->iscsilun->num_blocks = 0; - } else { - itask->iscsilun->num_blocks = rc10->lba + 1; - } - itask->bs->total_sectors = itask->iscsilun->num_blocks * - itask->iscsilun->block_size / BDRV_SECTOR_SIZE ; - - itask->status = 0; - itask->complete = 1; - scsi_free_scsi_task(task); -} - -static void -iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data, - void *opaque) -{ - struct IscsiTask *itask = opaque; - struct scsi_task *task = command_data; - struct scsi_inquiry_standard *inq; - - if (status != 0) { - itask->status = 1; - itask->complete = 1; - scsi_free_scsi_task(task); - return; - } - - inq = scsi_datain_unmarshall(task); - if (inq == NULL) { - error_report("iSCSI: Failed to unmarshall inquiry data."); - itask->status = 1; - itask->complete = 1; - scsi_free_scsi_task(task); - return; - } - - itask->iscsilun->type = inq->periperal_device_type; - - scsi_free_scsi_task(task); - - switch (itask->iscsilun->type) { - case TYPE_DISK: - task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun, - iscsi_readcapacity16_cb, opaque); - if (task == NULL) { - error_report("iSCSI: failed to send readcapacity16 command."); - itask->status = 1; - itask->complete = 1; - return; - } - break; - case TYPE_ROM: - task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun, - 0, 0, - iscsi_readcapacity10_cb, opaque); - if (task == NULL) { - error_report("iSCSI: failed to send readcapacity16 command."); - itask->status = 1; - itask->complete = 1; - return; - } - break; - default: - itask->status = 0; - itask->complete = 1; - } -} - -static void -iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, - void *opaque) -{ - struct IscsiTask *itask = opaque; - struct scsi_task *task; - - if (status != 0) { - itask->status = 1; - itask->complete = 1; - return; - } - - task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun, - 0, 0, 36, - iscsi_inquiry_cb, opaque); - if (task == NULL) { - error_report("iSCSI: failed to send inquiry command."); - itask->status = 1; - itask->complete = 1; - return; - } -} - static int parse_chap(struct iscsi_context *iscsi, const char *target) { QemuOptsList *list; @@ -934,7 +770,10 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = NULL; struct iscsi_url *iscsi_url = NULL; - struct IscsiTask task; + struct scsi_task *task = NULL; + struct scsi_inquiry_standard *inq = NULL; + struct scsi_readcapacity10 *rc10 = NULL; + struct scsi_readcapacity16 *rc16 = NULL; char *initiator_name = NULL; int ret; @@ -947,8 +786,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) iscsi_url = iscsi_parse_full_url(iscsi, filename); if (iscsi_url == NULL) { - error_report("Failed to parse URL : %s %s", filename, - iscsi_get_error(iscsi)); + error_report("Failed to parse URL : %s", filename); ret = -EINVAL; goto out; } @@ -998,33 +836,80 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) /* check if we got HEADER_DIGEST via the options */ parse_header_digest(iscsi, iscsi_url->target); - task.iscsilun = iscsilun; - task.status = 0; - task.complete = 0; - task.bs = bs; + if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) { + error_report("iSCSI: Failed to connect to LUN : %s", + iscsi_get_error(iscsi)); + ret = -EINVAL; + goto out; + } iscsilun->iscsi = iscsi; iscsilun->lun = iscsi_url->lun; - if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun, - iscsi_connect_cb, &task) - != 0) { - error_report("iSCSI: Failed to start async connect."); + task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36); + + if (task == NULL || task->status != SCSI_STATUS_GOOD) { + error_report("iSCSI: failed to send inquiry command."); ret = -EINVAL; goto out; } - while (!task.complete) { - iscsi_set_events(iscsilun); - qemu_aio_wait(); - } - if (task.status != 0) { - error_report("iSCSI: Failed to connect to LUN : %s", - iscsi_get_error(iscsi)); + inq = scsi_datain_unmarshall(task); + if (inq == NULL) { + error_report("iSCSI: Failed to unmarshall inquiry data."); ret = -EINVAL; goto out; } + iscsilun->type = inq->periperal_device_type; + + scsi_free_scsi_task(task); + + switch (iscsilun->type) { + case TYPE_DISK: + task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun); + if (task == NULL || task->status != SCSI_STATUS_GOOD) { + error_report("iSCSI: failed to send readcapacity16 command."); + ret = -EINVAL; + goto out; + } + 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(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; + } + + bs->total_sectors = iscsilun->num_blocks * + iscsilun->block_size / BDRV_SECTOR_SIZE ; + /* Medium changer or tape. We dont have any emulation for this so this must * be sg ioctl compatible. We force it to be sg, otherwise qemu will try * to read from the device to guess the image format. @@ -1043,6 +928,9 @@ out: if (iscsi_url != NULL) { iscsi_destroy_url(iscsi_url); } + if (task != NULL) { + scsi_free_scsi_task(task); + } if (ret) { if (iscsi != NULL) { @@ -1063,6 +951,11 @@ static void iscsi_close(BlockDriverState *bs) memset(iscsilun, 0, sizeof(IscsiLun)); } +static int iscsi_has_zero_init(BlockDriverState *bs) +{ + return 0; +} + static BlockDriver bdrv_iscsi = { .format_name = "iscsi", .protocol_name = "iscsi", @@ -1078,6 +971,7 @@ static BlockDriver bdrv_iscsi = { .bdrv_aio_flush = iscsi_aio_flush, .bdrv_aio_discard = iscsi_aio_discard, + .bdrv_has_zero_init = iscsi_has_zero_init, #ifdef __linux__ .bdrv_ioctl = iscsi_ioctl, diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 7d546f6..bfe1860 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -424,15 +424,17 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, size_t resid) { VirtIOSCSIReq *req = r->hba_private; + uint32_t sense_len; req->resp.cmd->response = VIRTIO_SCSI_S_OK; req->resp.cmd->status = status; if (req->resp.cmd->status == GOOD) { - req->resp.cmd->resid = resid; + req->resp.cmd->resid = tswap32(resid); } else { req->resp.cmd->resid = 0; - req->resp.cmd->sense_len = - scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE); + sense_len = scsi_req_get_sense(r, req->resp.cmd->sense, + VIRTIO_SCSI_SENSE_SIZE); + req->resp.cmd->sense_len = tswap32(sense_len); } virtio_scsi_complete_req(req); } @@ -532,8 +534,8 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent)); stl_raw(&scsiconf->sense_size, s->sense_size); stl_raw(&scsiconf->cdb_size, s->cdb_size); - stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL); - stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET); + stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL); + stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET); stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN); } |