Skip to content

Commit 9b1d6c8

Browse files
Ming Linmartinkpetersen
authored andcommitted
lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c
Now it's ready to move the mempool based SG chained allocator code from SCSI driver to lib/sg_pool.c, which will be compiled only based on a Kconfig symbol CONFIG_SG_POOL. SCSI selects CONFIG_SG_POOL. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ming Lin <ming.l@ssi.samsung.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 65e8617 commit 9b1d6c8

File tree

7 files changed

+206
-156
lines changed

7 files changed

+206
-156
lines changed

drivers/scsi/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ config SCSI
1717
tristate "SCSI device support"
1818
depends on BLOCK
1919
select SCSI_DMA if HAS_DMA
20+
select SG_POOL
2021
---help---
2122
If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
2223
any other SCSI device under Linux, say Y and make sure that you know

drivers/scsi/scsi_lib.c

Lines changed: 0 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#include <linux/completion.h>
1515
#include <linux/kernel.h>
1616
#include <linux/export.h>
17-
#include <linux/mempool.h>
18-
#include <linux/slab.h>
1917
#include <linux/init.h>
2018
#include <linux/pci.h>
2119
#include <linux/delay.h>
@@ -40,39 +38,6 @@
4038
#include "scsi_logging.h"
4139

4240

43-
#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools)
44-
#define SG_MEMPOOL_SIZE 2
45-
46-
struct sg_pool {
47-
size_t size;
48-
char *name;
49-
struct kmem_cache *slab;
50-
mempool_t *pool;
51-
};
52-
53-
#define SP(x) { .size = x, "sgpool-" __stringify(x) }
54-
#if (SG_CHUNK_SIZE < 32)
55-
#error SG_CHUNK_SIZE is too small (must be 32 or greater)
56-
#endif
57-
static struct sg_pool sg_pools[] = {
58-
SP(8),
59-
SP(16),
60-
#if (SG_CHUNK_SIZE > 32)
61-
SP(32),
62-
#if (SG_CHUNK_SIZE > 64)
63-
SP(64),
64-
#if (SG_CHUNK_SIZE > 128)
65-
SP(128),
66-
#if (SG_CHUNK_SIZE > 256)
67-
#error SG_CHUNK_SIZE is too large (256 MAX)
68-
#endif
69-
#endif
70-
#endif
71-
#endif
72-
SP(SG_CHUNK_SIZE)
73-
};
74-
#undef SP
75-
7641
struct kmem_cache *scsi_sdb_cache;
7742

7843
/*
@@ -553,65 +518,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
553518
scsi_run_queue(sdev->request_queue);
554519
}
555520

556-
static inline unsigned int sg_pool_index(unsigned short nents)
557-
{
558-
unsigned int index;
559-
560-
BUG_ON(nents > SG_CHUNK_SIZE);
561-
562-
if (nents <= 8)
563-
index = 0;
564-
else
565-
index = get_count_order(nents) - 3;
566-
567-
return index;
568-
}
569-
570-
static void sg_pool_free(struct scatterlist *sgl, unsigned int nents)
571-
{
572-
struct sg_pool *sgp;
573-
574-
sgp = sg_pools + sg_pool_index(nents);
575-
mempool_free(sgl, sgp->pool);
576-
}
577-
578-
static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask)
579-
{
580-
struct sg_pool *sgp;
581-
582-
sgp = sg_pools + sg_pool_index(nents);
583-
return mempool_alloc(sgp->pool, gfp_mask);
584-
}
585-
586-
static void sg_free_table_chained(struct sg_table *table, bool first_chunk)
587-
{
588-
if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE)
589-
return;
590-
__sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free);
591-
}
592-
593-
static int sg_alloc_table_chained(struct sg_table *table, int nents,
594-
struct scatterlist *first_chunk)
595-
{
596-
int ret;
597-
598-
BUG_ON(!nents);
599-
600-
if (first_chunk) {
601-
if (nents <= SG_CHUNK_SIZE) {
602-
table->nents = table->orig_nents = nents;
603-
sg_init_table(table->sgl, nents);
604-
return 0;
605-
}
606-
}
607-
608-
ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE,
609-
first_chunk, GFP_ATOMIC, sg_pool_alloc);
610-
if (unlikely(ret))
611-
sg_free_table_chained(table, (bool)first_chunk);
612-
return ret;
613-
}
614-
615521
static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
616522
{
617523
if (cmd->request->cmd_type == REQ_TYPE_FS) {
@@ -2269,8 +2175,6 @@ EXPORT_SYMBOL(scsi_unblock_requests);
22692175

22702176
int __init scsi_init_queue(void)
22712177
{
2272-
int i;
2273-
22742178
scsi_sdb_cache = kmem_cache_create("scsi_data_buffer",
22752179
sizeof(struct scsi_data_buffer),
22762180
0, 0, NULL);
@@ -2279,53 +2183,12 @@ int __init scsi_init_queue(void)
22792183
return -ENOMEM;
22802184
}
22812185

2282-
for (i = 0; i < SG_MEMPOOL_NR; i++) {
2283-
struct sg_pool *sgp = sg_pools + i;
2284-
int size = sgp->size * sizeof(struct scatterlist);
2285-
2286-
sgp->slab = kmem_cache_create(sgp->name, size, 0,
2287-
SLAB_HWCACHE_ALIGN, NULL);
2288-
if (!sgp->slab) {
2289-
printk(KERN_ERR "SCSI: can't init sg slab %s\n",
2290-
sgp->name);
2291-
goto cleanup_sdb;
2292-
}
2293-
2294-
sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE,
2295-
sgp->slab);
2296-
if (!sgp->pool) {
2297-
printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
2298-
sgp->name);
2299-
goto cleanup_sdb;
2300-
}
2301-
}
2302-
23032186
return 0;
2304-
2305-
cleanup_sdb:
2306-
for (i = 0; i < SG_MEMPOOL_NR; i++) {
2307-
struct sg_pool *sgp = sg_pools + i;
2308-
if (sgp->pool)
2309-
mempool_destroy(sgp->pool);
2310-
if (sgp->slab)
2311-
kmem_cache_destroy(sgp->slab);
2312-
}
2313-
kmem_cache_destroy(scsi_sdb_cache);
2314-
2315-
return -ENOMEM;
23162187
}
23172188

23182189
void scsi_exit_queue(void)
23192190
{
2320-
int i;
2321-
23222191
kmem_cache_destroy(scsi_sdb_cache);
2323-
2324-
for (i = 0; i < SG_MEMPOOL_NR; i++) {
2325-
struct sg_pool *sgp = sg_pools + i;
2326-
mempool_destroy(sgp->pool);
2327-
kmem_cache_destroy(sgp->slab);
2328-
}
23292192
}
23302193

23312194
/**

include/linux/scatterlist.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,31 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
285285
*/
286286
#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
287287

288+
/*
289+
* The maximum number of SG segments that we will put inside a
290+
* scatterlist (unless chaining is used). Should ideally fit inside a
291+
* single page, to avoid a higher order allocation. We could define this
292+
* to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The
293+
* minimum value is 32
294+
*/
295+
#define SG_CHUNK_SIZE 128
296+
297+
/*
298+
* Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit
299+
* is totally arbitrary, a setting of 2048 will get you at least 8mb ios.
300+
*/
301+
#ifdef CONFIG_ARCH_HAS_SG_CHAIN
302+
#define SG_MAX_SEGMENTS 2048
303+
#else
304+
#define SG_MAX_SEGMENTS SG_CHUNK_SIZE
305+
#endif
306+
307+
#ifdef CONFIG_SG_POOL
308+
void sg_free_table_chained(struct sg_table *table, bool first_chunk);
309+
int sg_alloc_table_chained(struct sg_table *table, int nents,
310+
struct scatterlist *first_chunk);
311+
#endif
312+
288313
/*
289314
* sg page iterator
290315
*

include/scsi/scsi.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,6 @@ enum scsi_timeouts {
1717
SCSI_DEFAULT_EH_TIMEOUT = 10 * HZ,
1818
};
1919

20-
/*
21-
* The maximum number of SG segments that we will put inside a
22-
* scatterlist (unless chaining is used). Should ideally fit inside a
23-
* single page, to avoid a higher order allocation. We could define this
24-
* to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The
25-
* minimum value is 32
26-
*/
27-
#define SG_CHUNK_SIZE 128
28-
29-
/*
30-
* Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit
31-
* is totally arbitrary, a setting of 2048 will get you at least 8mb ios.
32-
*/
33-
#ifdef CONFIG_ARCH_HAS_SG_CHAIN
34-
#define SG_MAX_SEGMENTS 2048
35-
#else
36-
#define SG_MAX_SEGMENTS SG_CHUNK_SIZE
37-
#endif
38-
3920
/*
4021
* DIX-capable adapters effectively support infinite chaining for the
4122
* protection information scatterlist

lib/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,13 @@ config SG_SPLIT
523523
a scatterlist. This should be selected by a driver or an API which
524524
whishes to split a scatterlist amongst multiple DMA channels.
525525

526+
config SG_POOL
527+
def_bool n
528+
help
529+
Provides a helper to allocate chained scatterlists. This should be
530+
selected by a driver or an API which whishes to allocate chained
531+
scatterlist.
532+
526533
#
527534
# sg chaining option
528535
#

lib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o
178178
obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o
179179

180180
obj-$(CONFIG_SG_SPLIT) += sg_split.o
181+
obj-$(CONFIG_SG_POOL) += sg_pool.o
181182
obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
182183
obj-$(CONFIG_IRQ_POLL) += irq_poll.o
183184

0 commit comments

Comments
 (0)