bdev_virtio: use READ CAPACITY (10) for initial target scan
Added READ CAPACITY (10) support. This is a work towards supporting both (10) and (16)-bit SCSI commands. If READ CAPACITY (10) returns 0xFFFFFFFF as max lba, a READ CAPACITY (16) is sent. As specified in SBC-3 5.10.2 READ CAPACITY (10): ``` If the number of logical blocks exceeds the maximum value that is able to be specified in the RETURNED LOGICAL BLOCK ADDRESS field, the device server shall set the RETURNED LOGICAL BLOCK ADDRESS field to FFFFFFFFh. The application client should then issue a READ CAPACITY (16) command (see 3.27) to retrieve the READ CAPACITY (16) parameter data. ``` Change-Id: If82bc45e904e91d95b124724e895350098337ae9 Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/377091 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
bcaac30fe3
commit
43be836ae5
@ -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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user