storvsc: use cmd_size to allocate per-command data
STORVSC uses its own momory pool to manage device request data. However, the SCSI layer already has a mechanisim for allocating additional memory for each command issued to device driver. This patch removes the memory pool in STORVSC and makes it use SCSI layer to allocate memory for device request data. Reviewed-by: Long Li <longli@microsoft.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Родитель
d454c91f74
Коммит
ead3700d89
|
@ -32,7 +32,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/hyperv.h>
|
#include <linux/hyperv.h>
|
||||||
#include <linux/mempool.h>
|
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/scsi_cmnd.h>
|
#include <scsi/scsi_cmnd.h>
|
||||||
|
@ -309,14 +308,6 @@ enum storvsc_request_type {
|
||||||
* This is the end of Protocol specific defines.
|
* This is the end of Protocol specific defines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We setup a mempool to allocate request structures for this driver
|
|
||||||
* on a per-lun basis. The following define specifies the number of
|
|
||||||
* elements in the pool.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define STORVSC_MIN_BUF_NR 64
|
|
||||||
static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
|
static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
|
||||||
|
|
||||||
module_param(storvsc_ringbuffer_size, int, S_IRUGO);
|
module_param(storvsc_ringbuffer_size, int, S_IRUGO);
|
||||||
|
@ -346,7 +337,6 @@ static void storvsc_on_channel_callback(void *context);
|
||||||
#define STORVSC_IDE_MAX_CHANNELS 1
|
#define STORVSC_IDE_MAX_CHANNELS 1
|
||||||
|
|
||||||
struct storvsc_cmd_request {
|
struct storvsc_cmd_request {
|
||||||
struct list_head entry;
|
|
||||||
struct scsi_cmnd *cmd;
|
struct scsi_cmnd *cmd;
|
||||||
|
|
||||||
unsigned int bounce_sgl_count;
|
unsigned int bounce_sgl_count;
|
||||||
|
@ -357,7 +347,6 @@ struct storvsc_cmd_request {
|
||||||
/* Synchronize the request/response if needed */
|
/* Synchronize the request/response if needed */
|
||||||
struct completion wait_event;
|
struct completion wait_event;
|
||||||
|
|
||||||
unsigned char *sense_buffer;
|
|
||||||
struct hv_multipage_buffer data_buffer;
|
struct hv_multipage_buffer data_buffer;
|
||||||
struct vstor_packet vstor_packet;
|
struct vstor_packet vstor_packet;
|
||||||
};
|
};
|
||||||
|
@ -389,11 +378,6 @@ struct storvsc_device {
|
||||||
struct storvsc_cmd_request reset_request;
|
struct storvsc_cmd_request reset_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stor_mem_pools {
|
|
||||||
struct kmem_cache *request_pool;
|
|
||||||
mempool_t *request_mempool;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hv_host_device {
|
struct hv_host_device {
|
||||||
struct hv_device *dev;
|
struct hv_device *dev;
|
||||||
unsigned int port;
|
unsigned int port;
|
||||||
|
@ -1070,10 +1054,8 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
|
||||||
{
|
{
|
||||||
struct scsi_cmnd *scmnd = cmd_request->cmd;
|
struct scsi_cmnd *scmnd = cmd_request->cmd;
|
||||||
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||||
void (*scsi_done_fn)(struct scsi_cmnd *);
|
|
||||||
struct scsi_sense_hdr sense_hdr;
|
struct scsi_sense_hdr sense_hdr;
|
||||||
struct vmscsi_request *vm_srb;
|
struct vmscsi_request *vm_srb;
|
||||||
struct stor_mem_pools *memp = scmnd->device->hostdata;
|
|
||||||
struct Scsi_Host *host;
|
struct Scsi_Host *host;
|
||||||
struct storvsc_device *stor_dev;
|
struct storvsc_device *stor_dev;
|
||||||
struct hv_device *dev = host_dev->dev;
|
struct hv_device *dev = host_dev->dev;
|
||||||
|
@ -1109,14 +1091,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
|
||||||
cmd_request->data_buffer.len -
|
cmd_request->data_buffer.len -
|
||||||
vm_srb->data_transfer_length);
|
vm_srb->data_transfer_length);
|
||||||
|
|
||||||
scsi_done_fn = scmnd->scsi_done;
|
scmnd->scsi_done(scmnd);
|
||||||
|
|
||||||
scmnd->host_scribble = NULL;
|
|
||||||
scmnd->scsi_done = NULL;
|
|
||||||
|
|
||||||
scsi_done_fn(scmnd);
|
|
||||||
|
|
||||||
mempool_free(cmd_request, memp->request_mempool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void storvsc_on_io_completion(struct hv_device *device,
|
static void storvsc_on_io_completion(struct hv_device *device,
|
||||||
|
@ -1160,7 +1135,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||||
SRB_STATUS_AUTOSENSE_VALID) {
|
SRB_STATUS_AUTOSENSE_VALID) {
|
||||||
/* autosense data available */
|
/* autosense data available */
|
||||||
|
|
||||||
memcpy(request->sense_buffer,
|
memcpy(request->cmd->sense_buffer,
|
||||||
vstor_packet->vm_srb.sense_data,
|
vstor_packet->vm_srb.sense_data,
|
||||||
vstor_packet->vm_srb.sense_info_length);
|
vstor_packet->vm_srb.sense_info_length);
|
||||||
|
|
||||||
|
@ -1378,55 +1353,6 @@ static int storvsc_do_io(struct hv_device *device,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int storvsc_device_alloc(struct scsi_device *sdevice)
|
|
||||||
{
|
|
||||||
struct stor_mem_pools *memp;
|
|
||||||
int number = STORVSC_MIN_BUF_NR;
|
|
||||||
|
|
||||||
memp = kzalloc(sizeof(struct stor_mem_pools), GFP_KERNEL);
|
|
||||||
if (!memp)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
memp->request_pool =
|
|
||||||
kmem_cache_create(dev_name(&sdevice->sdev_dev),
|
|
||||||
sizeof(struct storvsc_cmd_request), 0,
|
|
||||||
SLAB_HWCACHE_ALIGN, NULL);
|
|
||||||
|
|
||||||
if (!memp->request_pool)
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
memp->request_mempool = mempool_create(number, mempool_alloc_slab,
|
|
||||||
mempool_free_slab,
|
|
||||||
memp->request_pool);
|
|
||||||
|
|
||||||
if (!memp->request_mempool)
|
|
||||||
goto err1;
|
|
||||||
|
|
||||||
sdevice->hostdata = memp;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err1:
|
|
||||||
kmem_cache_destroy(memp->request_pool);
|
|
||||||
|
|
||||||
err0:
|
|
||||||
kfree(memp);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void storvsc_device_destroy(struct scsi_device *sdevice)
|
|
||||||
{
|
|
||||||
struct stor_mem_pools *memp = sdevice->hostdata;
|
|
||||||
|
|
||||||
if (!memp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mempool_destroy(memp->request_mempool);
|
|
||||||
kmem_cache_destroy(memp->request_pool);
|
|
||||||
kfree(memp);
|
|
||||||
sdevice->hostdata = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int storvsc_device_configure(struct scsi_device *sdevice)
|
static int storvsc_device_configure(struct scsi_device *sdevice)
|
||||||
{
|
{
|
||||||
scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
|
scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
|
||||||
|
@ -1561,13 +1487,11 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||||
int ret;
|
int ret;
|
||||||
struct hv_host_device *host_dev = shost_priv(host);
|
struct hv_host_device *host_dev = shost_priv(host);
|
||||||
struct hv_device *dev = host_dev->dev;
|
struct hv_device *dev = host_dev->dev;
|
||||||
struct storvsc_cmd_request *cmd_request;
|
struct storvsc_cmd_request *cmd_request = scsi_cmd_priv(scmnd);
|
||||||
unsigned int request_size = 0;
|
|
||||||
int i;
|
int i;
|
||||||
struct scatterlist *sgl;
|
struct scatterlist *sgl;
|
||||||
unsigned int sg_count = 0;
|
unsigned int sg_count = 0;
|
||||||
struct vmscsi_request *vm_srb;
|
struct vmscsi_request *vm_srb;
|
||||||
struct stor_mem_pools *memp = scmnd->device->hostdata;
|
|
||||||
|
|
||||||
if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
|
if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
|
||||||
/*
|
/*
|
||||||
|
@ -1584,25 +1508,9 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request_size = sizeof(struct storvsc_cmd_request);
|
|
||||||
|
|
||||||
cmd_request = mempool_alloc(memp->request_mempool,
|
|
||||||
GFP_ATOMIC);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We might be invoked in an interrupt context; hence
|
|
||||||
* mempool_alloc() can fail.
|
|
||||||
*/
|
|
||||||
if (!cmd_request)
|
|
||||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
|
||||||
|
|
||||||
memset(cmd_request, 0, sizeof(struct storvsc_cmd_request));
|
|
||||||
|
|
||||||
/* Setup the cmd request */
|
/* Setup the cmd request */
|
||||||
cmd_request->cmd = scmnd;
|
cmd_request->cmd = scmnd;
|
||||||
|
|
||||||
scmnd->host_scribble = (unsigned char *)cmd_request;
|
|
||||||
|
|
||||||
vm_srb = &cmd_request->vstor_packet.vm_srb;
|
vm_srb = &cmd_request->vstor_packet.vm_srb;
|
||||||
vm_srb->win8_extension.time_out_value = 60;
|
vm_srb->win8_extension.time_out_value = 60;
|
||||||
|
|
||||||
|
@ -1637,9 +1545,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||||
|
|
||||||
memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
|
memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
|
||||||
|
|
||||||
cmd_request->sense_buffer = scmnd->sense_buffer;
|
|
||||||
|
|
||||||
|
|
||||||
cmd_request->data_buffer.len = scsi_bufflen(scmnd);
|
cmd_request->data_buffer.len = scsi_bufflen(scmnd);
|
||||||
if (scsi_sg_count(scmnd)) {
|
if (scsi_sg_count(scmnd)) {
|
||||||
sgl = (struct scatterlist *)scsi_sglist(scmnd);
|
sgl = (struct scatterlist *)scsi_sglist(scmnd);
|
||||||
|
@ -1651,10 +1556,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||||
create_bounce_buffer(sgl, scsi_sg_count(scmnd),
|
create_bounce_buffer(sgl, scsi_sg_count(scmnd),
|
||||||
scsi_bufflen(scmnd),
|
scsi_bufflen(scmnd),
|
||||||
vm_srb->data_in);
|
vm_srb->data_in);
|
||||||
if (!cmd_request->bounce_sgl) {
|
if (!cmd_request->bounce_sgl)
|
||||||
ret = SCSI_MLQUEUE_HOST_BUSY;
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
goto queue_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_request->bounce_sgl_count =
|
cmd_request->bounce_sgl_count =
|
||||||
ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
|
ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
|
||||||
|
@ -1692,27 +1595,21 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||||
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||||
cmd_request->bounce_sgl_count);
|
cmd_request->bounce_sgl_count);
|
||||||
|
|
||||||
ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||||
goto queue_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
queue_error:
|
|
||||||
mempool_free(cmd_request, memp->request_mempool);
|
|
||||||
scmnd->host_scribble = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct scsi_host_template scsi_driver = {
|
static struct scsi_host_template scsi_driver = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.name = "storvsc_host_t",
|
.name = "storvsc_host_t",
|
||||||
|
.cmd_size = sizeof(struct storvsc_cmd_request),
|
||||||
.bios_param = storvsc_get_chs,
|
.bios_param = storvsc_get_chs,
|
||||||
.queuecommand = storvsc_queuecommand,
|
.queuecommand = storvsc_queuecommand,
|
||||||
.eh_host_reset_handler = storvsc_host_reset_handler,
|
.eh_host_reset_handler = storvsc_host_reset_handler,
|
||||||
|
.proc_name = "storvsc_host",
|
||||||
.eh_timed_out = storvsc_eh_timed_out,
|
.eh_timed_out = storvsc_eh_timed_out,
|
||||||
.slave_alloc = storvsc_device_alloc,
|
|
||||||
.slave_destroy = storvsc_device_destroy,
|
|
||||||
.slave_configure = storvsc_device_configure,
|
.slave_configure = storvsc_device_configure,
|
||||||
.cmd_per_lun = 255,
|
.cmd_per_lun = 255,
|
||||||
.can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
|
.can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче