Skip to content

Commit de25deb

Browse files
fujitajejb
authored andcommitted
[SCSI] use dynamically allocated sense buffer
This removes static array sense_buffer in scsi_cmnd and uses dynamically allocated sense_buffer (with GFP_DMA). The reason for doing this is that some architectures need cacheline aligned buffer for DMA: http://lkml.org/lkml/2007/11/19/2 The problems are that scsi_eh_prep_cmnd puts scsi_cmnd::sense_buffer to sglist and some LLDs directly DMA to scsi_cmnd::sense_buffer. It's necessary to DMA to scsi_cmnd::sense_buffer safely. This patch solves these issues. __scsi_get_command allocates sense_buffer via kmem_cache_alloc and attaches it to a scsi_cmnd so everything just work as before. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
1 parent b30c2fc commit de25deb

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

drivers/scsi/hosts.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ static void scsi_host_dev_release(struct device *dev)
268268
}
269269

270270
scsi_destroy_command_freelist(shost);
271+
scsi_destroy_command_sense_buffer(shost);
271272
if (shost->bqt)
272273
blk_free_tags(shost->bqt);
273274

@@ -372,10 +373,14 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
372373
else
373374
shost->dma_boundary = 0xffffffff;
374375

375-
rval = scsi_setup_command_freelist(shost);
376+
rval = scsi_setup_command_sense_buffer(shost);
376377
if (rval)
377378
goto fail_kfree;
378379

380+
rval = scsi_setup_command_freelist(shost);
381+
if (rval)
382+
goto fail_destroy_sense;
383+
379384
device_initialize(&shost->shost_gendev);
380385
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
381386
shost->host_no);
@@ -399,6 +404,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
399404

400405
fail_destroy_freelist:
401406
scsi_destroy_command_freelist(shost);
407+
fail_destroy_sense:
408+
scsi_destroy_command_sense_buffer(shost);
402409
fail_kfree:
403410
kfree(shost);
404411
return NULL;

drivers/scsi/scsi.c

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
161161

162162
static DEFINE_MUTEX(host_cmd_pool_mutex);
163163

164+
static struct kmem_cache *sense_buffer_slab;
165+
static int sense_buffer_slab_users;
166+
164167
/**
165168
* __scsi_get_command - Allocate a struct scsi_cmnd
166169
* @shost: host to transmit command
@@ -172,6 +175,7 @@ static DEFINE_MUTEX(host_cmd_pool_mutex);
172175
struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
173176
{
174177
struct scsi_cmnd *cmd;
178+
unsigned char *buf;
175179

176180
cmd = kmem_cache_alloc(shost->cmd_pool->slab,
177181
gfp_mask | shost->cmd_pool->gfp_mask);
@@ -186,6 +190,21 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
186190
list_del_init(&cmd->list);
187191
}
188192
spin_unlock_irqrestore(&shost->free_list_lock, flags);
193+
194+
if (cmd) {
195+
buf = cmd->sense_buffer;
196+
memset(cmd, 0, sizeof(*cmd));
197+
cmd->sense_buffer = buf;
198+
}
199+
} else {
200+
buf = kmem_cache_alloc(sense_buffer_slab, __GFP_DMA|gfp_mask);
201+
if (likely(buf)) {
202+
memset(cmd, 0, sizeof(*cmd));
203+
cmd->sense_buffer = buf;
204+
} else {
205+
kmem_cache_free(shost->cmd_pool->slab, cmd);
206+
cmd = NULL;
207+
}
189208
}
190209

191210
return cmd;
@@ -212,7 +231,6 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
212231
if (likely(cmd != NULL)) {
213232
unsigned long flags;
214233

215-
memset(cmd, 0, sizeof(*cmd));
216234
cmd->device = dev;
217235
init_timer(&cmd->eh_timeout);
218236
INIT_LIST_HEAD(&cmd->list);
@@ -246,8 +264,10 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
246264
}
247265
spin_unlock_irqrestore(&shost->free_list_lock, flags);
248266

249-
if (likely(cmd != NULL))
267+
if (likely(cmd != NULL)) {
268+
kmem_cache_free(sense_buffer_slab, cmd->sense_buffer);
250269
kmem_cache_free(shost->cmd_pool->slab, cmd);
270+
}
251271

252272
put_device(dev);
253273
}
@@ -290,6 +310,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
290310
{
291311
struct scsi_host_cmd_pool *pool;
292312
struct scsi_cmnd *cmd;
313+
unsigned char *sense_buffer;
293314

294315
spin_lock_init(&shost->free_list_lock);
295316
INIT_LIST_HEAD(&shost->free_list);
@@ -319,9 +340,18 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
319340
GFP_KERNEL | shost->cmd_pool->gfp_mask);
320341
if (!cmd)
321342
goto fail2;
343+
344+
sense_buffer = kmem_cache_alloc(sense_buffer_slab,
345+
GFP_KERNEL | __GFP_DMA);
346+
if (!sense_buffer)
347+
goto destroy_backup;
348+
349+
cmd->sense_buffer = sense_buffer;
322350
list_add(&cmd->list, &shost->free_list);
323351
return 0;
324352

353+
destroy_backup:
354+
kmem_cache_free(shost->cmd_pool->slab, cmd);
325355
fail2:
326356
mutex_lock(&host_cmd_pool_mutex);
327357
if (!--pool->users)
@@ -342,6 +372,7 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
342372

343373
cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
344374
list_del_init(&cmd->list);
375+
kmem_cache_free(sense_buffer_slab, cmd->sense_buffer);
345376
kmem_cache_free(shost->cmd_pool->slab, cmd);
346377
}
347378

@@ -351,6 +382,32 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
351382
mutex_unlock(&host_cmd_pool_mutex);
352383
}
353384

385+
int 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+
}
397+
sense_buffer_slab_users++;
398+
mutex_unlock(&host_cmd_pool_mutex);
399+
400+
return 0;
401+
}
402+
403+
void 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);
409+
}
410+
354411
#ifdef CONFIG_SCSI_LOGGING
355412
void scsi_log_send(struct scsi_cmnd *cmd)
356413
{

drivers/scsi/scsi_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ extern void scsi_exit_hosts(void);
2727
extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
2828
extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
2929
extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
30+
extern int scsi_setup_command_sense_buffer(struct Scsi_Host *shost);
31+
extern void scsi_destroy_command_sense_buffer(struct Scsi_Host *shost);
3032
extern void __scsi_done(struct scsi_cmnd *cmd);
3133
#ifdef CONFIG_SCSI_LOGGING
3234
void scsi_log_send(struct scsi_cmnd *cmd);

include/scsi/scsi_cmnd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct scsi_cmnd {
8888
working on */
8989

9090
#define SCSI_SENSE_BUFFERSIZE 96
91-
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
91+
unsigned char *sense_buffer;
9292
/* obtained by REQUEST SENSE when
9393
* CHECK CONDITION is received on original
9494
* command (auto-sense) */

0 commit comments

Comments
 (0)