From a6a8d9f87eb8510a8f53672ea87703f62185d75f Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Thu, 1 May 2008 14:49:46 -0700 Subject: [SCSI] scsi_dh: add infrastructure for SCSI Device Handlers Some of the storage devices (that can be accessed through multiple paths), do need some special handling for 1. Activating the passive path of the storage access. 2. Decode and handle the special sense codes returned by the devices. 3. Handle the I/Os being sent to the passive path, especially during the device probe time. when accessed through multiple paths. As of today this special device handling is done at the dm-multipath layer using dm-handlers. That works well for (1); for (2) to be handled at dm layer, scsi sense information need to be exported from SCSI to dm-layer, which is not very attractive; (3) cannot be done at all at the dm layer. Device handler has been moved to SCSI mainly to handle (2) and (3) properly. Signed-off-by: Chandra Seetharaman Signed-off-by: Mike Anderson Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a82d2fe..033c58a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1160,6 +1160,14 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (ret != BLKPREP_OK) return ret; + + if (unlikely(sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh + && sdev->scsi_dh_data->scsi_dh->prep_fn)) { + ret = sdev->scsi_dh_data->scsi_dh->prep_fn(sdev, req); + if (ret != BLKPREP_OK) + return ret; + } + /* * Filesystem requests must transfer data. */ -- cgit v1.1 From bdb2b8cab4392ce41ddfbd6773a3da3334daf836 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Jun 2008 14:03:14 -0400 Subject: [SCSI] erase invalid data returned by device This patch (as1108) fixes a problem that can occur with certain USB mass-storage devices: They return invalid data together with a residue indicating that the data should be ignored. Rather than leave the invalid data in a transfer buffer, where it can get misinterpreted, the patch clears the invalid portion of the buffer. This solves a problem (wrong write-protect setting detected) reported by Maciej Rutecki and Peter Teoh. Signed-off-by: Alan Stern Tested-by: Peter Teoh Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a82d2fe..cbf55d5 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -207,6 +207,15 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, */ blk_execute_rq(req->q, NULL, req, 1); + /* + * Some devices (USB mass-storage in particular) may transfer + * garbage data together with a residue indicating that the data + * is invalid. Prevent the garbage from being misinterpreted + * and prevent security leaks by zeroing out the excess data. + */ + if (unlikely(req->data_len > 0 && req->data_len <= bufflen)) + memset(buffer + (bufflen - req->data_len), 0, req->data_len); + ret = req->errors; out: blk_put_request(req); -- cgit v1.1 From 6362abd3e00d3161affad996fa53cc69a01fc6d1 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Thu, 5 Jun 2008 23:30:03 -0400 Subject: [SCSI] Rename scsi_bidi_sdb_cache The data integrity changes need to dynamically allocate scsi_data_buffers too. Rename scsi_bidi_sdb_cache for clarity. Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 033c58a..aa8d5de 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -65,7 +65,7 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = { }; #undef SP -static struct kmem_cache *scsi_bidi_sdb_cache; +static struct kmem_cache *scsi_sdb_cache; static void scsi_run_queue(struct request_queue *q); @@ -775,7 +775,7 @@ void scsi_release_buffers(struct scsi_cmnd *cmd) struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; scsi_free_sgtable(bidi_sdb); - kmem_cache_free(scsi_bidi_sdb_cache, bidi_sdb); + kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } } @@ -1050,7 +1050,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) if (blk_bidi_rq(cmd->request)) { struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc( - scsi_bidi_sdb_cache, GFP_ATOMIC); + scsi_sdb_cache, GFP_ATOMIC); if (!bidi_sdb) { error = BLKPREP_DEFER; goto err_exit; @@ -1692,11 +1692,11 @@ int __init scsi_init_queue(void) return -ENOMEM; } - scsi_bidi_sdb_cache = kmem_cache_create("scsi_bidi_sdb", - sizeof(struct scsi_data_buffer), - 0, 0, NULL); - if (!scsi_bidi_sdb_cache) { - printk(KERN_ERR "SCSI: can't init scsi bidi sdb cache\n"); + scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", + sizeof(struct scsi_data_buffer), + 0, 0, NULL); + if (!scsi_sdb_cache) { + printk(KERN_ERR "SCSI: can't init scsi sdb cache\n"); goto cleanup_io_context; } @@ -1709,7 +1709,7 @@ int __init scsi_init_queue(void) if (!sgp->slab) { printk(KERN_ERR "SCSI: can't init sg slab %s\n", sgp->name); - goto cleanup_bidi_sdb; + goto cleanup_sdb; } sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, @@ -1717,13 +1717,13 @@ int __init scsi_init_queue(void) if (!sgp->pool) { printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name); - goto cleanup_bidi_sdb; + goto cleanup_sdb; } } return 0; -cleanup_bidi_sdb: +cleanup_sdb: for (i = 0; i < SG_MEMPOOL_NR; i++) { struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; if (sgp->pool) @@ -1731,7 +1731,7 @@ cleanup_bidi_sdb: if (sgp->slab) kmem_cache_destroy(sgp->slab); } - kmem_cache_destroy(scsi_bidi_sdb_cache); + kmem_cache_destroy(scsi_sdb_cache); cleanup_io_context: kmem_cache_destroy(scsi_io_context_cache); @@ -1743,7 +1743,7 @@ void scsi_exit_queue(void) int i; kmem_cache_destroy(scsi_io_context_cache); - kmem_cache_destroy(scsi_bidi_sdb_cache); + kmem_cache_destroy(scsi_sdb_cache); for (i = 0; i < SG_MEMPOOL_NR; i++) { struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; -- cgit v1.1 From 2476b4d0426e1d6d4a42b2f7ae08f668b2cfe510 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 3 Jul 2008 11:31:55 -0500 Subject: [SCSI] fix locking in host use of blk_plug_device() scsi_lib.c:scsi_host_queue_ready() plugs the device with incorrect locking. It should actually have the queue lock held, but it's holding the host lock. Fix this by eliminating the call. The host ready has no need to plug the queue because if it returns 0 in scsi_request_function control transfers to not_ready which acquires the queue lock and plugs the device if its at zero depth. Reported-by: Elias Oltmanns Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aa8d5de..0451903 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1328,7 +1328,6 @@ static inline int scsi_host_queue_ready(struct request_queue *q, printk("scsi%d unblocking host at zero depth\n", shost->host_no)); } else { - blk_plug_device(q); return 0; } } -- cgit v1.1