Commit 0720ad35 authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

scsi: allow zero-length read and write



The SCSI spec says that zero transfer length shouldn't be considered an
error.

Change-Id: I98958cc393e0e487e25fdbb0eb7fc8126aff9945
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/374320


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 75a3ee3f
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -1338,15 +1338,6 @@ spdk_bdev_scsi_write(struct spdk_bdev *bdev,
	int rc;
	struct spdk_scsi_task *primary = task->parent;

	if (len == 0) {
		task->data_transferred = 0;
		spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
					  SPDK_SCSI_SENSE_NO_SENSE,
					  SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
					  SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
		return SPDK_SCSI_TASK_COMPLETE;
	}

	blen = spdk_bdev_get_block_size(bdev);
	offset = lba * blen;
	nbytes = ((uint64_t)len) * blen;
@@ -1461,6 +1452,11 @@ spdk_bdev_scsi_readwrite(struct spdk_bdev *bdev,
		return SPDK_SCSI_TASK_COMPLETE;
	}

	if (xfer_len == 0) {
		task->status = SPDK_SCSI_STATUS_GOOD;
		return SPDK_SCSI_TASK_COMPLETE;
	}

	/* Transfer Length is limited to the Block Limits VPD page Maximum Transfer Length */
	max_xfer_len = SPDK_WORK_BLOCK_SIZE / spdk_bdev_get_block_size(bdev);
	if (xfer_len > max_xfer_len) {
+18 −0
Original line number Diff line number Diff line
@@ -672,6 +672,24 @@ xfer_len_test(void)
	CU_ASSERT((task.sense_data[2] & 0xf) == SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
	CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB);

	/* zero transfer length (valid) */
	to_be64(&cdb[2], 0); /* LBA */
	to_be32(&cdb[10], 0); /* transfer length */
	task.transfer_len = 0;
	rc = spdk_bdev_scsi_execute(&bdev, &task);
	CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
	CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
	CU_ASSERT(task.data_transferred == 0);

	/* zero transfer length past end of disk (invalid) */
	to_be64(&cdb[2], g_test_bdev_num_blocks); /* LBA */
	to_be32(&cdb[10], 0); /* transfer length */
	task.transfer_len = 0;
	rc = spdk_bdev_scsi_execute(&bdev, &task);
	CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
	CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
	CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);

	spdk_put_task(&task);
}