bdev_virtio: retry sending scan requests
Scan requests will be re-sent if non-critical failure has happened. This is actually required, as some Virtio SCSI devices require a dummy request to clear it's POWER ON OCCURED unit attention status after Virtio device init. The very first request might fail with asc = 0x29 (POWER ON, RESET, OR BUS RESET OCCURED), but subsequent requests will be processed correctly. Change-Id: I809bfe7952062995078f33dccb92192d722e6574 Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/383689 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
fde584034d
commit
cfa668375b
@ -57,6 +57,7 @@
|
||||
#define BDEV_VIRTIO_SCAN_PAYLOAD_SIZE 256
|
||||
#define CTRLQ_POLL_PERIOD_US (1000 * 5)
|
||||
#define CTRLQ_RING_SIZE 16
|
||||
#define SCAN_REQUEST_RETRIES 5
|
||||
|
||||
#define VIRTIO_SCSI_CONTROLQ 0
|
||||
#define VIRTIO_SCSI_EVENTQ 1
|
||||
@ -92,6 +93,9 @@ struct virtio_scsi_scan_base {
|
||||
/* Disks to be registered after the scan finishes */
|
||||
TAILQ_HEAD(, virtio_scsi_disk) found_disks;
|
||||
|
||||
/** Remaining attempts for sending the current request. */
|
||||
unsigned retries;
|
||||
|
||||
struct virtio_scsi_io_ctx io_ctx;
|
||||
struct iovec iov;
|
||||
uint8_t payload[BDEV_VIRTIO_SCAN_PAYLOAD_SIZE];
|
||||
@ -782,7 +786,9 @@ static void
|
||||
process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
|
||||
{
|
||||
struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base;
|
||||
int rc;
|
||||
struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base;
|
||||
int rc, sk, asc, ascq;
|
||||
uint8_t target_id;
|
||||
|
||||
if (vreq->iov_req.iov_len < sizeof(struct virtio_scsi_cmd_req) ||
|
||||
vreq->iov_resp.iov_len < sizeof(struct virtio_scsi_cmd_resp)) {
|
||||
@ -791,6 +797,32 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
|
||||
return;
|
||||
}
|
||||
|
||||
get_scsi_status(resp, &sk, &asc, &ascq);
|
||||
target_id = req->lun[1];
|
||||
|
||||
if (resp->response == VIRTIO_SCSI_S_OK &&
|
||||
resp->status == SPDK_SCSI_STATUS_CHECK_CONDITION &&
|
||||
sk != SPDK_SCSI_SENSE_ILLEGAL_REQUEST) {
|
||||
assert(base->retries > 0);
|
||||
base->retries--;
|
||||
if (base->retries == 0) {
|
||||
SPDK_NOTICELOG("Target %"PRIu8" is present, but unavailable.\n", target_id);
|
||||
SPDK_TRACEDUMP(SPDK_TRACE_VIRTIO, "CDB", req->cdb, sizeof(req->cdb));
|
||||
SPDK_TRACEDUMP(SPDK_TRACE_VIRTIO, "SENSE DATA", resp->sense, sizeof(resp->sense));
|
||||
scan_target_finish(base);
|
||||
return;
|
||||
}
|
||||
|
||||
/* resend the same request */
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
base->retries = SCAN_REQUEST_RETRIES;
|
||||
|
||||
switch (req->cdb[0]) {
|
||||
case SPDK_SPC_INQUIRY:
|
||||
rc = process_scan_inquiry(base, vreq);
|
||||
@ -859,6 +891,7 @@ scan_target(struct virtio_scsi_scan_base *base)
|
||||
cdb->opcode = SPDK_SPC_INQUIRY;
|
||||
cdb->alloc_len[1] = 255;
|
||||
|
||||
base->retries = SCAN_REQUEST_RETRIES;
|
||||
return virtio_xmit_pkt(base->vq, vreq);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user