diff --git a/lib/bdev/virtio/bdev_virtio.c b/lib/bdev/virtio/bdev_virtio.c index 1f25db10e5..b9af17655a 100644 --- a/lib/bdev/virtio/bdev_virtio.c +++ b/lib/bdev/virtio/bdev_virtio.c @@ -310,31 +310,53 @@ scan_target_finish(struct virtio_scsi_scan_base *base) spdk_bdev_module_init_done(SPDK_GET_BDEV_MODULE(virtio_scsi)); } -static int -process_scan_inquiry(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) +static void +send_read_cap_10(struct virtio_scsi_scan_base *base, uint8_t target_id, struct virtio_req *vreq) { struct iovec *iov = vreq->iov; struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base; + + memset(req, 0, sizeof(*req)); + req->lun[0] = 1; + req->lun[1] = target_id; + + iov[0].iov_len = 8; + req->cdb[0] = SPDK_SBC_READ_CAPACITY_10; + + virtio_xmit_pkts(base->vdev->vqs[2], vreq); +} + +static void +send_read_cap_16(struct virtio_scsi_scan_base *base, uint8_t target_id, struct virtio_req *vreq) +{ + struct iovec *iov = vreq->iov; + struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base; + + memset(req, 0, sizeof(*req)); + req->lun[0] = 1; + req->lun[1] = target_id; + + iov[0].iov_len = 32; + req->cdb[0] = SPDK_SPC_SERVICE_ACTION_IN_16; + req->cdb[1] = SPDK_SBC_SAI_READ_CAPACITY_16; + to_be32(&req->cdb[10], iov[0].iov_len); + + virtio_xmit_pkts(base->vdev->vqs[2], vreq); +} + +static int +process_scan_inquiry(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) +{ + struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base; struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base; - uint8_t lun_id; + uint8_t target_id; if (resp->response != VIRTIO_SCSI_S_OK || resp->status != SPDK_SCSI_STATUS_GOOD) { return -1; } - lun_id = req->lun[1]; - /* reuse vreq for next request */ - memset(req, 0, sizeof(*req)); - req->lun[0] = 1; - req->lun[1] = lun_id; - - req->cdb[0] = SPDK_SPC_SERVICE_ACTION_IN_16; - req->cdb[1] = SPDK_SBC_SAI_READ_CAPACITY_16; - - iov[0].iov_len = 32; - to_be32(&req->cdb[10], iov[0].iov_len); - - virtio_xmit_pkts(base->vdev->vqs[2], vreq); + target_id = req->lun[1]; + send_read_cap_10(base, target_id, vreq); return 0; } @@ -371,7 +393,34 @@ alloc_virtio_disk(struct virtio_scsi_scan_base *base, uint64_t num_blocks, uint3 } static int -process_read_cap(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) +process_read_cap_10(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) +{ + struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base; + struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base; + uint64_t max_block; + uint32_t block_size; + uint8_t target_id; + + if (resp->response != VIRTIO_SCSI_S_OK || resp->status != SPDK_SCSI_STATUS_GOOD) { + SPDK_ERRLOG("READ CAPACITY (10) failed for target %"PRIu8".\n", req->lun[1]); + return -1; + } + + block_size = from_be32((uint8_t *)vreq->iov[0].iov_base + 4); + max_block = from_be32(vreq->iov[0].iov_base); + + if (max_block == 0xffffffff) { + target_id = req->lun[1]; + + send_read_cap_16(base, target_id, vreq); + return 0; + } + + return alloc_virtio_disk(base, max_block + 1, block_size); +} + +static int +process_read_cap_16(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) { struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base; struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base; @@ -379,7 +428,7 @@ process_read_cap(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) uint32_t block_size; if (resp->response != VIRTIO_SCSI_S_OK || resp->status != SPDK_SCSI_STATUS_GOOD) { - SPDK_ERRLOG("read capacity failed for target %"PRIu8".\n", req->lun[1]); + SPDK_ERRLOG("READ CAPACITY (16) failed for target %"PRIu8".\n", req->lun[1]); return -1; } @@ -405,8 +454,11 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) case SPDK_SPC_INQUIRY: rc = process_scan_inquiry(base, vreq); break; + case SPDK_SBC_READ_CAPACITY_10: + rc = process_read_cap_10(base, vreq); + break; case SPDK_SPC_SERVICE_ACTION_IN_16: - rc = process_read_cap(base, vreq); + rc = process_read_cap_16(base, vreq); break; default: SPDK_ERRLOG("Received invalid target scan message: cdb[0] = %"PRIu8".\n", req->cdb[0]);