aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian King <brking@us.ibm.com>2006-02-22 14:28:24 -0600
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-02-27 23:38:59 -0600
commit32f95792500794a0a7cce266b7dafb2bee323bf8 (patch)
treef7565bd227ffbb71b72f306de84bb1dca3bd0917
parentffedb4522571ac170f941678d138a31bc0884ab4 (diff)
[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 <brking@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/scsi_scan.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 84f01fd0c8f..be14f9d82fd 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);