From: Boaz Harrosh <bharrosh@panasas.com>
To: James Bottomley <James.Bottomley@SteelEye.com>,
Jens Axboe <jens.axboe@oracle.com>,
FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>,
linux-scsi <linux-scsi@vger.kernel.org>
Subject: Re: [PATCH AB1/5] SCSI: SG pools allocation cleanup.
Date: Tue, 24 Jul 2007 16:08:12 +0300 [thread overview]
Message-ID: <46A5F9BC.3060705@panasas.com> (raw)
In-Reply-To: <46A5BDEB.3040506@panasas.com>
Boaz Harrosh wrote:
> First patch will not apply on scsi-misc-2.6 because there
> is a missing NULL in the call to kmem_cache_create(). (linux-2.6.23-rcx)
> (If any one need a patchset for that please ask)
It will have more problems if Jens's:
ac133644304cd1721dfb77193e0502f8afd4ea9b - scsi: simplify scsi_free_sgtable()
is not applied. any way here is an: over scsi-misc one.
Also A2/5 will have issues.
>From 20f05cf739fc414033b4ca11e9f52e9f6d8db95b Mon Sep 17 00:00:00 2001
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Mon, 23 Jul 2007 18:51:59 +0300
Subject: [PATCH] SCSI: SG pools allocation cleanup.
- The code Automatically calculates at compile time the
maximum size sg-array that will fit in a memory-page and will allocate
pools of BASE_2 size, up to that maximum size.
- split scsi_alloc() into an helper scsi_sgtable_index() that will return
the index of the pool for a given sg_count.
- Remove now unused SCSI_MAX_PHYS_SEGMENTS
- rename sglist_len to sg_pool which is what it always was.
- Some extra prints at scsi_init_queue(). These prints will be removed
once everything stabilizes.
Now that the Arrays are automatically calculated to fit in a page, what
about ARCH's that have a very big page size? I have, just for demonstration,
calculated upto 512 entries. But I suspect that other kernel-subsystems are
bounded to 256 or 128, is that true? should I allow more/less than 512 here?
some common numbers:
Arch | SCSI_MAX_SG_SEGMENTS = | sizeof(struct scatterlist)
--------------------------|-------------------------|---------------------------
x86_64 | 128 |32
i386 CONFIG_HIGHMEM64G=y | 205 |20
i386 other | 256 |16
Could some one give example numbers of an ARCH with big page size?
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
drivers/scsi/scsi_lib.c | 140 +++++++++++++++++++++-------------------------
include/scsi/scsi.h | 7 --
include/scsi/scsi_cmnd.h | 19 +++++-
3 files changed, 79 insertions(+), 87 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 1f5a07b..c065de5 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -29,40 +29,31 @@
#include "scsi_priv.h"
#include "scsi_logging.h"
-
-#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools)
#define SG_MEMPOOL_SIZE 2
+/*
+ * Should fit within a single page.
+ */
+enum { SCSI_MAX_SG_SEGMENTS = (PAGE_SIZE / sizeof(struct scatterlist)) };
+
+enum { SG_MEMPOOL_NR =
+ (SCSI_MAX_SG_SEGMENTS >= 8) +
+ (SCSI_MAX_SG_SEGMENTS >= 16) +
+ (SCSI_MAX_SG_SEGMENTS >= 32) +
+ (SCSI_MAX_SG_SEGMENTS >= 64) +
+ (SCSI_MAX_SG_SEGMENTS >= 128) +
+ (SCSI_MAX_SG_SEGMENTS >= 256) +
+ (SCSI_MAX_SG_SEGMENTS >= 512)
+};
+
struct scsi_host_sg_pool {
- size_t size;
- char *name;
+ unsigned size;
struct kmem_cache *slab;
mempool_t *pool;
};
+static struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR];
+
-#if (SCSI_MAX_PHYS_SEGMENTS < 32)
-#error SCSI_MAX_PHYS_SEGMENTS is too small
-#endif
-
-#define SP(x) { x, "sgpool-" #x }
-static struct scsi_host_sg_pool scsi_sg_pools[] = {
- SP(8),
- SP(16),
- SP(32),
-#if (SCSI_MAX_PHYS_SEGMENTS > 32)
- SP(64),
-#if (SCSI_MAX_PHYS_SEGMENTS > 64)
- SP(128),
-#if (SCSI_MAX_PHYS_SEGMENTS > 128)
- SP(256),
-#if (SCSI_MAX_PHYS_SEGMENTS > 256)
-#error SCSI_MAX_PHYS_SEGMENTS is too large
-#endif
-#endif
-#endif
-#endif
-};
-#undef SP
static void scsi_run_queue(struct request_queue *q);
@@ -701,44 +692,32 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
return NULL;
}
+static unsigned scsi_sgtable_index(unsigned nents)
+{
+ int i, size;
+
+ for (i = 0, size = 8; i < SG_MEMPOOL_NR-1; i++, size <<= 1)
+ if (size >= nents)
+ return i;
+
+ if (SCSI_MAX_SG_SEGMENTS >= nents)
+ return SG_MEMPOOL_NR-1;
+
+ printk(KERN_ERR "scsi: bad segment count=%d\n", nents);
+ BUG();
+ return -1;
+}
+
struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
{
- struct scsi_host_sg_pool *sgp;
+ unsigned int pool = scsi_sgtable_index(cmd->use_sg);
struct scatterlist *sgl;
- BUG_ON(!cmd->use_sg);
-
- switch (cmd->use_sg) {
- case 1 ... 8:
- cmd->sglist_len = 0;
- break;
- case 9 ... 16:
- cmd->sglist_len = 1;
- break;
- case 17 ... 32:
- cmd->sglist_len = 2;
- break;
-#if (SCSI_MAX_PHYS_SEGMENTS > 32)
- case 33 ... 64:
- cmd->sglist_len = 3;
- break;
-#if (SCSI_MAX_PHYS_SEGMENTS > 64)
- case 65 ... 128:
- cmd->sglist_len = 4;
- break;
-#if (SCSI_MAX_PHYS_SEGMENTS > 128)
- case 129 ... 256:
- cmd->sglist_len = 5;
- break;
-#endif
-#endif
-#endif
- default:
+ sgl = mempool_alloc(scsi_sg_pools[pool].pool, gfp_mask);
+ if (unlikely(!sgl))
return NULL;
- }
- sgp = scsi_sg_pools + cmd->sglist_len;
- sgl = mempool_alloc(sgp->pool, gfp_mask);
+ cmd->sg_pool = pool;
return sgl;
}
@@ -746,12 +725,8 @@ EXPORT_SYMBOL(scsi_alloc_sgtable);
void scsi_free_sgtable(struct scatterlist *sgl, int index)
{
- struct scsi_host_sg_pool *sgp;
-
BUG_ON(index >= SG_MEMPOOL_NR);
-
- sgp = scsi_sg_pools + index;
- mempool_free(sgl, sgp->pool);
+ mempool_free(sgl, scsi_sg_pools[index].pool);
}
EXPORT_SYMBOL(scsi_free_sgtable);
@@ -784,6 +759,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
*/
cmd->request_buffer = NULL;
cmd->request_bufflen = 0;
+ cmd->use_sg = 0;
}
/*
@@ -991,7 +967,6 @@ EXPORT_SYMBOL(scsi_io_completion);
static int scsi_init_io(struct scsi_cmnd *cmd)
{
struct request *req = cmd->request;
- struct scatterlist *sgpnt;
int count;
/*
@@ -1004,14 +979,13 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
/*
* If sg table allocation fails, requeue request later.
*/
- sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
- if (unlikely(!sgpnt)) {
+ cmd->request_buffer = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
+ if (unlikely(!cmd->request_buffer)) {
scsi_unprep_request(req);
return BLKPREP_DEFER;
}
req->buffer = NULL;
- cmd->request_buffer = (char *) sgpnt;
if (blk_pc_request(req))
cmd->request_bufflen = req->data_len;
else
@@ -1576,7 +1550,7 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
return NULL;
blk_queue_max_hw_segments(q, shost->sg_tablesize);
- blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS);
+ blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS);
blk_queue_max_sectors(q, shost->max_sectors);
blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary);
@@ -1655,9 +1629,15 @@ void scsi_unblock_requests(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(scsi_unblock_requests);
+const char* sg_names[] = {
+ "sgpool-8", "sgpool-16", "sgpool-32", "sgpool-64",
+ "sgpool-128", "sgpool-256", "sgpool-512"
+};
+
int __init scsi_init_queue(void)
{
int i;
+ unsigned size;
scsi_io_context_cache = kmem_cache_create("scsi_io_context",
sizeof(struct scsi_io_context),
@@ -1667,25 +1647,33 @@ int __init scsi_init_queue(void)
return -ENOMEM;
}
- for (i = 0; i < SG_MEMPOOL_NR; i++) {
+ for (i = 0, size = 8; i < SG_MEMPOOL_NR; i++, size <<= 1) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
- int size = sgp->size * sizeof(struct scatterlist);
-
- sgp->slab = kmem_cache_create(sgp->name, size, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ sgp->size = size;
+ sgp->slab = kmem_cache_create(sg_names[i],
+ sgp->size*sizeof(struct scatterlist),
+ 0, 0, NULL, NULL);
if (!sgp->slab) {
printk(KERN_ERR "SCSI: can't init sg slab %s\n",
- sgp->name);
+ sg_names[i]);
}
sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE,
sgp->slab);
if (!sgp->pool) {
printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
- sgp->name);
+ sg_names[i]);
}
}
+ /* FIXME: Here for the debugging phase only */
+ printk(KERN_ERR
+ "SCSI: max_sg_count=%d SG_MEMPOOL_NR=%d page=%ld "
+ "so_scaterlist=%Zd\n",
+ SCSI_MAX_SG_SEGMENTS, SG_MEMPOOL_NR, PAGE_SIZE,
+ sizeof(struct scatterlist)
+ );
+
return 0;
}
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 9f8f80a..702fcfe 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -11,13 +11,6 @@
#include <linux/types.h>
/*
- * The maximum sg list length SCSI can cope with
- * (currently must be a power of 2 between 32 and 256)
- */
-#define SCSI_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
-
-
-/*
* SCSI command lengths
*/
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 53e1705..9214ad6 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -71,7 +71,7 @@ struct scsi_cmnd {
/* These elements define the operation we ultimately want to perform */
unsigned short use_sg; /* Number of pieces of scatter-gather */
- unsigned short sglist_len; /* size of malloc'd scatter-gather list */
+ unsigned short sg_pool; /* pool index of allocated sg array */
unsigned underflow; /* Return error if less than
this amount is transferred */
@@ -138,9 +138,20 @@ extern void scsi_free_sgtable(struct scatterlist *, int);
extern int scsi_dma_map(struct scsi_cmnd *cmd);
extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
-#define scsi_sg_count(cmd) ((cmd)->use_sg)
-#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
-#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
+{
+ return cmd->->use_sg;
+}
+
+static inline struct scatterlist *scsi_sglist(struct scsi_cmnd *cmd)
+{
+ return ((struct scatterlist *)cmd->request_buffer)
+}
+
+static inline unsigned scsi_bufflen(struct scsi_cmnd *cmd)
+{
+ return cmd->request_bufflen;
+}
static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
{
--
1.5.2.2.249.g45fd
next prev parent reply other threads:[~2007-07-24 13:08 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-24 8:47 [PATCHSET 0/5] Peaceful co-existence of scsi_sgtable and Large IO sg-chaining Boaz Harrosh
2007-07-24 8:52 ` [PATCH AB1/5] SCSI: SG pools allocation cleanup Boaz Harrosh
2007-07-24 13:08 ` Boaz Harrosh [this message]
2007-07-25 8:08 ` Boaz Harrosh
2007-07-25 9:05 ` [PATCH AB1/5 ver2] " Boaz Harrosh
2007-07-25 9:06 ` [PATCH A2/5 ver2] SCSI: scsi_sgtable implementation Boaz Harrosh
2007-07-24 8:56 ` [PATCH A2/5] " Boaz Harrosh
2007-07-24 8:59 ` [PATCH A3/5] SCSI: sg-chaining over scsi_sgtable Boaz Harrosh
2007-07-24 9:01 ` [PATCH B2/5] SCSI: support for allocating large scatterlists Boaz Harrosh
2007-07-24 9:03 ` [PATCH B3/5] SCSI: scsi_sgtable over sg-chainning Boaz Harrosh
2007-07-24 9:16 ` [PATCHSET 0/5] Peaceful co-existence of scsi_sgtable and Large IO sg-chaining FUJITA Tomonori
2007-07-24 10:01 ` Boaz Harrosh
2007-07-24 11:12 ` FUJITA Tomonori
2007-07-24 13:41 ` FUJITA Tomonori
2007-07-24 14:01 ` Benny Halevy
2007-07-24 16:10 ` James Bottomley
2007-07-25 8:26 ` Benny Halevy
2007-07-25 8:42 ` FUJITA Tomonori
2007-07-25 19:22 ` Boaz Harrosh
2007-07-26 11:33 ` FUJITA Tomonori
2007-07-31 20:12 ` Boaz Harrosh
2007-08-05 16:03 ` FUJITA Tomonori
2007-08-06 7:22 ` FUJITA Tomonori
2007-08-07 6:55 ` Jens Axboe
2007-08-07 8:36 ` FUJITA Tomonori
2007-08-08 7:16 ` Jens Axboe
2007-07-25 19:50 ` Boaz Harrosh
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=46A5F9BC.3060705@panasas.com \
--to=bharrosh@panasas.com \
--cc=James.Bottomley@SteelEye.com \
--cc=fujita.tomonori@lab.ntt.co.jp \
--cc=jens.axboe@oracle.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).