aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-03-13 12:19:36 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:18:57 -0400
commit1c353f7d616a4ef04b5e73fe7a2184baa039f06f (patch)
treea5401c83e6cad369d72abcbd06ad55620346d242 /drivers
parente507e30b803fb56d768ed9a597e7609b74d2db21 (diff)
[SCSI] export command allocation and freeing functions independently of the host
This is needed by things like USB storage that want to set up static commands for later use at start of day. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/scsi.c149
1 files changed, 112 insertions, 37 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2cf9a625f227..f6980bd9d8f9 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -330,30 +330,16 @@ void scsi_put_command(struct scsi_cmnd *cmd)
330} 330}
331EXPORT_SYMBOL(scsi_put_command); 331EXPORT_SYMBOL(scsi_put_command);
332 332
333/** 333static struct scsi_host_cmd_pool *scsi_get_host_cmd_pool(gfp_t gfp_mask)
334 * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
335 * @shost: host to allocate the freelist for.
336 *
337 * Description: The command freelist protects against system-wide out of memory
338 * deadlock by preallocating one SCSI command structure for each host, so the
339 * system can always write to a swap file on a device associated with that host.
340 *
341 * Returns: Nothing.
342 */
343int scsi_setup_command_freelist(struct Scsi_Host *shost)
344{ 334{
345 struct scsi_host_cmd_pool *pool; 335 struct scsi_host_cmd_pool *retval = NULL, *pool;
346 struct scsi_cmnd *cmd;
347
348 spin_lock_init(&shost->free_list_lock);
349 INIT_LIST_HEAD(&shost->free_list);
350
351 /* 336 /*
352 * Select a command slab for this host and create it if not 337 * Select a command slab for this host and create it if not
353 * yet existent. 338 * yet existent.
354 */ 339 */
355 mutex_lock(&host_cmd_pool_mutex); 340 mutex_lock(&host_cmd_pool_mutex);
356 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool); 341 pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
342 &scsi_cmd_pool;
357 if (!pool->users) { 343 if (!pool->users) {
358 pool->cmd_slab = kmem_cache_create(pool->cmd_name, 344 pool->cmd_slab = kmem_cache_create(pool->cmd_name,
359 sizeof(struct scsi_cmnd), 0, 345 sizeof(struct scsi_cmnd), 0,
@@ -371,28 +357,122 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
371 } 357 }
372 358
373 pool->users++; 359 pool->users++;
374 shost->cmd_pool = pool; 360 retval = pool;
361 fail:
375 mutex_unlock(&host_cmd_pool_mutex); 362 mutex_unlock(&host_cmd_pool_mutex);
363 return retval;
364}
365
366static void scsi_put_host_cmd_pool(gfp_t gfp_mask)
367{
368 struct scsi_host_cmd_pool *pool;
376 369
370 mutex_lock(&host_cmd_pool_mutex);
371 pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
372 &scsi_cmd_pool;
377 /* 373 /*
378 * Get one backup command for this host. 374 * This may happen if a driver has a mismatched get and put
375 * of the command pool; the driver should be implicated in
376 * the stack trace
379 */ 377 */
380 cmd = scsi_pool_alloc_command(shost->cmd_pool, GFP_KERNEL); 378 BUG_ON(pool->users == 0);
381 if (!cmd)
382 goto fail2;
383 379
384 list_add(&cmd->list, &shost->free_list);
385 return 0;
386
387 fail2:
388 mutex_lock(&host_cmd_pool_mutex);
389 if (!--pool->users) { 380 if (!--pool->users) {
390 kmem_cache_destroy(pool->cmd_slab); 381 kmem_cache_destroy(pool->cmd_slab);
391 kmem_cache_destroy(pool->sense_slab); 382 kmem_cache_destroy(pool->sense_slab);
392 } 383 }
393 fail:
394 mutex_unlock(&host_cmd_pool_mutex); 384 mutex_unlock(&host_cmd_pool_mutex);
395 return -ENOMEM; 385}
386
387/**
388 * scsi_allocate_command - get a fully allocated SCSI command
389 * @gfp_mask: allocation mask
390 *
391 * This function is for use outside of the normal host based pools.
392 * It allocates the relevant command and takes an additional reference
393 * on the pool it used. This function *must* be paired with
394 * scsi_free_command which also has the identical mask, otherwise the
395 * free pool counts will eventually go wrong and you'll trigger a bug.
396 *
397 * This function should *only* be used by drivers that need a static
398 * command allocation at start of day for internal functions.
399 */
400struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask)
401{
402 struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
403
404 if (!pool)
405 return NULL;
406
407 return scsi_pool_alloc_command(pool, gfp_mask);
408}
409EXPORT_SYMBOL(scsi_allocate_command);
410
411/**
412 * scsi_free_command - free a command allocated by scsi_allocate_command
413 * @gfp_mask: mask used in the original allocation
414 * @cmd: command to free
415 *
416 * Note: using the original allocation mask is vital because that's
417 * what determines which command pool we use to free the command. Any
418 * mismatch will cause the system to BUG eventually.
419 */
420void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd)
421{
422 struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
423
424 /*
425 * this could trigger if the mask to scsi_allocate_command
426 * doesn't match this mask. Otherwise we're guaranteed that this
427 * succeeds because scsi_allocate_command must have taken a reference
428 * on the pool
429 */
430 BUG_ON(!pool);
431
432 scsi_pool_free_command(pool, cmd);
433 /*
434 * scsi_put_host_cmd_pool is called twice; once to release the
435 * reference we took above, and once to release the reference
436 * originally taken by scsi_allocate_command
437 */
438 scsi_put_host_cmd_pool(gfp_mask);
439 scsi_put_host_cmd_pool(gfp_mask);
440}
441EXPORT_SYMBOL(scsi_free_command);
442
443/**
444 * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
445 * @shost: host to allocate the freelist for.
446 *
447 * Description: The command freelist protects against system-wide out of memory
448 * deadlock by preallocating one SCSI command structure for each host, so the
449 * system can always write to a swap file on a device associated with that host.
450 *
451 * Returns: Nothing.
452 */
453int scsi_setup_command_freelist(struct Scsi_Host *shost)
454{
455 struct scsi_cmnd *cmd;
456 const gfp_t gfp_mask = shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL;
457
458 spin_lock_init(&shost->free_list_lock);
459 INIT_LIST_HEAD(&shost->free_list);
460
461 shost->cmd_pool = scsi_get_host_cmd_pool(gfp_mask);
462
463 if (!shost->cmd_pool)
464 return -ENOMEM;
465
466 /*
467 * Get one backup command for this host.
468 */
469 cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
470 if (!cmd) {
471 scsi_put_host_cmd_pool(gfp_mask);
472 return -ENOMEM;
473 }
474 list_add(&cmd->list, &shost->free_list);
475 return 0;
396} 476}
397 477
398/** 478/**
@@ -408,13 +488,8 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
408 list_del_init(&cmd->list); 488 list_del_init(&cmd->list);
409 scsi_pool_free_command(shost->cmd_pool, cmd); 489 scsi_pool_free_command(shost->cmd_pool, cmd);
410 } 490 }
411 491 shost->cmd_pool = NULL;
412 mutex_lock(&host_cmd_pool_mutex); 492 scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL);
413 if (!--shost->cmd_pool->users) {
414 kmem_cache_destroy(shost->cmd_pool->cmd_slab);
415 kmem_cache_destroy(shost->cmd_pool->sense_slab);
416 }
417 mutex_unlock(&host_cmd_pool_mutex);
418} 493}
419 494
420#ifdef CONFIG_SCSI_LOGGING 495#ifdef CONFIG_SCSI_LOGGING