提交 e6451fd3 编写于 作者: A Anthony Liguori

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: NAnthony Liguori <aliguori@us.ibm.com>
...@@ -65,13 +65,6 @@ typedef struct IscsiAIOCB { ...@@ -65,13 +65,6 @@ typedef struct IscsiAIOCB {
#endif #endif
} IscsiAIOCB; } IscsiAIOCB;
struct IscsiTask {
IscsiLun *iscsilun;
BlockDriverState *bs;
int status;
int complete;
};
static void static void
iscsi_bh_cb(void *p) iscsi_bh_cb(void *p)
{ {
...@@ -380,7 +373,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, ...@@ -380,7 +373,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
*(uint16_t *)&acb->task->cdb[7] = htons(num_sectors); *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
break; break;
} }
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
iscsi_aio_read16_cb, iscsi_aio_read16_cb,
NULL, NULL,
...@@ -665,163 +658,6 @@ iscsi_getlength(BlockDriverState *bs) ...@@ -665,163 +658,6 @@ iscsi_getlength(BlockDriverState *bs)
return len; 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) static int parse_chap(struct iscsi_context *iscsi, const char *target)
{ {
QemuOptsList *list; QemuOptsList *list;
...@@ -934,7 +770,10 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) ...@@ -934,7 +770,10 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;
struct iscsi_context *iscsi = NULL; struct iscsi_context *iscsi = NULL;
struct iscsi_url *iscsi_url = 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; char *initiator_name = NULL;
int ret; int ret;
...@@ -947,8 +786,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) ...@@ -947,8 +786,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
iscsi_url = iscsi_parse_full_url(iscsi, filename); iscsi_url = iscsi_parse_full_url(iscsi, filename);
if (iscsi_url == NULL) { if (iscsi_url == NULL) {
error_report("Failed to parse URL : %s %s", filename, error_report("Failed to parse URL : %s", filename);
iscsi_get_error(iscsi));
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
...@@ -998,33 +836,80 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) ...@@ -998,33 +836,80 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
/* check if we got HEADER_DIGEST via the options */ /* check if we got HEADER_DIGEST via the options */
parse_header_digest(iscsi, iscsi_url->target); parse_header_digest(iscsi, iscsi_url->target);
task.iscsilun = iscsilun; if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
task.status = 0; error_report("iSCSI: Failed to connect to LUN : %s",
task.complete = 0; iscsi_get_error(iscsi));
task.bs = bs; ret = -EINVAL;
goto out;
}
iscsilun->iscsi = iscsi; iscsilun->iscsi = iscsi;
iscsilun->lun = iscsi_url->lun; iscsilun->lun = iscsi_url->lun;
if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun, task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
iscsi_connect_cb, &task)
!= 0) { if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_report("iSCSI: Failed to start async connect."); error_report("iSCSI: failed to send inquiry command.");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
while (!task.complete) { inq = scsi_datain_unmarshall(task);
iscsi_set_events(iscsilun); if (inq == NULL) {
qemu_aio_wait(); error_report("iSCSI: Failed to unmarshall inquiry data.");
}
if (task.status != 0) {
error_report("iSCSI: Failed to connect to LUN : %s",
iscsi_get_error(iscsi));
ret = -EINVAL; ret = -EINVAL;
goto out; 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 /* 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 * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
* to read from the device to guess the image format. * to read from the device to guess the image format.
...@@ -1043,6 +928,9 @@ out: ...@@ -1043,6 +928,9 @@ out:
if (iscsi_url != NULL) { if (iscsi_url != NULL) {
iscsi_destroy_url(iscsi_url); iscsi_destroy_url(iscsi_url);
} }
if (task != NULL) {
scsi_free_scsi_task(task);
}
if (ret) { if (ret) {
if (iscsi != NULL) { if (iscsi != NULL) {
...@@ -1063,6 +951,11 @@ static void iscsi_close(BlockDriverState *bs) ...@@ -1063,6 +951,11 @@ static void iscsi_close(BlockDriverState *bs)
memset(iscsilun, 0, sizeof(IscsiLun)); memset(iscsilun, 0, sizeof(IscsiLun));
} }
static int iscsi_has_zero_init(BlockDriverState *bs)
{
return 0;
}
static BlockDriver bdrv_iscsi = { static BlockDriver bdrv_iscsi = {
.format_name = "iscsi", .format_name = "iscsi",
.protocol_name = "iscsi", .protocol_name = "iscsi",
...@@ -1078,6 +971,7 @@ static BlockDriver bdrv_iscsi = { ...@@ -1078,6 +971,7 @@ static BlockDriver bdrv_iscsi = {
.bdrv_aio_flush = iscsi_aio_flush, .bdrv_aio_flush = iscsi_aio_flush,
.bdrv_aio_discard = iscsi_aio_discard, .bdrv_aio_discard = iscsi_aio_discard,
.bdrv_has_zero_init = iscsi_has_zero_init,
#ifdef __linux__ #ifdef __linux__
.bdrv_ioctl = iscsi_ioctl, .bdrv_ioctl = iscsi_ioctl,
......
...@@ -424,15 +424,17 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, ...@@ -424,15 +424,17 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
size_t resid) size_t resid)
{ {
VirtIOSCSIReq *req = r->hba_private; VirtIOSCSIReq *req = r->hba_private;
uint32_t sense_len;
req->resp.cmd->response = VIRTIO_SCSI_S_OK; req->resp.cmd->response = VIRTIO_SCSI_S_OK;
req->resp.cmd->status = status; req->resp.cmd->status = status;
if (req->resp.cmd->status == GOOD) { if (req->resp.cmd->status == GOOD) {
req->resp.cmd->resid = resid; req->resp.cmd->resid = tswap32(resid);
} else { } else {
req->resp.cmd->resid = 0; req->resp.cmd->resid = 0;
req->resp.cmd->sense_len = sense_len = scsi_req_get_sense(r, req->resp.cmd->sense,
scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE); VIRTIO_SCSI_SENSE_SIZE);
req->resp.cmd->sense_len = tswap32(sense_len);
} }
virtio_scsi_complete_req(req); virtio_scsi_complete_req(req);
} }
...@@ -532,8 +534,8 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, ...@@ -532,8 +534,8 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent)); stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
stl_raw(&scsiconf->sense_size, s->sense_size); stl_raw(&scsiconf->sense_size, s->sense_size);
stl_raw(&scsiconf->cdb_size, s->cdb_size); stl_raw(&scsiconf->cdb_size, s->cdb_size);
stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL); stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET); stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN); stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册