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:
Dariusz Stojaczyk 2017-09-04 19:23:46 +02:00 committed by Daniel Verkamp
parent bcaac30fe3
commit 43be836ae5

View File

@ -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]);