diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-03-04 14:25:34 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-03-04 14:25:34 +0000 |
commit | 739aa555b8d6e45920b44cb7a2a790fce5061890 (patch) | |
tree | 4cd7e0f966b3ad13dc819070ee6351eae489fb58 /block | |
parent | d47e95c0c86ea5d8d050bf201ee27bcec617c10e (diff) | |
parent | d9738fd2463f71530d8d92fbb52ebdd1d78074fc (diff) | |
download | qemu-739aa555b8d6e45920b44cb7a2a790fce5061890.zip qemu-739aa555b8d6e45920b44cb7a2a790fce5061890.tar.gz qemu-739aa555b8d6e45920b44cb7a2a790fce5061890.tar.bz2 |
Merge remote-tracking branch 'remotes/bonzini/scsi-next' into staging
* remotes/bonzini/scsi-next:
block/iscsi: fix segfault if writesame fails
scsi-disk: Add support for port WWN and index descriptors in VPD page 83h
block/iscsi: query for supported VPD pages
block/iscsi: fix deadlock on scsi check condition
scsi-bus: Fix transfer length for VERIFY with BYTCHK=11b
scsi: report thin provisioning errors with werror=report
scsi: Change scsi sense buf size to 252
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block')
-rw-r--r-- | block/iscsi.c | 133 |
1 files changed, 71 insertions, 62 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index 41ec097..0a15f53 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -145,12 +145,13 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) { + error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi)); iTask->do_retry = 1; goto out; } if (status != SCSI_STATUS_GOOD) { - error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi)); + error_report("iSCSI Failure: %s", iscsi_get_error(iscsi)); } out: @@ -325,6 +326,7 @@ retry: } if (iTask.do_retry) { + iTask.complete = 0; goto retry; } @@ -399,6 +401,7 @@ retry: } if (iTask.do_retry) { + iTask.complete = 0; goto retry; } @@ -433,6 +436,7 @@ retry: } if (iTask.do_retry) { + iTask.complete = 0; goto retry; } @@ -683,6 +687,7 @@ retry: scsi_free_scsi_task(iTask.task); iTask.task = NULL; } + iTask.complete = 0; goto retry; } @@ -767,6 +772,7 @@ retry: } if (iTask.do_retry) { + iTask.complete = 0; goto retry; } @@ -830,24 +836,26 @@ retry: qemu_coroutine_yield(); } + if (iTask.status == SCSI_STATUS_CHECK_CONDITION && + iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { + /* WRITE SAME is not supported by the target */ + iscsilun->has_write_same = false; + scsi_free_scsi_task(iTask.task); + return -ENOTSUP; + } + if (iTask.task != NULL) { scsi_free_scsi_task(iTask.task); iTask.task = NULL; } if (iTask.do_retry) { + iTask.complete = 0; goto retry; } if (iTask.status != SCSI_STATUS_GOOD) { - if (iTask.status == SCSI_STATUS_CHECK_CONDITION && - iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { - /* WRITE SAME is not supported by the target */ - iscsilun->has_write_same = false; - return -ENOTSUP; - } - return -EIO; } @@ -1060,7 +1068,7 @@ static QemuOptsList runtime_opts = { }; static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun, - int evpd, int pc, Error **errp) + int evpd, int pc, void **inq, Error **errp) { int full_size; struct scsi_task *task = NULL; @@ -1079,14 +1087,19 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun, } } + *inq = scsi_datain_unmarshall(task); + if (*inq == NULL) { + error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob"); + goto fail; + } + return task; fail: error_setg(errp, "iSCSI: Inquiry command failed : %s", iscsi_get_error(iscsi)); - if (task) { + if (task != NULL) { scsi_free_scsi_task(task); - return NULL; } return NULL; } @@ -1107,11 +1120,12 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, struct iscsi_url *iscsi_url = NULL; struct scsi_task *task = NULL; struct scsi_inquiry_standard *inq = NULL; + struct scsi_inquiry_supported_pages *inq_vpd; char *initiator_name = NULL; QemuOpts *opts; Error *local_err = NULL; const char *filename; - int ret; + int i, ret; if ((BDRV_SECTOR_SIZE % 512) != 0) { error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. " @@ -1197,24 +1211,17 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, iscsilun->iscsi = iscsi; iscsilun->lun = iscsi_url->lun; + iscsilun->has_write_same = true; - task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36); - - if (task == NULL || task->status != SCSI_STATUS_GOOD) { - error_setg(errp, "iSCSI: failed to send inquiry command."); - ret = -EINVAL; - goto out; - } - - inq = scsi_datain_unmarshall(task); - if (inq == NULL) { - error_setg(errp, "iSCSI: Failed to unmarshall inquiry data."); + task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0, + (void **) &inq, errp); + if (task == NULL) { ret = -EINVAL; goto out; } - iscsilun->type = inq->periperal_device_type; - iscsilun->has_write_same = true; + scsi_free_scsi_task(task); + task = NULL; iscsi_readcapacity_sync(iscsilun, &local_err); if (local_err != NULL) { @@ -1233,46 +1240,48 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, bs->sg = 1; } - if (iscsilun->lbpme) { - struct scsi_inquiry_logical_block_provisioning *inq_lbp; - task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1, - SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, - errp); - if (task == NULL) { - ret = -EINVAL; - goto out; - } - inq_lbp = scsi_datain_unmarshall(task); - if (inq_lbp == NULL) { - error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob"); - ret = -EINVAL; - goto out; - } - memcpy(&iscsilun->lbp, inq_lbp, - sizeof(struct scsi_inquiry_logical_block_provisioning)); - scsi_free_scsi_task(task); - task = NULL; + task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1, + SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, + (void **) &inq_vpd, errp); + if (task == NULL) { + ret = -EINVAL; + goto out; } - - if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) { + for (i = 0; i < inq_vpd->num_pages; i++) { + struct scsi_task *inq_task; + struct scsi_inquiry_logical_block_provisioning *inq_lbp; struct scsi_inquiry_block_limits *inq_bl; - task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1, - SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, errp); - if (task == NULL) { - ret = -EINVAL; - goto out; - } - inq_bl = scsi_datain_unmarshall(task); - if (inq_bl == NULL) { - error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob"); - ret = -EINVAL; - goto out; + switch (inq_vpd->pages[i]) { + case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING: + inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1, + SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, + (void **) &inq_lbp, errp); + if (inq_task == NULL) { + ret = -EINVAL; + goto out; + } + memcpy(&iscsilun->lbp, inq_lbp, + sizeof(struct scsi_inquiry_logical_block_provisioning)); + scsi_free_scsi_task(inq_task); + break; + case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS: + inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1, + SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, + (void **) &inq_bl, errp); + if (inq_task == NULL) { + ret = -EINVAL; + goto out; + } + memcpy(&iscsilun->bl, inq_bl, + sizeof(struct scsi_inquiry_block_limits)); + scsi_free_scsi_task(inq_task); + break; + default: + break; } - memcpy(&iscsilun->bl, inq_bl, - sizeof(struct scsi_inquiry_block_limits)); - scsi_free_scsi_task(task); - task = NULL; } + scsi_free_scsi_task(task); + task = NULL; #if defined(LIBISCSI_FEATURE_NOP_COUNTER) /* Set up a timer for sending out iSCSI NOPs */ |