From 24669f75a3231fa37444977c92d1f4838bec1233 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 16 Jan 2006 10:31:18 -0500 Subject: [SCSI] SCSI core kmalloc2kzalloc Change the core SCSI code to use kzalloc rather than kmalloc+memset where possible. Signed-off-by: Jes Sorensen Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 5acb83ca5ae5..74863da1d630 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -205,12 +205,11 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, int display_failure_msg = 1, ret; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size, + sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, GFP_ATOMIC); if (!sdev) goto out; - memset(sdev, 0, sizeof(*sdev)); sdev->vendor = scsi_null_device_strs; sdev->model = scsi_null_device_strs; sdev->rev = scsi_null_device_strs; @@ -334,12 +333,11 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, struct scsi_target *starget; struct scsi_target *found_target; - starget = kmalloc(size, GFP_KERNEL); + starget = kzalloc(size, GFP_KERNEL); if (!starget) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; } - memset(starget, 0, size); dev = &starget->dev; device_initialize(dev); starget->reap_ref = 1; -- cgit v1.2.3 From 5e3c34c1e988a0dfe177c38cf324e8e321c55ef5 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Wed, 18 Jan 2006 16:17:46 -0800 Subject: [SCSI] Remove devfs support from the SCSI subsystem As devfs has been disabled from the kernel tree for a number of months now (5 to be exact), here's a patch against 2.6.16-rc1-git1 that removes support for it from the SCSI subsystem. The patch also removes the scsi_disk devfs_name field as it's no longer needed. Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 74863da1d630..dfdbbd008630 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -687,12 +687,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) if (inq_result[7] & 0x10) sdev->sdtr = 1; - sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d", - sdev->host->host_no, sdev->channel, - sdev->id, sdev->lun); - /* - * End driverfs/devfs code. + * End sysfs code. */ if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && -- cgit v1.2.3 From a97a83a06b44d4d1cb01191423caf9813a150b95 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 5 Feb 2006 08:01:33 -0700 Subject: [SCSI] fix uninitialized variable error in __scsi_add_device, sdev may be uninitialised if scsi_host_scan_allowed() returns false. Fix by initialising at the top of the routine. Also rely on the fact that scsi_probe_and_add_lun() only actually fills in the sdev pointer if the SCSI_SCAN_LUN_PRESENT case (so no need to check the return value). Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index dfdbbd008630..803c7b9690c5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1243,9 +1243,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, uint id, uint lun, void *hostdata) { - struct scsi_device *sdev; + struct scsi_device *sdev = ERR_PTR(-ENODEV); struct device *parent = &shost->shost_gendev; - int res; struct scsi_target *starget; starget = scsi_alloc_target(parent, channel, id); @@ -1254,12 +1253,8 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, get_device(&starget->dev); mutex_lock(&shost->scan_mutex); - if (scsi_host_scan_allowed(shost)) { - res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, - hostdata); - if (res != SCSI_SCAN_LUN_PRESENT) - sdev = ERR_PTR(-ENODEV); - } + if (scsi_host_scan_allowed(shost)) + scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); mutex_unlock(&shost->scan_mutex); scsi_target_reap(starget); put_device(&starget->dev); -- cgit v1.2.3 From 1bfc5d9d5eb8e1a2efacc306bc55c248ed259a8e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 9 Feb 2006 15:26:18 -0500 Subject: [SCSI] Recognize missing LUNs for non-standard devices Some non-standard SCSI targets or protocols, such as USB UFI, report "no LUN present" by setting the Peripheral Device Type to 0x1f and the Peripheral Qualifier to 0 (not 3 as the standard requires) in the INQUIRY response. This patch (as650b) adds a new target flag and code to accomodate such targets. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 803c7b9690c5..94b86d5b1469 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -853,6 +853,19 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, goto out_free_result; } + /* + * Non-standard SCSI targets may set the PDT to 0x1f (unknown or + * no device type) instead of using the Peripheral Qualifier to + * indicate that no LUN is present. For example, USB UFI does this. + */ + if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) { + SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + "scsi scan: peripheral device type" + " of 31, no device added\n")); + res = SCSI_SCAN_TARGET_PRESENT; + goto out_free_result; + } + res = scsi_add_lun(sdev, result, &bflags); if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { -- cgit v1.2.3 From ffedb4522571ac170f941678d138a31bc0884ab4 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 23 Feb 2006 14:27:18 -0600 Subject: [SCSI] fix scsi process problems and clean up the target reap issues In order to use the new execute_in_process_context() API, you have to provide it with the work storage, which I do in SCSI in scsi_device and scsi_target, but which also means that we can no longer queue up the target reaps, so instead I moved the target to a state model which allows target_alloc to detect if we've received a dying target and wait for it to be gone. Hopefully, this should also solve the target namespace race. Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 49 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 94b86d5b1469..84f01fd0c8fd 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -349,6 +349,8 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, starget->channel = channel; INIT_LIST_HEAD(&starget->siblings); INIT_LIST_HEAD(&starget->devices); + starget->state = STARGET_RUNNING; + retry: spin_lock_irqsave(shost->host_lock, flags); found_target = __scsi_find_target(parent, channel, id); @@ -381,8 +383,15 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, found_target->reap_ref++; spin_unlock_irqrestore(shost->host_lock, flags); put_device(parent); - kfree(starget); - return found_target; + if (found_target->state != STARGET_DEL) { + kfree(starget); + return found_target; + } + /* Unfortunately, we found a dying target; need to + * wait until it's dead before we can get a new one */ + put_device(&found_target->dev); + flush_scheduled_work(); + goto retry; } static void scsi_target_reap_usercontext(void *data) @@ -391,21 +400,13 @@ static void scsi_target_reap_usercontext(void *data) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; + transport_remove_device(&starget->dev); + device_del(&starget->dev); + transport_destroy_device(&starget->dev); spin_lock_irqsave(shost->host_lock, flags); - - if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { - list_del_init(&starget->siblings); - spin_unlock_irqrestore(shost->host_lock, flags); - transport_remove_device(&starget->dev); - device_del(&starget->dev); - transport_destroy_device(&starget->dev); - put_device(&starget->dev); - return; - - } + list_del_init(&starget->siblings); spin_unlock_irqrestore(shost->host_lock, flags); - - return; + put_device(&starget->dev); } /** @@ -419,7 +420,23 @@ static void scsi_target_reap_usercontext(void *data) */ void scsi_target_reap(struct scsi_target *starget) { - scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { + BUG_ON(starget->state == STARGET_DEL); + starget->state = STARGET_DEL; + spin_unlock_irqrestore(shost->host_lock, flags); + execute_in_process_context(scsi_target_reap_usercontext, + starget, &starget->ew); + return; + + } + spin_unlock_irqrestore(shost->host_lock, flags); + + return; } /** -- cgit v1.2.3 From 32f95792500794a0a7cce266b7dafb2bee323bf8 Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 22 Feb 2006 14:28:24 -0600 Subject: [SCSI] scsi: Handle device_add failure in scsi_alloc_target Fixes scsi to handle device_add failure in scsi_alloc_target. Without this patch, if this call were to fail, we can oops when we free the target. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 84f01fd0c8fd..be14f9d82fde 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -332,6 +332,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, + shost->transportt->target_size; struct scsi_target *starget; struct scsi_target *found_target; + int error; starget = kzalloc(size, GFP_KERNEL); if (!starget) { @@ -361,10 +362,20 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, spin_unlock_irqrestore(shost->host_lock, flags); /* allocate and add */ transport_setup_device(dev); - device_add(dev); + error = device_add(dev); + if (error) { + dev_err(dev, "target device_add failed, error %d\n", error); + spin_lock_irqsave(shost->host_lock, flags); + list_del_init(&starget->siblings); + spin_unlock_irqrestore(shost->host_lock, flags); + transport_destroy_device(dev); + put_device(parent); + kfree(starget); + return NULL; + } transport_add_device(dev); if (shost->hostt->target_alloc) { - int error = shost->hostt->target_alloc(starget); + error = shost->hostt->target_alloc(starget); if(error) { dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); -- cgit v1.2.3 From 93f56089898a1b27fc0c89b5c1c748291353f679 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 9 Mar 2006 10:21:27 -0500 Subject: [SCSI] fix two leaks in scsi_alloc_sdev failure paths If the scsi_alloc_queue or the slave_alloc calls in scsi_alloc_device fail, we forget to release the locally allocated sdev on the failure path. Coverity #609 Signed-off-by: Dave Jones Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index be14f9d82fde..5d4ca87af3df 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, /* release fn is set up in scsi_sysfs_device_initialise, so * have to free and put manually here */ put_device(&starget->dev); + kfree(sdev); goto out; } -- cgit v1.2.3 From a50a5e3792a6c65f95dab547dba45608bd193404 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Tue, 14 Mar 2006 11:18:46 -0800 Subject: [SCSI] scsi: move target_destroy call This patch moves the calling of target_destroy next to the list_del. This closed a race being seen while doing a device add on the aic7xxx. Signed-off-by: Mike Anderson Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 9cd4404cf9ab..f14945996ede 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -288,10 +288,7 @@ static void scsi_target_dev_release(struct device *dev) { struct device *parent = dev->parent; struct scsi_target *starget = to_scsi_target(dev); - struct Scsi_Host *shost = dev_to_shost(parent); - if (shost->hostt->target_destroy) - shost->hostt->target_destroy(starget); kfree(starget); put_device(parent); } @@ -416,6 +413,8 @@ static void scsi_target_reap_usercontext(void *data) device_del(&starget->dev); transport_destroy_device(&starget->dev); spin_lock_irqsave(shost->host_lock, flags); + if (shost->hostt->target_destroy) + shost->hostt->target_destroy(starget); list_del_init(&starget->siblings); spin_unlock_irqrestore(shost->host_lock, flags); put_device(&starget->dev); -- cgit v1.2.3