edac: core fix to use dynamic kobject
Static kobjects are not supported in linux kernel. Convert the edac_pci_top_main_kobj from static to dynamic. This avoids the double free of the edac_pci_top_main_kobj.name that we see on module reload of the e752x edac driver (and probably others as well). In addition Greg KH <greg@kroah.com> has pointed out that this code may be cleaned up significantly. I will look at that as a follow-on patch, for now, I just want the minimum fix to get this double-free oops bug squashed... Many thanks to Greg KH for his patience in showing me what the Documentation/kobject.txt already said (oops)... Signed-off-by: Arthur Jones <ajones@riverbed.com> Signed-off-by: Doug Thompson <dougthompson@xmission.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b238e57723
commit
14cc571bb1
|
@ -28,7 +28,7 @@ static int edac_pci_poll_msec = 1000; /* one second workq period */
|
||||||
static atomic_t pci_parity_count = ATOMIC_INIT(0);
|
static atomic_t pci_parity_count = ATOMIC_INIT(0);
|
||||||
static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
|
static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
|
||||||
|
|
||||||
static struct kobject edac_pci_top_main_kobj;
|
static struct kobject *edac_pci_top_main_kobj;
|
||||||
static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
|
static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
|
||||||
|
|
||||||
/* getter functions for the data variables */
|
/* getter functions for the data variables */
|
||||||
|
@ -83,7 +83,7 @@ static void edac_pci_instance_release(struct kobject *kobj)
|
||||||
pci = to_instance(kobj);
|
pci = to_instance(kobj);
|
||||||
|
|
||||||
/* decrement reference count on top main kobj */
|
/* decrement reference count on top main kobj */
|
||||||
kobject_put(&edac_pci_top_main_kobj);
|
kobject_put(edac_pci_top_main_kobj);
|
||||||
|
|
||||||
kfree(pci); /* Free the control struct */
|
kfree(pci); /* Free the control struct */
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
|
||||||
* track the number of PCI instances we have, and thus nest
|
* track the number of PCI instances we have, and thus nest
|
||||||
* properly on keeping the module loaded
|
* properly on keeping the module loaded
|
||||||
*/
|
*/
|
||||||
main_kobj = kobject_get(&edac_pci_top_main_kobj);
|
main_kobj = kobject_get(edac_pci_top_main_kobj);
|
||||||
if (!main_kobj) {
|
if (!main_kobj) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto error_out;
|
goto error_out;
|
||||||
|
@ -174,11 +174,11 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
|
||||||
|
|
||||||
/* And now register this new kobject under the main kobj */
|
/* And now register this new kobject under the main kobj */
|
||||||
err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
|
err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
|
||||||
&edac_pci_top_main_kobj, "pci%d", idx);
|
edac_pci_top_main_kobj, "pci%d", idx);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
debugf2("%s() failed to register instance pci%d\n",
|
debugf2("%s() failed to register instance pci%d\n",
|
||||||
__func__, idx);
|
__func__, idx);
|
||||||
kobject_put(&edac_pci_top_main_kobj);
|
kobject_put(edac_pci_top_main_kobj);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,9 +316,10 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
|
||||||
*/
|
*/
|
||||||
static void edac_pci_release_main_kobj(struct kobject *kobj)
|
static void edac_pci_release_main_kobj(struct kobject *kobj)
|
||||||
{
|
{
|
||||||
|
|
||||||
debugf0("%s() here to module_put(THIS_MODULE)\n", __func__);
|
debugf0("%s() here to module_put(THIS_MODULE)\n", __func__);
|
||||||
|
|
||||||
|
kfree(kobj);
|
||||||
|
|
||||||
/* last reference to top EDAC PCI kobject has been removed,
|
/* last reference to top EDAC PCI kobject has been removed,
|
||||||
* NOW release our ref count on the core module
|
* NOW release our ref count on the core module
|
||||||
*/
|
*/
|
||||||
|
@ -369,8 +370,16 @@ static int edac_pci_main_kobj_setup(void)
|
||||||
goto decrement_count_fail;
|
goto decrement_count_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
|
||||||
|
if (!edac_pci_top_main_kobj) {
|
||||||
|
debugf1("Failed to allocate\n");
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto kzalloc_fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Instanstiate the pci object */
|
/* Instanstiate the pci object */
|
||||||
err = kobject_init_and_add(&edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj,
|
err = kobject_init_and_add(edac_pci_top_main_kobj,
|
||||||
|
&ktype_edac_pci_main_kobj,
|
||||||
&edac_class->kset.kobj, "pci");
|
&edac_class->kset.kobj, "pci");
|
||||||
if (err) {
|
if (err) {
|
||||||
debugf1("Failed to register '.../edac/pci'\n");
|
debugf1("Failed to register '.../edac/pci'\n");
|
||||||
|
@ -381,13 +390,16 @@ static int edac_pci_main_kobj_setup(void)
|
||||||
* for EDAC PCI, then edac_pci_main_kobj_teardown()
|
* for EDAC PCI, then edac_pci_main_kobj_teardown()
|
||||||
* must be used, for resources to be cleaned up properly
|
* must be used, for resources to be cleaned up properly
|
||||||
*/
|
*/
|
||||||
kobject_uevent(&edac_pci_top_main_kobj, KOBJ_ADD);
|
kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD);
|
||||||
debugf1("Registered '.../edac/pci' kobject\n");
|
debugf1("Registered '.../edac/pci' kobject\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Error unwind statck */
|
/* Error unwind statck */
|
||||||
kobject_init_and_add_fail:
|
kobject_init_and_add_fail:
|
||||||
|
kfree(edac_pci_top_main_kobj);
|
||||||
|
|
||||||
|
kzalloc_fail:
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
|
|
||||||
decrement_count_fail:
|
decrement_count_fail:
|
||||||
|
@ -414,7 +426,7 @@ static void edac_pci_main_kobj_teardown(void)
|
||||||
if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
|
if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
|
||||||
debugf0("%s() called kobject_put on main kobj\n",
|
debugf0("%s() called kobject_put on main kobj\n",
|
||||||
__func__);
|
__func__);
|
||||||
kobject_put(&edac_pci_top_main_kobj);
|
kobject_put(edac_pci_top_main_kobj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue