Updating the FC transport for the following: - Take a self-reference on the rport. Prior, when the starget was removed, the ref count would hit zero and fc_rport_dev_release was called, which would free the rport. This left corrupt lists, etc... Symptoms of error is oops w/ either: "Badness in kref_get in lib/kref.c:32" "Unable to handle kernel paging request for data at address 0x00000010" from kref_get - Fix fc_rport_create failure path - too many put's on parent - Add commenting to easily track ref taking. -- james s Signed-off-by: James Smart <james.smart@xxxxxxxxxx> diff -upNr a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c --- a/drivers/scsi/scsi_transport_fc.c 2006-06-14 11:37:09.000000000 -0400 +++ b/drivers/scsi/scsi_transport_fc.c 2006-06-14 16:33:55.000000000 -0400 @@ -1077,7 +1077,7 @@ static int fc_target_match(struct attrib static void fc_rport_dev_release(struct device *dev) { struct fc_rport *rport = dev_to_rport(dev); - put_device(dev->parent); + put_device(dev->parent); /* for parent reference */ kfree(rport); } @@ -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, 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); + 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); @@ -1554,6 +1555,9 @@ fc_rport_create(struct Scsi_Host *shost, printk(KERN_ERR "FC Remote Port device_add failed\n"); goto delete_rport; } + + get_device(dev); /* for self-reference */ + transport_add_device(dev); transport_configure_device(dev); @@ -1567,12 +1571,11 @@ fc_rport_create(struct Scsi_Host *shost, delete_rport: transport_destroy_device(dev); - put_device(dev->parent); + put_device(dev->parent); /* for parent reference */ 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); return NULL; } - : send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html