Skip to content

Commit

Permalink
[SCSI] fix memory leak in initialization
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Bottomley authored and James Bottomley committed Oct 13, 2009
1 parent 2caa731 commit 37e6ba0
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 5 deletions.
2 changes: 2 additions & 0 deletions drivers/scsi/scsi_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down
7 changes: 2 additions & 5 deletions drivers/scsi/scsi_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 37e6ba0

Please sign in to comment.