]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
[SCSI] fix memory leak in initialization
authorJames Bottomley <James.Bottomley@suse.de>
Fri, 2 Oct 2009 18:30:08 +0000 (13:30 -0500)
committerJames Bottomley <James.Bottomley@suse.de>
Tue, 13 Oct 2009 16:33:45 +0000 (11:33 -0500)
The root cause of the problem is the fact that dev_set_name() now
allocates storage instead of using the original array within the kobj.
That means that the SCSI assumption that if you haven't made the
containing object or any sub objects visible, you can just destroy it
(and its component devices) lock stock and barrel becomes false.

Fix this by doing the get of sdev_dev at parent time and thus do an
extra put of it in scsi_destroy_sdev() (and all other destruction
without add paths).

Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c

index c44783801402083b7dbd610df35f8990eb090ef9..0547a7f44d4277768f6c4fc4b407fedd72df39d0 100644 (file)
@@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
 out_device_destroy:
        scsi_device_set_state(sdev, SDEV_DEL);
        transport_destroy_device(&sdev->sdev_gendev);
+       put_device(&sdev->sdev_dev);
        put_device(&sdev->sdev_gendev);
 out:
        if (display_failure_msg)
@@ -957,6 +958,7 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev)
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(&sdev->sdev_gendev);
+       put_device(&sdev->sdev_dev);
        put_device(&sdev->sdev_gendev);
 }
 
index fde54537d715cf185f1d6edef655cee1136c2beb..5c7eb63a19d13732514e0bd3f50ade6ab380c4d5 100644 (file)
@@ -864,10 +864,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                goto clean_device;
        }
 
-       /* take a reference for the sdev_dev; this is
-        * released by the sdev_class .release */
-       get_device(&sdev->sdev_gendev);
-
        /* create queue files, which may be writable, depending on the host */
        if (sdev->host->hostt->change_queue_depth)
                error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
@@ -917,6 +913,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
 
        device_del(&sdev->sdev_gendev);
        transport_destroy_device(&sdev->sdev_gendev);
+       put_device(&sdev->sdev_dev);
        put_device(&sdev->sdev_gendev);
 
        return error;
@@ -1065,7 +1062,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
                     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 
        device_initialize(&sdev->sdev_dev);
-       sdev->sdev_dev.parent = &sdev->sdev_gendev;
+       sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
        sdev->sdev_dev.class = &sdev_class;
        dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d",
                     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);