All of lore.kernel.org
 help / color / mirror / Atom feed
From: FUJITA Tomonori <tomof@acm.org>
To: James.Bottomley@HansenPartnership.com
Cc: linux-scsi@vger.kernel.org, benh@kernel.crashing.org,
	fujita.tomonori@lab.ntt.co.jp
Subject: [PATCH 2/2] use dynamically allocated sense buffer
Date: Thu, 3 Jan 2008 13:56:37 +0900	[thread overview]
Message-ID: <20080103135907G.tomof@acm.org> (raw)
In-Reply-To: <5dc13e4823ec8c254e5164a51249f05983fa00c2.tomof@acm.org>

This removes static array sense_buffer in scsi_cmnd and uses
dynamically allocated sense_buffer (with GFP_DMA).

scsi_add_host allocates as many buffers as
scsi_host->can_queue. __scsi_get_command attaches sense_buffer to a
scsi_cmnd and __scsi_put_command detaches the sense_buffer from it.

There is a small possibility that a host need more sense buffers than
can_queue. The failure of the buffer allocation works just like the
failure of scsi_cmnd allocation. So everything should work as before.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
 drivers/scsi/hosts.c     |   10 ++++++-
 drivers/scsi/scsi.c      |   67 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/scsi_priv.h |    2 +
 include/scsi/scsi_cmnd.h |    2 +-
 include/scsi/scsi_host.h |    3 ++
 5 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 9a10b43..35c5f0e 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -205,10 +205,14 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
 	if (!shost->shost_gendev.parent)
 		shost->shost_gendev.parent = dev ? dev : &platform_bus;
 
-	error = device_add(&shost->shost_gendev);
+	error = scsi_setup_command_sense_buffer(shost);
 	if (error)
 		goto out;
 
+	error = device_add(&shost->shost_gendev);
+	if (error)
+		goto destroy_pool;
+
 	scsi_host_set_state(shost, SHOST_RUNNING);
 	get_device(shost->shost_gendev.parent);
 
@@ -248,6 +252,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
 	class_device_del(&shost->shost_classdev);
  out_del_gendev:
 	device_del(&shost->shost_gendev);
+ destroy_pool:
+	scsi_destroy_command_sense_buffer(shost);
  out:
 	return error;
 }
@@ -267,6 +273,8 @@ static void scsi_host_dev_release(struct device *dev)
 		scsi_free_queue(shost->uspace_req_q);
 	}
 
+	scsi_destroy_command_sense_buffer(shost);
+
 	scsi_destroy_command_freelist(shost);
 	if (shost->bqt)
 		blk_free_tags(shost->bqt);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ebc0193..91306a5 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -161,6 +161,9 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
 
 static DEFINE_MUTEX(host_cmd_pool_mutex);
 
+static struct kmem_cache *sense_buffer_slab;
+static int sense_buffer_slab_users;
+
 /**
  * __scsi_get_command - Allocate a struct scsi_cmnd
  * @shost: host to transmit command
@@ -172,6 +175,11 @@ static DEFINE_MUTEX(host_cmd_pool_mutex);
 struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 {
 	struct scsi_cmnd *cmd;
+	unsigned char *buf;
+
+	buf = mempool_alloc(shost->sense_buffer_pool, __GFP_DMA|gfp_mask);
+	if (!buf)
+		return NULL;
 
 	cmd = kmem_cache_alloc(shost->cmd_pool->slab,
 			gfp_mask | shost->cmd_pool->gfp_mask);
@@ -188,6 +196,14 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 		spin_unlock_irqrestore(&shost->free_list_lock, flags);
 	}
 
+	if (cmd) {
+		memset(cmd, 0, sizeof(*cmd));
+		cmd->sense_buffer = buf;
+		/* probably unnecessary */
+		memset(buf, 0, SCSI_SENSE_BUFFERSIZE);
+	} else
+		mempool_free(buf, shost->sense_buffer_pool);
+
 	return cmd;
 }
 EXPORT_SYMBOL_GPL(__scsi_get_command);
@@ -212,7 +228,6 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
 	if (likely(cmd != NULL)) {
 		unsigned long flags;
 
-		memset(cmd, 0, sizeof(*cmd));
 		cmd->device = dev;
 		init_timer(&cmd->eh_timeout);
 		INIT_LIST_HEAD(&cmd->list);
@@ -238,6 +253,8 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
 {
 	unsigned long flags;
 
+	mempool_free(cmd->sense_buffer, shost->sense_buffer_pool);
+
 	/* changing locks here, don't need to restore the irq state */
 	spin_lock_irqsave(&shost->free_list_lock, flags);
 	if (unlikely(list_empty(&shost->free_list))) {
@@ -352,6 +369,54 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
 	mutex_unlock(&host_cmd_pool_mutex);
 }
 
+int scsi_setup_command_sense_buffer(struct Scsi_Host *shost)
+{
+	int ret;
+
+	mutex_lock(&host_cmd_pool_mutex);
+	if (!sense_buffer_slab) {
+		sense_buffer_slab = kmem_cache_create("scsi_sense_buffer",
+						      SCSI_SENSE_BUFFERSIZE,
+						      0, SLAB_CACHE_DMA, NULL);
+		if (!sense_buffer_slab) {
+			mutex_unlock(&host_cmd_pool_mutex);
+			return -ENOMEM;
+		}
+	}
+	sense_buffer_slab_users++;
+	mutex_unlock(&host_cmd_pool_mutex);
+
+	shost->sense_buffer_pool =
+		mempool_create_slab_pool(0, sense_buffer_slab);
+	if (!shost->sense_buffer_pool)
+		goto fail;
+
+	ret = mempool_resize(shost->sense_buffer_pool, shost->can_queue,
+			     __GFP_DMA|GFP_KERNEL);
+	if (ret) {
+		mempool_destroy(shost->sense_buffer_pool);
+		goto fail;
+	}
+
+	return 0;
+fail:
+	mutex_lock(&host_cmd_pool_mutex);
+	if (!--sense_buffer_slab_users)
+			kmem_cache_destroy(sense_buffer_slab);
+	mutex_unlock(&host_cmd_pool_mutex);
+	return -ENOMEM;
+}
+
+void scsi_destroy_command_sense_buffer(struct Scsi_Host *shost)
+{
+	mempool_destroy(shost->sense_buffer_pool);
+
+	mutex_lock(&host_cmd_pool_mutex);
+	if (!--sense_buffer_slab_users)
+		kmem_cache_destroy(sense_buffer_slab);
+	mutex_unlock(&host_cmd_pool_mutex);
+}
+
 #ifdef CONFIG_SCSI_LOGGING
 void scsi_log_send(struct scsi_cmnd *cmd)
 {
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index eff0059..88b20f0 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -27,6 +27,8 @@ extern void scsi_exit_hosts(void);
 extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
+extern int scsi_setup_command_sense_buffer(struct Scsi_Host *shost);
+extern void scsi_destroy_command_sense_buffer(struct Scsi_Host *shost);
 extern void __scsi_done(struct scsi_cmnd *cmd);
 #ifdef CONFIG_SCSI_LOGGING
 void scsi_log_send(struct scsi_cmnd *cmd);
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index a7be605..753da55 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -88,7 +88,7 @@ struct scsi_cmnd {
 				   	   working on */
 
 #define SCSI_SENSE_BUFFERSIZE 	96
-	unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
+	unsigned char *sense_buffer;
 				/* obtained by REQUEST SENSE when
 				 * CHECK CONDITION is received on original
 				 * command (auto-sense) */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 0fd4746..3f4bae3 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/mempool.h>
 
 struct request_queue;
 struct block_device;
@@ -520,6 +521,8 @@ struct Scsi_Host {
 	struct list_head	free_list; /* backup store of cmd structs */
 	struct list_head	starved_list;
 
+	mempool_t *sense_buffer_pool;
+
 	spinlock_t		default_lock;
 	spinlock_t		*host_lock;
 
-- 
1.5.3.4


  parent reply	other threads:[~2008-01-03  4:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-03  4:56 [PATCH 0/2] fix the sense buffer DMA issue FUJITA Tomonori
2008-01-03  4:56 ` [PATCH 1/2] replace sizeof sense_buffer with SCSI_SENSE_BUFFERSIZE FUJITA Tomonori
2008-01-03 15:01   ` Boaz Harrosh
2008-01-03 15:34     ` FUJITA Tomonori
2008-01-03 16:10   ` Salyzyn, Mark
2008-01-04 14:05     ` FUJITA Tomonori
2008-01-03  4:56 ` FUJITA Tomonori [this message]
2008-01-03 14:00   ` [PATCH 2/2] use dynamically allocated sense buffer FUJITA Tomonori
2008-01-07  6:37   ` FUJITA Tomonori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080103135907G.tomof@acm.org \
    --to=tomof@acm.org \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=benh@kernel.crashing.org \
    --cc=fujita.tomonori@lab.ntt.co.jp \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.