From 0720ad357b338b32a01fcd8a438ba9423134519f Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Tue, 15 Aug 2017 08:56:20 -0700 Subject: [PATCH] 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: Daniel Verkamp Reviewed-on: https://review.gerrithub.io/374320 Tested-by: SPDK Automated Test System Reviewed-by: Ben Walker --- lib/scsi/scsi_bdev.c | 14 +++++--------- test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/scsi/scsi_bdev.c b/lib/scsi/scsi_bdev.c index 2a3b80618..9a70f3257 100644 --- a/lib/scsi/scsi_bdev.c +++ b/lib/scsi/scsi_bdev.c @@ -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) { diff --git a/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c b/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c index 08de75af5..02c06bcdc 100644 --- a/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c +++ b/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c @@ -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); }