aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-20 10:28:24 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:37:44 -0500
commit5b7f16804ad90e7f7a10c05b6a2e782598d9745a (patch)
tree2228c575b0b001eaf76f48216fee2f066065681a
parentde25deb18016f66dcdede165d07654559bb332bc (diff)
[SCSI] don't use __GFP_DMA for sense buffers if not required
Only hosts which actually have ISA DMA requirements need sense buffers coming out of ZONE_DMA, so only use the __GFP_DMA flag for that case to avoid allocating this scarce resource if it's not necessary. [tomo: fixed slab leak in failure case] Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/hosts.c9
-rw-r--r--drivers/scsi/scsi.c111
-rw-r--r--drivers/scsi/scsi_priv.h2
3 files changed, 51 insertions, 71 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index f5d3fbb55717..9a10b4335e76 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -268,7 +268,6 @@ static void scsi_host_dev_release(struct device *dev)
268 } 268 }
269 269
270 scsi_destroy_command_freelist(shost); 270 scsi_destroy_command_freelist(shost);
271 scsi_destroy_command_sense_buffer(shost);
272 if (shost->bqt) 271 if (shost->bqt)
273 blk_free_tags(shost->bqt); 272 blk_free_tags(shost->bqt);
274 273
@@ -373,13 +372,9 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
373 else 372 else
374 shost->dma_boundary = 0xffffffff; 373 shost->dma_boundary = 0xffffffff;
375 374
376 rval = scsi_setup_command_sense_buffer(shost);
377 if (rval)
378 goto fail_kfree;
379
380 rval = scsi_setup_command_freelist(shost); 375 rval = scsi_setup_command_freelist(shost);
381 if (rval) 376 if (rval)
382 goto fail_destroy_sense; 377 goto fail_kfree;
383 378
384 device_initialize(&shost->shost_gendev); 379 device_initialize(&shost->shost_gendev);
385 snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d", 380 snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
@@ -404,8 +399,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
404 399
405 fail_destroy_freelist: 400 fail_destroy_freelist:
406 scsi_destroy_command_freelist(shost); 401 scsi_destroy_command_freelist(shost);
407 fail_destroy_sense:
408 scsi_destroy_command_sense_buffer(shost);
409 fail_kfree: 402 fail_kfree:
410 kfree(shost); 403 kfree(shost);
411 return NULL; 404 return NULL;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 0a4a5b8b87c6..1a9fba6a9f92 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -141,29 +141,30 @@ const char * scsi_device_type(unsigned type)
141EXPORT_SYMBOL(scsi_device_type); 141EXPORT_SYMBOL(scsi_device_type);
142 142
143struct scsi_host_cmd_pool { 143struct scsi_host_cmd_pool {
144 struct kmem_cache *slab; 144 struct kmem_cache *cmd_slab;
145 unsigned int users; 145 struct kmem_cache *sense_slab;
146 char *name; 146 unsigned int users;
147 unsigned int slab_flags; 147 char *cmd_name;
148 gfp_t gfp_mask; 148 char *sense_name;
149 unsigned int slab_flags;
150 gfp_t gfp_mask;
149}; 151};
150 152
151static struct scsi_host_cmd_pool scsi_cmd_pool = { 153static struct scsi_host_cmd_pool scsi_cmd_pool = {
152 .name = "scsi_cmd_cache", 154 .cmd_name = "scsi_cmd_cache",
155 .sense_name = "scsi_sense_cache",
153 .slab_flags = SLAB_HWCACHE_ALIGN, 156 .slab_flags = SLAB_HWCACHE_ALIGN,
154}; 157};
155 158
156static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { 159static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
157 .name = "scsi_cmd_cache(DMA)", 160 .cmd_name = "scsi_cmd_cache(DMA)",
161 .sense_name = "scsi_sense_cache(DMA)",
158 .slab_flags = SLAB_HWCACHE_ALIGN|SLAB_CACHE_DMA, 162 .slab_flags = SLAB_HWCACHE_ALIGN|SLAB_CACHE_DMA,
159 .gfp_mask = __GFP_DMA, 163 .gfp_mask = __GFP_DMA,
160}; 164};
161 165
162static DEFINE_MUTEX(host_cmd_pool_mutex); 166static DEFINE_MUTEX(host_cmd_pool_mutex);
163 167
164static struct kmem_cache *sense_buffer_slab;
165static int sense_buffer_slab_users;
166
167/** 168/**
168 * __scsi_get_command - Allocate a struct scsi_cmnd 169 * __scsi_get_command - Allocate a struct scsi_cmnd
169 * @shost: host to transmit command 170 * @shost: host to transmit command
@@ -177,8 +178,8 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
177 struct scsi_cmnd *cmd; 178 struct scsi_cmnd *cmd;
178 unsigned char *buf; 179 unsigned char *buf;
179 180
180 cmd = kmem_cache_alloc(shost->cmd_pool->slab, 181 cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
181 gfp_mask | shost->cmd_pool->gfp_mask); 182 gfp_mask | shost->cmd_pool->gfp_mask);
182 183
183 if (unlikely(!cmd)) { 184 if (unlikely(!cmd)) {
184 unsigned long flags; 185 unsigned long flags;
@@ -197,12 +198,13 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
197 cmd->sense_buffer = buf; 198 cmd->sense_buffer = buf;
198 } 199 }
199 } else { 200 } else {
200 buf = kmem_cache_alloc(sense_buffer_slab, __GFP_DMA|gfp_mask); 201 buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
202 gfp_mask | shost->cmd_pool->gfp_mask);
201 if (likely(buf)) { 203 if (likely(buf)) {
202 memset(cmd, 0, sizeof(*cmd)); 204 memset(cmd, 0, sizeof(*cmd));
203 cmd->sense_buffer = buf; 205 cmd->sense_buffer = buf;
204 } else { 206 } else {
205 kmem_cache_free(shost->cmd_pool->slab, cmd); 207 kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
206 cmd = NULL; 208 cmd = NULL;
207 } 209 }
208 } 210 }
@@ -265,8 +267,9 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
265 spin_unlock_irqrestore(&shost->free_list_lock, flags); 267 spin_unlock_irqrestore(&shost->free_list_lock, flags);
266 268
267 if (likely(cmd != NULL)) { 269 if (likely(cmd != NULL)) {
268 kmem_cache_free(sense_buffer_slab, cmd->sense_buffer); 270 kmem_cache_free(shost->cmd_pool->sense_slab,
269 kmem_cache_free(shost->cmd_pool->slab, cmd); 271 cmd->sense_buffer);
272 kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
270 } 273 }
271 274
272 put_device(dev); 275 put_device(dev);
@@ -310,7 +313,6 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
310{ 313{
311 struct scsi_host_cmd_pool *pool; 314 struct scsi_host_cmd_pool *pool;
312 struct scsi_cmnd *cmd; 315 struct scsi_cmnd *cmd;
313 unsigned char *sense_buffer;
314 316
315 spin_lock_init(&shost->free_list_lock); 317 spin_lock_init(&shost->free_list_lock);
316 INIT_LIST_HEAD(&shost->free_list); 318 INIT_LIST_HEAD(&shost->free_list);
@@ -322,11 +324,19 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
322 mutex_lock(&host_cmd_pool_mutex); 324 mutex_lock(&host_cmd_pool_mutex);
323 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool); 325 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
324 if (!pool->users) { 326 if (!pool->users) {
325 pool->slab = kmem_cache_create(pool->name, 327 pool->cmd_slab = kmem_cache_create(pool->cmd_name,
326 sizeof(struct scsi_cmnd), 0, 328 sizeof(struct scsi_cmnd), 0,
327 pool->slab_flags, NULL); 329 pool->slab_flags, NULL);
328 if (!pool->slab) 330 if (!pool->cmd_slab)
331 goto fail;
332
333 pool->sense_slab = kmem_cache_create(pool->sense_name,
334 SCSI_SENSE_BUFFERSIZE, 0,
335 pool->slab_flags, NULL);
336 if (!pool->sense_slab) {
337 kmem_cache_destroy(pool->cmd_slab);
329 goto fail; 338 goto fail;
339 }
330 } 340 }
331 341
332 pool->users++; 342 pool->users++;
@@ -336,26 +346,28 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
336 /* 346 /*
337 * Get one backup command for this host. 347 * Get one backup command for this host.
338 */ 348 */
339 cmd = kmem_cache_alloc(shost->cmd_pool->slab, 349 cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
340 GFP_KERNEL | shost->cmd_pool->gfp_mask); 350 GFP_KERNEL | shost->cmd_pool->gfp_mask);
341 if (!cmd) 351 if (!cmd)
342 goto fail2; 352 goto fail2;
343 353
344 sense_buffer = kmem_cache_alloc(sense_buffer_slab, 354 cmd->sense_buffer = kmem_cache_alloc(shost->cmd_pool->sense_slab,
345 GFP_KERNEL | __GFP_DMA); 355 GFP_KERNEL |
346 if (!sense_buffer) 356 shost->cmd_pool->gfp_mask);
347 goto destroy_backup; 357 if (!cmd->sense_buffer)
358 goto fail2;
348 359
349 cmd->sense_buffer = sense_buffer;
350 list_add(&cmd->list, &shost->free_list); 360 list_add(&cmd->list, &shost->free_list);
351 return 0; 361 return 0;
352 362
353destroy_backup:
354 kmem_cache_free(shost->cmd_pool->slab, cmd);
355 fail2: 363 fail2:
364 if (cmd)
365 kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
356 mutex_lock(&host_cmd_pool_mutex); 366 mutex_lock(&host_cmd_pool_mutex);
357 if (!--pool->users) 367 if (!--pool->users) {
358 kmem_cache_destroy(pool->slab); 368 kmem_cache_destroy(pool->cmd_slab);
369 kmem_cache_destroy(pool->sense_slab);
370 }
359 fail: 371 fail:
360 mutex_unlock(&host_cmd_pool_mutex); 372 mutex_unlock(&host_cmd_pool_mutex);
361 return -ENOMEM; 373 return -ENOMEM;
@@ -372,39 +384,16 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
372 384
373 cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list); 385 cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
374 list_del_init(&cmd->list); 386 list_del_init(&cmd->list);
375 kmem_cache_free(sense_buffer_slab, cmd->sense_buffer); 387 kmem_cache_free(shost->cmd_pool->sense_slab,
376 kmem_cache_free(shost->cmd_pool->slab, cmd); 388 cmd->sense_buffer);
389 kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
377 } 390 }
378 391
379 mutex_lock(&host_cmd_pool_mutex); 392 mutex_lock(&host_cmd_pool_mutex);
380 if (!--shost->cmd_pool->users) 393 if (!--shost->cmd_pool->users) {
381 kmem_cache_destroy(shost->cmd_pool->slab); 394 kmem_cache_destroy(shost->cmd_pool->cmd_slab);
382 mutex_unlock(&host_cmd_pool_mutex); 395 kmem_cache_destroy(shost->cmd_pool->sense_slab);
383}
384
385int scsi_setup_command_sense_buffer(struct Scsi_Host *shost)
386{
387 mutex_lock(&host_cmd_pool_mutex);
388 if (!sense_buffer_slab_users) {
389 sense_buffer_slab = kmem_cache_create("scsi_sense_buffer",
390 SCSI_SENSE_BUFFERSIZE,
391 0, SLAB_CACHE_DMA, NULL);
392 if (!sense_buffer_slab) {
393 mutex_unlock(&host_cmd_pool_mutex);
394 return -ENOMEM;
395 }
396 } 396 }
397 sense_buffer_slab_users++;
398 mutex_unlock(&host_cmd_pool_mutex);
399
400 return 0;
401}
402
403void scsi_destroy_command_sense_buffer(struct Scsi_Host *shost)
404{
405 mutex_lock(&host_cmd_pool_mutex);
406 if (!--sense_buffer_slab_users)
407 kmem_cache_destroy(sense_buffer_slab);
408 mutex_unlock(&host_cmd_pool_mutex); 397 mutex_unlock(&host_cmd_pool_mutex);
409} 398}
410 399
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 55c6f71a9aee..3f34e9376b0a 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -27,8 +27,6 @@ extern void scsi_exit_hosts(void);
27extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); 27extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
28extern int scsi_setup_command_freelist(struct Scsi_Host *shost); 28extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
29extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); 29extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
30extern int scsi_setup_command_sense_buffer(struct Scsi_Host *shost);
31extern void scsi_destroy_command_sense_buffer(struct Scsi_Host *shost);
32extern void __scsi_done(struct scsi_cmnd *cmd); 30extern void __scsi_done(struct scsi_cmnd *cmd);
33#ifdef CONFIG_SCSI_LOGGING 31#ifdef CONFIG_SCSI_LOGGING
34void scsi_log_send(struct scsi_cmnd *cmd); 32void scsi_log_send(struct scsi_cmnd *cmd);