diff options
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r-- | drivers/scsi/scsi.c | 229 |
1 files changed, 161 insertions, 68 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c78b836f59dd..f6980bd9d8f9 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -166,6 +166,51 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { | |||
166 | static DEFINE_MUTEX(host_cmd_pool_mutex); | 166 | static DEFINE_MUTEX(host_cmd_pool_mutex); |
167 | 167 | ||
168 | /** | 168 | /** |
169 | * scsi_pool_alloc_command - internal function to get a fully allocated command | ||
170 | * @pool: slab pool to allocate the command from | ||
171 | * @gfp_mask: mask for the allocation | ||
172 | * | ||
173 | * Returns a fully allocated command (with the allied sense buffer) or | ||
174 | * NULL on failure | ||
175 | */ | ||
176 | static struct scsi_cmnd * | ||
177 | scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask) | ||
178 | { | ||
179 | struct scsi_cmnd *cmd; | ||
180 | |||
181 | cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask); | ||
182 | if (!cmd) | ||
183 | return NULL; | ||
184 | |||
185 | memset(cmd, 0, sizeof(*cmd)); | ||
186 | |||
187 | cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab, | ||
188 | gfp_mask | pool->gfp_mask); | ||
189 | if (!cmd->sense_buffer) { | ||
190 | kmem_cache_free(pool->cmd_slab, cmd); | ||
191 | return NULL; | ||
192 | } | ||
193 | |||
194 | return cmd; | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * scsi_pool_free_command - internal function to release a command | ||
199 | * @pool: slab pool to allocate the command from | ||
200 | * @cmd: command to release | ||
201 | * | ||
202 | * the command must previously have been allocated by | ||
203 | * scsi_pool_alloc_command. | ||
204 | */ | ||
205 | static void | ||
206 | scsi_pool_free_command(struct scsi_host_cmd_pool *pool, | ||
207 | struct scsi_cmnd *cmd) | ||
208 | { | ||
209 | kmem_cache_free(pool->sense_slab, cmd->sense_buffer); | ||
210 | kmem_cache_free(pool->cmd_slab, cmd); | ||
211 | } | ||
212 | |||
213 | /** | ||
169 | * __scsi_get_command - Allocate a struct scsi_cmnd | 214 | * __scsi_get_command - Allocate a struct scsi_cmnd |
170 | * @shost: host to transmit command | 215 | * @shost: host to transmit command |
171 | * @gfp_mask: allocation mask | 216 | * @gfp_mask: allocation mask |
@@ -178,20 +223,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) | |||
178 | struct scsi_cmnd *cmd; | 223 | struct scsi_cmnd *cmd; |
179 | unsigned char *buf; | 224 | unsigned char *buf; |
180 | 225 | ||
181 | cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab, | 226 | cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask); |
182 | gfp_mask | shost->cmd_pool->gfp_mask); | ||
183 | |||
184 | if (likely(cmd)) { | ||
185 | buf = kmem_cache_alloc(shost->cmd_pool->sense_slab, | ||
186 | gfp_mask | shost->cmd_pool->gfp_mask); | ||
187 | if (likely(buf)) { | ||
188 | memset(cmd, 0, sizeof(*cmd)); | ||
189 | cmd->sense_buffer = buf; | ||
190 | } else { | ||
191 | kmem_cache_free(shost->cmd_pool->cmd_slab, cmd); | ||
192 | cmd = NULL; | ||
193 | } | ||
194 | } | ||
195 | 227 | ||
196 | if (unlikely(!cmd)) { | 228 | if (unlikely(!cmd)) { |
197 | unsigned long flags; | 229 | unsigned long flags; |
@@ -268,11 +300,8 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd, | |||
268 | } | 300 | } |
269 | spin_unlock_irqrestore(&shost->free_list_lock, flags); | 301 | spin_unlock_irqrestore(&shost->free_list_lock, flags); |
270 | 302 | ||
271 | if (likely(cmd != NULL)) { | 303 | if (likely(cmd != NULL)) |
272 | kmem_cache_free(shost->cmd_pool->sense_slab, | 304 | scsi_pool_free_command(shost->cmd_pool, cmd); |
273 | cmd->sense_buffer); | ||
274 | kmem_cache_free(shost->cmd_pool->cmd_slab, cmd); | ||
275 | } | ||
276 | 305 | ||
277 | put_device(dev); | 306 | put_device(dev); |
278 | } | 307 | } |
@@ -301,30 +330,16 @@ void scsi_put_command(struct scsi_cmnd *cmd) | |||
301 | } | 330 | } |
302 | EXPORT_SYMBOL(scsi_put_command); | 331 | EXPORT_SYMBOL(scsi_put_command); |
303 | 332 | ||
304 | /** | 333 | static struct scsi_host_cmd_pool *scsi_get_host_cmd_pool(gfp_t gfp_mask) |
305 | * scsi_setup_command_freelist - Setup the command freelist for a scsi host. | ||
306 | * @shost: host to allocate the freelist for. | ||
307 | * | ||
308 | * Description: The command freelist protects against system-wide out of memory | ||
309 | * deadlock by preallocating one SCSI command structure for each host, so the | ||
310 | * system can always write to a swap file on a device associated with that host. | ||
311 | * | ||
312 | * Returns: Nothing. | ||
313 | */ | ||
314 | int scsi_setup_command_freelist(struct Scsi_Host *shost) | ||
315 | { | 334 | { |
316 | struct scsi_host_cmd_pool *pool; | 335 | struct scsi_host_cmd_pool *retval = NULL, *pool; |
317 | struct scsi_cmnd *cmd; | ||
318 | |||
319 | spin_lock_init(&shost->free_list_lock); | ||
320 | INIT_LIST_HEAD(&shost->free_list); | ||
321 | |||
322 | /* | 336 | /* |
323 | * 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 |
324 | * yet existent. | 338 | * yet existent. |
325 | */ | 339 | */ |
326 | mutex_lock(&host_cmd_pool_mutex); | 340 | mutex_lock(&host_cmd_pool_mutex); |
327 | 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; | ||
328 | if (!pool->users) { | 343 | if (!pool->users) { |
329 | pool->cmd_slab = kmem_cache_create(pool->cmd_name, | 344 | pool->cmd_slab = kmem_cache_create(pool->cmd_name, |
330 | sizeof(struct scsi_cmnd), 0, | 345 | sizeof(struct scsi_cmnd), 0, |
@@ -342,37 +357,122 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) | |||
342 | } | 357 | } |
343 | 358 | ||
344 | pool->users++; | 359 | pool->users++; |
345 | shost->cmd_pool = pool; | 360 | retval = pool; |
361 | fail: | ||
346 | mutex_unlock(&host_cmd_pool_mutex); | 362 | mutex_unlock(&host_cmd_pool_mutex); |
363 | return retval; | ||
364 | } | ||
365 | |||
366 | static void scsi_put_host_cmd_pool(gfp_t gfp_mask) | ||
367 | { | ||
368 | struct scsi_host_cmd_pool *pool; | ||
347 | 369 | ||
370 | mutex_lock(&host_cmd_pool_mutex); | ||
371 | pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool : | ||
372 | &scsi_cmd_pool; | ||
348 | /* | 373 | /* |
349 | * 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 | ||
350 | */ | 377 | */ |
351 | cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab, | 378 | BUG_ON(pool->users == 0); |
352 | GFP_KERNEL | shost->cmd_pool->gfp_mask); | ||
353 | if (!cmd) | ||
354 | goto fail2; | ||
355 | 379 | ||
356 | cmd->sense_buffer = kmem_cache_alloc(shost->cmd_pool->sense_slab, | ||
357 | GFP_KERNEL | | ||
358 | shost->cmd_pool->gfp_mask); | ||
359 | if (!cmd->sense_buffer) | ||
360 | goto fail2; | ||
361 | |||
362 | list_add(&cmd->list, &shost->free_list); | ||
363 | return 0; | ||
364 | |||
365 | fail2: | ||
366 | if (cmd) | ||
367 | kmem_cache_free(shost->cmd_pool->cmd_slab, cmd); | ||
368 | mutex_lock(&host_cmd_pool_mutex); | ||
369 | if (!--pool->users) { | 380 | if (!--pool->users) { |
370 | kmem_cache_destroy(pool->cmd_slab); | 381 | kmem_cache_destroy(pool->cmd_slab); |
371 | kmem_cache_destroy(pool->sense_slab); | 382 | kmem_cache_destroy(pool->sense_slab); |
372 | } | 383 | } |
373 | fail: | ||
374 | mutex_unlock(&host_cmd_pool_mutex); | 384 | mutex_unlock(&host_cmd_pool_mutex); |
375 | 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 | */ | ||
400 | struct 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 | } | ||
409 | EXPORT_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 | */ | ||
420 | void 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 | } | ||
441 | EXPORT_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 | */ | ||
453 | int 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; | ||
376 | } | 476 | } |
377 | 477 | ||
378 | /** | 478 | /** |
@@ -386,17 +486,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost) | |||
386 | 486 | ||
387 | cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list); | 487 | cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list); |
388 | list_del_init(&cmd->list); | 488 | list_del_init(&cmd->list); |
389 | kmem_cache_free(shost->cmd_pool->sense_slab, | 489 | scsi_pool_free_command(shost->cmd_pool, cmd); |
390 | cmd->sense_buffer); | ||
391 | kmem_cache_free(shost->cmd_pool->cmd_slab, cmd); | ||
392 | } | 490 | } |
393 | 491 | shost->cmd_pool = NULL; | |
394 | mutex_lock(&host_cmd_pool_mutex); | 492 | scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL); |
395 | if (!--shost->cmd_pool->users) { | ||
396 | kmem_cache_destroy(shost->cmd_pool->cmd_slab); | ||
397 | kmem_cache_destroy(shost->cmd_pool->sense_slab); | ||
398 | } | ||
399 | mutex_unlock(&host_cmd_pool_mutex); | ||
400 | } | 493 | } |
401 | 494 | ||
402 | #ifdef CONFIG_SCSI_LOGGING | 495 | #ifdef CONFIG_SCSI_LOGGING |