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

View File

@ -1635,7 +1635,12 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
switch (cdb[0]) { switch (cdb[0]) {
case SPDK_SPC_INQUIRY: case SPDK_SPC_INQUIRY:
alloc_len = from_be16(&cdb[3]); 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_len = spdk_bdev_scsi_inquiry(bdev, task, cdb,
data, alloc_len); data, alloc_len);
if (data_len < 0) { if (data_len < 0) {

View File

@ -120,15 +120,6 @@ spdk_scsi_task_free_data(struct spdk_scsi_task *task)
void * void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len) 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); assert(task->alloc_len == 0);
/* Only one buffer is managable */ /* 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; return NULL;
} }
if (alloc_len < 4096) {
alloc_len = 4096;
}
/* This is workaround for buffers shorter than 4kb */ /* This is workaround for buffers shorter than 4kb */
if (task->iov.iov_base == NULL) { if (task->iov.iov_base == NULL) {
task->iov.iov_base = spdk_zmalloc(alloc_len, 0, 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 * void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len) 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->iov.iov_base != NULL) {
if (task->alloc_len != 0 && alloc_len > task->alloc_len) { if (task->alloc_len != 0 && alloc_len > task->alloc_len) {
spdk_put_task(task); spdk_put_task(task);
@ -458,7 +454,6 @@ inquiry_standard_test(void)
struct spdk_scsi_lun lun; struct spdk_scsi_lun lun;
struct spdk_scsi_dev dev; struct spdk_scsi_dev dev;
char cdb[6]; char cdb[6];
/* expects a 4K internal data buffer */
char *data; char *data;
struct spdk_scsi_cdb_inquiry_data *inq_data; struct spdk_scsi_cdb_inquiry_data *inq_data;
int rc; int rc;