Commit 43be836a authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Daniel Verkamp
Browse files

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: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/377091


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent bcaac30f
Loading
Loading
Loading
Loading
+67 −15
Original line number Diff line number Diff line
@@ -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;
	struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base;
	uint8_t lun_id;

	if (resp->response != VIRTIO_SCSI_S_OK || resp->status != SPDK_SCSI_STATUS_GOOD) {
		return -1;
	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);
}

	lun_id = req->lun[1];
	/* reuse vreq for next request */
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] = lun_id;
	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;

	iov[0].iov_len = 32;
	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 target_id;

	if (resp->response != VIRTIO_SCSI_S_OK || resp->status != SPDK_SCSI_STATUS_GOOD) {
		return -1;
	}

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