summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2006-06-26 14:19:59 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-27 11:01:46 -0500
commit3bdad7bd253f17ead00b4af2e82f84e9522c95ac (patch)
tree2f25e9ec91e76a19ceb939552ef21ee9713fb4b5
parent1c9e16e47a22c61d99aabb1c154e5106ddbf3575 (diff)
[SCSI] fc transport: bug fix: correct references
Original post was incorrect as it didn't realize that we already had a self-referenc due to device_initialize(), and we were really only missing the put on our own reference. This was hidden by the other bug which had the midlayer reusing stargets after they were already free, which was doing too many puts on our rport. Updating FC transport for: - Add put in fc_rport_final_delete(), to release the rport. Prior, we were leaving the rport with a reference, thus the shost with references, etc. If the driver was unloaded, shosts and rports remained, along with work threads, etc - Fix fc_rport_create failure path - too many put's on parent - Add commenting to easily track ref taking. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/scsi_transport_fc.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index df6263dfd791..b03aa85108e5 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1476,7 +1476,8 @@ fc_rport_final_delete(void *data)
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
- put_device(&shost->shost_gendev);
+ put_device(&shost->shost_gendev); /* for fc_host->rport list */
+ put_device(dev); /* for self-reference */
}
@@ -1537,13 +1538,13 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
else
rport->scsi_target_id = -1;
list_add_tail(&rport->peers, &fc_host->rports);
- get_device(&shost->shost_gendev);
+ get_device(&shost->shost_gendev); /* for fc_host->rport list */
spin_unlock_irqrestore(shost->host_lock, flags);
dev = &rport->dev;
- device_initialize(dev);
- dev->parent = get_device(&shost->shost_gendev);
+ device_initialize(dev); /* takes self reference */
+ dev->parent = get_device(&shost->shost_gendev); /* parent reference */
dev->release = fc_rport_dev_release;
sprintf(dev->bus_id, "rport-%d:%d-%d",
shost->host_no, channel, rport->number);
@@ -1567,10 +1568,9 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
delete_rport:
transport_destroy_device(dev);
- put_device(dev->parent);
spin_lock_irqsave(shost->host_lock, flags);
list_del(&rport->peers);
- put_device(&shost->shost_gendev);
+ put_device(&shost->shost_gendev); /* for fc_host->rport list */
spin_unlock_irqrestore(shost->host_lock, flags);
put_device(dev->parent);
kfree(rport);