From f457a46f179df41b0f6d80dee33b6e629945f276 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 24 Jun 2011 15:11:53 -0500 Subject: [SCSI] iscsi_ibft, be2iscsi, iscsi_boot: fix boot kobj data lifetime management be2iscsi passes the boot functions its phba object which is allocated in the shost, but iscsi_ibft passes in a object allocated for each item to display. The problem is that iscsi_boot_sysfs was managing the lifetime of the object passed in and doing a kfree on release. This causes a double free for be2iscsi which frees the shost in its pci_remove. This patch fixes the problem by adding a release callback which the drivers can call kfree or a put() type of function (needed for be2iscsi which will do a get/put on the shost). Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_boot_sysfs.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/scsi/iscsi_boot_sysfs.c') diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c index 4274ce93d8f2..89700cbca16e 100644 --- a/drivers/scsi/iscsi_boot_sysfs.c +++ b/drivers/scsi/iscsi_boot_sysfs.c @@ -64,7 +64,8 @@ static void iscsi_boot_kobj_release(struct kobject *kobj) struct iscsi_boot_kobj *boot_kobj = container_of(kobj, struct iscsi_boot_kobj, kobj); - kfree(boot_kobj->data); + if (boot_kobj->release) + boot_kobj->release(boot_kobj->data); kfree(boot_kobj); } @@ -305,7 +306,8 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, struct attribute_group *attr_group, const char *name, int index, void *data, ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) + mode_t (*is_visible) (void *data, int type), + void (*release) (void *data)) { struct iscsi_boot_kobj *boot_kobj; @@ -323,6 +325,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, boot_kobj->data = data; boot_kobj->show = show; boot_kobj->is_visible = is_visible; + boot_kobj->release = release; if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { /* @@ -331,7 +334,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, * the boot kobj was not setup and the normal release * path is not being run. */ - boot_kobj->data = NULL; + boot_kobj->release = NULL; kobject_put(&boot_kobj->kobj); return NULL; } @@ -357,6 +360,7 @@ static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj) * @data: driver specific data for target * @show: attr show function * @is_visible: attr visibility function + * @release: release function * * Note: The boot sysfs lib will free the data passed in for the caller * when all refs to the target kobject have been released. @@ -365,10 +369,12 @@ struct iscsi_boot_kobj * iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, void *data, ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) + mode_t (*is_visible) (void *data, int type), + void (*release) (void *data)) { return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, - "target%d", index, data, show, is_visible); + "target%d", index, data, show, is_visible, + release); } EXPORT_SYMBOL_GPL(iscsi_boot_create_target); @@ -379,6 +385,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_target); * @data: driver specific data * @show: attr show function * @is_visible: attr visibility function + * @release: release function * * Note: The boot sysfs lib will free the data passed in for the caller * when all refs to the initiator kobject have been released. @@ -387,12 +394,13 @@ struct iscsi_boot_kobj * iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, void *data, ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) + mode_t (*is_visible) (void *data, int type), + void (*release) (void *data)) { return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_initiator_attr_group, "initiator", index, data, show, - is_visible); + is_visible, release); } EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); @@ -403,6 +411,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); * @data: driver specific data * @show: attr show function * @is_visible: attr visibility function + * @release: release function * * Note: The boot sysfs lib will free the data passed in for the caller * when all refs to the ethernet kobject have been released. @@ -411,12 +420,13 @@ struct iscsi_boot_kobj * iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, void *data, ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) + mode_t (*is_visible) (void *data, int type), + void (*release) (void *data)) { return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_ethernet_attr_group, "ethernet%d", index, data, show, - is_visible); + is_visible, release); } EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); -- cgit v1.2.3