lib/scsi: allocate only requested amount of data

Remove 4k allocation size in spdk_scsi_task_alloc_data(). From now on
all commands must obay allocation length.

Change-Id: Ica9384c62d431483ae1d0bd2e6fdee18b570861f
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
This commit is contained in:
Pawel Wodkowski 2016-10-24 17:23:35 +02:00 committed by Jim Harris
parent 4fdc493c8e
commit 8b449060eb
4 changed files with 24 additions and 28 deletions

View File

@ -183,9 +183,10 @@ spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
static void
complete_task_with_no_lun(struct spdk_scsi_task *task)
{
uint8_t buffer[36];
uint8_t *data;
uint32_t allocation_len;
int data_len;
uint32_t data_len;
if (task->cdb[0] == SPDK_SPC_INQUIRY) {
/*
@ -194,14 +195,22 @@ complete_task_with_no_lun(struct spdk_scsi_task *task)
* PERIPHERAL DEVICE TYPE = 0x1F.
*/
allocation_len = from_be16(&task->cdb[3]);
data = spdk_scsi_task_alloc_data(task, allocation_len);
data_len = 36;
memset(data, 0, data_len);
/* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
data[0] = 0x03 << 5 | 0x1f;
/* ADDITIONAL LENGTH */
data[4] = data_len - 5;
task->data_transferred = (uint64_t)data_len;
data_len = sizeof(buffer);
if (allocation_len > data_len)
allocation_len = data_len;
if (allocation_len) {
memset(buffer, 0, data_len);
/* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
buffer[0] = 0x03 << 5 | 0x1f;
/* ADDITIONAL LENGTH */
buffer[4] = data_len - 5;
data = spdk_scsi_task_alloc_data(task, allocation_len);
memcpy(data, buffer, allocation_len);
}
task->data_transferred = data_len;
task->status = SPDK_SCSI_STATUS_GOOD;
} else {
/* LOGICAL UNIT NOT SUPPORTED */

View File

@ -1635,7 +1635,12 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
switch (cdb[0]) {
case SPDK_SPC_INQUIRY:
alloc_len = from_be16(&cdb[3]);
data = spdk_scsi_task_alloc_data(task, alloc_len);
if (alloc_len) {
data = spdk_scsi_task_alloc_data(task, alloc_len);
} else {
data = NULL;
}
data_len = spdk_bdev_scsi_inquiry(bdev, task, cdb,
data, alloc_len);
if (data_len < 0) {

View File

@ -120,15 +120,6 @@ spdk_scsi_task_free_data(struct spdk_scsi_task *task)
void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
{
/*
* SPDK iSCSI target depends on allocating at least 4096 bytes, even if
* the command requested less. The individual command code (for
* example, INQUIRY) will fill out up to 4096 bytes of data, ignoring
* the allocation length specified in the command. After the individual
* command functions are done, spdk_scsi_lun_execute_tasks() takes
* care of only sending back the amount of data specified in the
* allocation length.
*/
assert(task->alloc_len == 0);
/* Only one buffer is managable */
@ -136,10 +127,6 @@ spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
return NULL;
}
if (alloc_len < 4096) {
alloc_len = 4096;
}
/* This is workaround for buffers shorter than 4kb */
if (task->iov.iov_base == NULL) {
task->iov.iov_base = spdk_zmalloc(alloc_len, 0, NULL);

View File

@ -104,10 +104,6 @@ spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
{
if (alloc_len < 4096) {
alloc_len = 4096;
}
if (task->iov.iov_base != NULL) {
if (task->alloc_len != 0 && alloc_len > task->alloc_len) {
spdk_put_task(task);
@ -458,7 +454,6 @@ inquiry_standard_test(void)
struct spdk_scsi_lun lun;
struct spdk_scsi_dev dev;
char cdb[6];
/* expects a 4K internal data buffer */
char *data;
struct spdk_scsi_cdb_inquiry_data *inq_data;
int rc;