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);
}
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;
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)) {
/*
* 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;
}
* @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.
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);
* @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.
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);
* @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.
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);