2.6.21-rc4-mm1 + 4 hotfixes -- BUG: unable to handle kernel paging request at virtual address 6b6b6ceb -- EIP is at module_put+0x7/0x1f
Subsystems (2)
It looks like the cpuidle patches are doing incorrect things with their kobject protocol.
Begin forwarded message:
Date: Thu, 22 Mar 2007 09:24:38 -0700
From: "Miles Lane" <[email protected]>
To: "Andrew Morton" <[email protected]>
Cc: LKML <[email protected]>, [email protected]
Subject: Re: 2.6.21-rc4-mm1 + 4 hotfixes -- BUG: unable to handle kernel paging request at virtual address 6b6b6ceb -- EIP is at module_put+0x7/0x1f
I cannot reproduce the BUG with your ml.bz2 patch applied. I am seeing this with both 2.6.21-rc4-mm1 + hotfixes, and with 2.6.21-rc4 + ml.bz2:
Mar 22 09:10:35 FractalPath kernel: ACPI: CPU0 (power states: C1[C1] C2[C2] C3[C3]) Mar 22 09:10:35 FractalPath kernel: The kobject at, or inside per_cpu__cpuidle_devices+0x40/0x558 is not dynamically allocated. Mar 22 09:10:35 FractalPath kernel: The kobject at, or inside per_cpu__cpuidle_devices+0xd4/0x558 is not dynamically allocated. Mar 22 09:10:35 FractalPath kernel: The kobject at, or inside per_cpu__cpuidle_devices+0x168/0x558 is not dynamically allocated. Mar 22 09:10:35 FractalPath kernel: cpuidle: using driver acpi_idle
Not sure if this is a problem. Also, the first time I booted the ml.bz2 build, it hung. I don't have netconsole or a serial debugging system set up, so I have no idea what the problem was. The second boot, ipw2200 loaded with no errors, but NetworkManager wouldn't connect until I removed and reinserted the module.
All the best,
Miles
Quoted 3 lines · Andrew Morton
It looks like the cpuidle patches are doing incorrect things with their kobject protocol.
Looks the goal to force kobject to be allocated dynamically is to release the memory of the kobject. But in the cpuidle case, we don't want to free the memory as it might be used soon. I saw a lot of similar staff too, like 'cpu_devices' in arch/i386/kernel/topology.c.
Thanks,
Shaohua
Quoted 42 lines
Begin forwarded message:
Date: Thu, 22 Mar 2007 09:24:38 -0700
From: "Miles Lane" <[email protected]>
To: "Andrew Morton" <[email protected]>
Cc: LKML <[email protected]>, [email protected]
Subject: Re: 2.6.21-rc4-mm1 + 4 hotfixes -- BUG: unable to handle kernel paging request at virtual address6b6b6ceb-- EIP is atmodule_put+0x7/0x1fI cannot reproduce the BUG with your ml.bz2 patch applied. I am seeing this with both 2.6.21-rc4-mm1 + hotfixes, and with 2.6.21-rc4 + ml.bz2:
Mar 22 09:10:35 FractalPath kernel: ACPI: CPU0 (power states: C1[C1] C2[C2] C3[C3]) Mar 22 09:10:35 FractalPath kernel: The kobject at, or inside per_cpu__cpuidle_devices+0x40/0x558 is not dynamically allocated. Mar 22 09:10:35 FractalPath kernel: The kobject at, or inside per_cpu__cpuidle_devices+0xd4/0x558 is not dynamically allocated. Mar 22 09:10:35 FractalPath kernel: The kobject at, or inside per_cpu__cpuidle_devices+0x168/0x558 is not dynamically allocated. Mar 22 09:10:35 FractalPath kernel: cpuidle: using driver acpi_idleNot sure if this is a problem. Also, the first time I booted the ml.bz2
build, it hung. I don't have netconsole or a serial debugging system set up, so I have no idea what the problem was. The second boot, ipw2200 loaded with no errors, but NetworkManager wouldn't connect until I removed and reinserted the module.All the best,
Miles
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 7 lines · Shaohua Li
Quoted 3 lines · Andrew Morton
It looks like the cpuidle patches are doing incorrect things with their kobject protocol.
Looks the goal to force kobject to be allocated dynamically is to release the memory of the kobject. But in the cpuidle case, we don't want to free the memory as it might be used soon.
What do you mean "used soon"? Is this a time critical thing?
Quoted 2 lines
I saw a lot of similar staff too, like '
cpu_devices' inarch/i386/kernel/topology.c.
The point is that kobjects should be created dynamically as they can be referenced by different threads at different times, so you need to let it manage the reference counting logic for you. Don't create them statically, it's almost always wrong.
Note, one valid use of static kobject is in struct bus_type and in some class definitions.
So this should probably be fixed.
thanks,
greg k-h
Quoted 19 lines · Greg KH
Quoted 7 lines · Shaohua Li
Quoted 3 lines · Andrew Morton
It looks like the cpuidle patches are doing incorrect things with their kobject protocol.
Looks the goal to force kobject to be allocated dynamically is to release the memory of the kobject. But in the cpuidle case, we don't want to free the memory as it might be used soon.
What do you mean "used soon"? Is this a time critical thing?
Quoted 2 lines
I saw a lot of similar staff too, like '
cpu_devices' inarch/i386/kernel/topology.c.The point is that kobjects should be created dynamically as they can be referenced by different threads at different times, so you need to let it manage the reference counting logic for you. Don't create them statically, it's almost always wrong.
Quoted 4 lines
Note, one valid use of static kobject is in struct
bus_typeand in some class definitions.So this should probably be fixed.
Ok, below patch should fix the issue.
drivers/acpi/processor_idle.c +1 -1
@@ -623,7 +623,7 @@ int acpi_processor_cst_has_changed(strucreturn -ENODEV ;acpi_processor_get_power_info (pr); -return cpuidle_force_redetect (&per_cpu (cpuidle_devices, pr->id)); +return cpuidle_force_redetect (per_cpu (cpuidle_devices, pr->id)); }/* proc interface */
drivers/cpuidle/cpuidle.c +17 -4
@@ -18,7 +18,7 @@#include "cpuidle.h" -DEFINE_PER_CPU(struct cpuidle_device, cpuidle_devices); +DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);EXPORT_PER_CPU_SYMBOL_GPL (cpuidle_devices);DEFINE_MUTEX (cpuidle_lock);
@@ -34,7 +34,7 @@ static void (*pm_idle_old)(void);*/ static void cpuidle_idle_call (void ) { -struct cpuidle_device *dev = &__get_cpu_var (cpuidle_devices); +struct cpuidle_device *dev =__get_cpu_var (cpuidle_devices);struct cpuidle_state *target_state;int next_state;
@@ -117,7 +117,7 @@ static int cpuidle_add_device(struct sysint cpu = sys_dev->id;struct cpuidle_device *dev; - dev = &per_cpu (cpuidle_devices, cpu); + dev =per_cpu (cpuidle_devices, cpu);mutex_lock (&cpuidle_lock);if (cpu_is_offline (cpu)) {
@@ -125,6 +125,16 @@ static int cpuidle_add_device(struct sysreturn 0 ; } +if (!dev) { + dev =kzalloc (sizeof (struct cpuidle_device ),GFP_KERNEL ); +if (!dev) { +mutex_unlock (&cpuidle_lock); +return -ENOMEM ; + } +init_completion (&dev->kobj_unregister); +per_cpu (cpuidle_devices, cpu) = dev; + } +if (dev->status &CPUIDLE_STATUS_DETECTED ) {mutex_unlock (&cpuidle_lock);return 0 ;
@@ -153,7 +163,7 @@ static int __cpuidle_remove_device(struc {struct cpuidle_device *dev; - dev = &per_cpu (cpuidle_devices, sys_dev->id); + dev =per_cpu (cpuidle_devices, sys_dev->id);if (!(dev->status &CPUIDLE_STATUS_DETECTED )) {return 0 ;
@@ -166,6 +176,9 @@ static int __cpuidle_remove_device(struccpuidle_detach_driver (dev);cpuidle_remove_sysfs (sys_dev);list_del (&dev->device_list); +wait_for_completion (&dev->kobj_unregister); +per_cpu (cpuidle_devices, sys_dev->id) =NULL ; +kfree (dev);return 0 ; }
drivers/cpuidle/sysfs.c +16 -2
@@ -210,8 +210,16 @@ static struct sysfs_ops cpuidle_sysfs_op .store = cpuidle_store, }; +static void cpuidle_sysfs_release (struct kobject *kobj) +{ +struct cpuidle_device *dev =kobj_to_cpuidledev (kobj); + +complete (&dev->kobj_unregister); +} +static struct kobj_type ktype_cpuidle = { .sysfs_ops = &cpuidle_sysfs_ops, + .release = cpuidle_sysfs_release, };struct cpuidle_state_attr {
@@ -265,9 +273,15 @@ static struct sysfs_ops cpuidle_state_sy .show = cpuidle_state_show, }; +static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +} +static struct kobj_type ktype_state_cpuidle = { .sysfs_ops = &cpuidle_state_sysfs_ops, .default_attrs = cpuidle_state_default_attrs, + .release = cpuidle_state_sysfs_release, };/**
@@ -319,7 +333,7 @@ int cpuidle_add_sysfs(struct sys_deviceint cpu = sysdev->id;struct cpuidle_device *dev; - dev = &per_cpu (cpuidle_devices, cpu); + dev =per_cpu (cpuidle_devices, cpu); dev->kobj.parent = &sysdev->kobj; dev->kobj.ktype = &ktype_cpuidle;kobject_set_name (&dev->kobj,"%s" ,"cpuidle" );
@@ -335,6 +349,6 @@ void cpuidle_remove_sysfs(struct sys_devint cpu = sysdev->id;struct cpuidle_device *dev; - dev = &per_cpu (cpuidle_devices, cpu); + dev =per_cpu (cpuidle_devices, cpu);kobject_unregister (&dev->kobj); }
include/linux/cpuidle.h +1 -3
@@ -89,9 +89,7 @@ struct cpuidle_device {void *governor_data; }; -#define to_cpuidle_device (n) container_of(n, struct cpuidle_device, kobj); - -DECLARE_PER_CPU(struct cpuidle_device, cpuidle_devices); +DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);/* Device Status Flags */ #define CPUIDLE_STATUS_DETECTED (0x1)
drivers/cpuidle/sysfs.c static struct sysfs_ops cpuidle_state_sy · line 279
Quoted 4 lines · Shaohua Li
drivers/cpuidle/sysfs.c +4
-0+static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +}
NO!!!
Do people think that I add warnings to the kernel so that people can just work around them by passing empty functions to the driver core?
Sometimes I wonder why I even try...
Please fix this code, it is wrong.
greg k-h
Quoted 7 lines · On Tue, 27 Mar 2007 21:19:58 -0700 Greg KH <[email protected]> wrote:
drivers/cpuidle/sysfs.c static struct sysfs_ops cpuidle_state_sy · line 279
Quoted 4 lines · Shaohua Li
drivers/cpuidle/sysfs.c +4
-0+static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +}NO!!!
heh. This happens rather a lot.
Quoted 7 lines
Do people think that I add warnings to the kernel so that people can just work around them by passing empty functions to the driver core?
Sometimes I wonder why I even try...
Please fix this code, it is wrong.
Is it documented anywhere? I always forget the reasoning so I have to cc you each time I see it happening.
Quoted 15 lines · Andrew Morton
Quoted 7 lines · On Tue, 27 Mar 2007 21:19:58 -0700 Greg KH <[email protected]> wrote:
drivers/cpuidle/sysfs.c static struct sysfs_ops cpuidle_state_sy · line 279
Quoted 4 lines · Shaohua Li
drivers/cpuidle/sysfs.c +4
-0+static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +}NO!!!
heh. This happens rather a lot.
Quoted 3 lines
Do people think that I add warnings to the kernel so that people can just work around them by passing empty functions to the driver core?
Quoted 7 lines
Quoted 4 lines
Sometimes I wonder why I even try...
Please fix this code, it is wrong.
Is it documented anywhere? I always forget the reasoning so I have to cc you each time I see it happening.
The fact that the kernel itself spits out a message saying:
"Device '%s' does not have a release() function, it is broken and must be fixed."
isn't enough? What should I change it to, something like this:
"Device '%s' does not have a release() function, it is broken and must be fixed, and if you just provide an empty function to remove this warning, rabid echidnas will track you down and puncture your spleen."
The reason for this is that the device is a reference counted object, and you have to free the memory in the release function, otherwise you can easily be accessing memory that is freed already.
Now note, this patch used a completion function to wait for the object to be destroyed, which isn't the nicest. But if you are going to do this, do it in the release function, like the code did a bit earlier.
And if you are doing this because you have two kobjects in the same structure, well, your code is so messed up beyond belief that it needs to be fixed. And yes scsi developers, I'm pointing at you...
So, where do I need to put this information so that people stop trying to be smarter than the kernel...
ugh.
greg k-h
Quoted 2 lines · On Tue, 27 Mar 2007 21:51:24 -0700 Greg KH <[email protected]> wrote:
So, where do I need to put this information so that people stop trying to be smarter than the kernel...
Documentation/driver-model/driver.txt?
And a pointer to a sample properly-written driver would help.
Quoted 8 lines · Andrew Morton
Quoted 2 lines · On Tue, 27 Mar 2007 21:51:24 -0700 Greg KH <[email protected]> wrote:
So, where do I need to put this information so that people stop trying to be smarter than the kernel...
Documentation/driver-model/driver.txt?And a pointer to a sample properly-written driver would help.
Well, this is not something that a driver will ever have to do, it's only people writing a driver subsystem, or messing with sysfs in "different" ways.
But yes, I will do that, it is really needed...
thanks,
greg k-h
Quoted 40 lines · Greg KH
Quoted 15 lines · Andrew Morton
Quoted 7 lines · On Tue, 27 Mar 2007 21:19:58 -0700 Greg KH <[email protected]> wrote:
drivers/cpuidle/sysfs.c static struct sysfs_ops cpuidle_state_sy · line 279
Quoted 4 lines · Shaohua Li
drivers/cpuidle/sysfs.c +4
-0+static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +}NO!!!
heh. This happens rather a lot.
Quoted 3 lines
Do people think that I add warnings to the kernel so that people can just work around them by passing empty functions to the driver core?
Quoted 7 lines
Quoted 4 lines
Sometimes I wonder why I even try...
Please fix this code, it is wrong.
Is it documented anywhere? I always forget the reasoning so I have to cc you each time I see it happening.
The fact that the kernel itself spits out a message saying:
"Device '%s' does not have arelease()function, it is broken and must be fixed."isn't enough? What should I change it to, something like this:
"Device '%s' does not have a
release()function, it is broken and must be fixed, and if you just provide an empty function to remove this warning, rabid echidnas will track you down and puncture your spleen."The reason for this is that the device is a reference counted object, and you have to free the memory in the release function, otherwise you can easily be accessing memory that is freed already.
Quoted 7 lines
Now note, this patch used a completion function to wait for the object to be destroyed, which isn't the nicest. But if you are going to do this, do it in the release function, like the code did a bit earlier.
And if you are doing this because you have two kobjects in the same structure, well, your code is so messed up beyond belief that it needs to be fixed. And yes scsi developers, I'm pointing at you...
The two kobjects will be removed in the maintime. As I wait for one object to be destroyed (the two objects are in one structure, and one object's release will free the memory), we haven't the 'using freed memory' issue here. Do we still need a .release for the kobject you pointed out?
Thanks,
Shaohua
Quoted 45 lines · Shaohua Li
Quoted 44 lines · Greg KH
Quoted 15 lines · Andrew Morton
Quoted 7 lines · On Tue, 27 Mar 2007 21:19:58 -0700 Greg KH <[email protected]> wrote:
drivers/cpuidle/sysfs.c static struct sysfs_ops cpuidle_state_sy · line 279
Quoted 4 lines · Shaohua Li
drivers/cpuidle/sysfs.c +4
-0+static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +}NO!!!
heh. This happens rather a lot.
Quoted 3 lines
Do people think that I add warnings to the kernel so that people can just work around them by passing empty functions to the driver core?
Quoted 7 lines
Quoted 4 lines
Sometimes I wonder why I even try...
Please fix this code, it is wrong.
Is it documented anywhere? I always forget the reasoning so I have to cc you each time I see it happening.
The fact that the kernel itself spits out a message saying:
"Device '%s' does not have arelease()function, it is broken and must be fixed."isn't enough? What should I change it to, something like this:
"Device '%s' does not have a
release()function, it is broken and must be fixed, and if you just provide an empty function to remove this warning, rabid echidnas will track you down and puncture your spleen."The reason for this is that the device is a reference counted object, and you have to free the memory in the release function, otherwise you can easily be accessing memory that is freed already.
Now note, this patch used a completion function to wait for the object to be destroyed, which isn't the nicest. But if you are going to do this, do it in the release function, like the code did a bit earlier.
Quoted 8 lines
Quoted 3 lines
And if you are doing this because you have two kobjects in the same structure, well, your code is so messed up beyond belief that it needs to be fixed. And yes scsi developers, I'm pointing at you...
The two kobjects will be removed in the maintime. As I wait for one object to be destroyed (the two objects are in one structure, and one object's release will free the memory), we haven't the 'using freed memory' issue here. Do we still need a .release for the kobject you pointed out?
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
thanks,
greg k-h
Quoted 55 lines · Greg KH
Quoted 45 lines · Shaohua Li
Quoted 44 lines · Greg KH
Quoted 15 lines · Andrew Morton
Quoted 7 lines · On Tue, 27 Mar 2007 21:19:58 -0700 Greg KH <[email protected]> wrote:
drivers/cpuidle/sysfs.c static struct sysfs_ops cpuidle_state_sy · line 279
Quoted 4 lines · Shaohua Li
drivers/cpuidle/sysfs.c +4
-0+static void cpuidle_state_sysfs_release (struct kobject *kobj) +{ +/* Nothing required to do here, just workaround kobject warning*/ +}NO!!!
heh. This happens rather a lot.
Quoted 3 lines
Do people think that I add warnings to the kernel so that people can just work around them by passing empty functions to the driver core?
Quoted 7 lines
Quoted 4 lines
Sometimes I wonder why I even try...
Please fix this code, it is wrong.
Is it documented anywhere? I always forget the reasoning so I have to cc you each time I see it happening.
The fact that the kernel itself spits out a message saying:
"Device '%s' does not have arelease()function, it is broken and must be fixed."isn't enough? What should I change it to, something like this:
"Device '%s' does not have a
release()function, it is broken and must be fixed, and if you just provide an empty function to remove this warning, rabid echidnas will track you down and puncture your spleen."The reason for this is that the device is a reference counted object, and you have to free the memory in the release function, otherwise you can easily be accessing memory that is freed already.
Now note, this patch used a completion function to wait for the object to be destroyed, which isn't the nicest. But if you are going to do this, do it in the release function, like the code did a bit earlier.
Quoted 8 lines
Quoted 3 lines
And if you are doing this because you have two kobjects in the same structure, well, your code is so messed up beyond belief that it needs to be fixed. And yes scsi developers, I'm pointing at you...
The two kobjects will be removed in the maintime. As I wait for one object to be destroyed (the two objects are in one structure, and one object's release will free the memory), we haven't the 'using freed memory' issue here. Do we still need a .release for the kobject you pointed out?
Quoted 7 lines
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
struct foo {
kobject kobja;
}struct bar {
struct foo foo[];
kobject kobjb
}kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Thanks,
Shaohua
Quoted 9 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Quoted 8 lines
Our data structure is something like below:
struct foo { kobject kobja; }struct bar { struct foo foo[];
Ick, don't do that...
Quoted 7 lines
kobject kobjb
}kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
thanks,
greg k-h
Quoted 12 lines · Greg KH
Quoted 11 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
Quoted 8 lines
Quoted 6 lines
struct foo { kobject kobja; }struct bar { struct foo foo[];Ick, don't do that...
why?
Quoted 10 lines
Quoted 7 lines
kobject kobjb
}kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
I still didn't get the reason why we couldn't do this in the way of my patch. As I said, there isn't risk to use 'freed memory'. I can make the 'struct foo' a pointer, but this will mess the cpuidle driver.
Thanks,
Shaohua
Quoted 17 lines · Shaohua Li
Quoted 16 lines · Greg KH
Quoted 15 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
struct foo { kobject kobja; }
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines
struct bar { struct foo foo[];Ick, don't do that...
why?
Greg, can you share why don't do that? Or I can assume the patch is ok to push to len?
Quoted 16 lines
Quoted 10 lines
Quoted 7 lines
kobject kobjb
}kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
I still didn't get the reason why we couldn't do this in the way of my patch. As I said, there isn't risk to use 'freed memory'. I can make the 'struct foo' a pointer, but this will mess the cpuidle driver.
Thanks,
Shaohua
Quoted 17 lines · Shaohua Li
Quoted 16 lines · Greg KH
Quoted 15 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
struct foo { kobject kobja; }
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
struct bar { struct foo foo[];Ick, don't do that...
why?
Quoted 1 line
Quoted 1 line
kobject kobjb
Because you have multiple kobjects in the same object.
It's just that simple, the lifetime rules for such a thing is almost impossible to track properly. Don't do it!
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
}
kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Quoted 5 lines
Quoted 2 lines
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
I still didn't get the reason why we couldn't do this in the way of my patch. As I said, there isn't risk to use 'freed memory'. I can make the 'struct foo' a pointer, but this will mess the cpuidle driver.
Again, the main point is you can not have more than one reference count for the same structure. It just does not work at all.
So please, fix the code, it is broken.
And yes, I know of other places in the kernel (scsi stack...) that violate this, but that only means that they are wrong, not that it is an excuse for you to do it also.
thanks,
greg k-h
Quoted 43 lines · Greg KH
Quoted 17 lines · Shaohua Li
Quoted 16 lines · Greg KH
Quoted 15 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
struct foo { kobject kobja; }Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
struct bar { struct foo foo[];Ick, don't do that...
why?
Quoted 1 line
Quoted 1 line
kobject kobjb
Because you have multiple kobjects in the same object.
It's just that simple, the lifetime rules for such a thing is almost impossible to track properly. Don't do it!
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
}
kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Quoted 5 lines
Quoted 2 lines
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
I still didn't get the reason why we couldn't do this in the way of my patch. As I said, there isn't risk to use 'freed memory'. I can make the 'struct foo' a pointer, but this will mess the cpuidle driver.
Quoted 8 lines
Again, the main point is you can not have more than one reference count for the same structure. It just does not work at all.
So please, fix the code, it is broken.
And yes, I know of other places in the kernel (scsi stack...) that violate this, but that only means that they are wrong, not that it is an excuse for you to do it also.
We don't use the kobject to track the reference count. But anyway, below patch should make you happy.
drivers/acpi/processor_idle.c +1 -1
@@ -623,7 +623,7 @@ int acpi_processor_cst_has_changed(strucreturn -ENODEV ;acpi_processor_get_power_info (pr); -return cpuidle_force_redetect (&per_cpu (cpuidle_devices, pr->id)); +return cpuidle_force_redetect (per_cpu (cpuidle_devices, pr->id)); }/* proc interface */
drivers/cpuidle/cpuidle.c +17 -4
@@ -18,7 +18,7 @@#include "cpuidle.h" -DEFINE_PER_CPU(struct cpuidle_device, cpuidle_devices); +DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);EXPORT_PER_CPU_SYMBOL_GPL (cpuidle_devices);DEFINE_MUTEX (cpuidle_lock);
@@ -34,7 +34,7 @@ static void (*pm_idle_old)(void);*/ static void cpuidle_idle_call (void ) { -struct cpuidle_device *dev = &__get_cpu_var (cpuidle_devices); +struct cpuidle_device *dev =__get_cpu_var (cpuidle_devices);struct cpuidle_state *target_state;int next_state;
@@ -117,7 +117,7 @@ static int cpuidle_add_device(struct sysint cpu = sys_dev->id;struct cpuidle_device *dev; - dev = &per_cpu (cpuidle_devices, cpu); + dev =per_cpu (cpuidle_devices, cpu);mutex_lock (&cpuidle_lock);if (cpu_is_offline (cpu)) {
@@ -125,6 +125,16 @@ static int cpuidle_add_device(struct sysreturn 0 ; } +if (!dev) { + dev =kzalloc (sizeof (struct cpuidle_device ),GFP_KERNEL ); +if (!dev) { +mutex_unlock (&cpuidle_lock); +return -ENOMEM ; + } +init_completion (&dev->kobj_unregister); +per_cpu (cpuidle_devices, cpu) = dev; + } +if (dev->status &CPUIDLE_STATUS_DETECTED ) {mutex_unlock (&cpuidle_lock);return 0 ;
@@ -153,7 +163,7 @@ static int __cpuidle_remove_device(struc {struct cpuidle_device *dev; - dev = &per_cpu (cpuidle_devices, sys_dev->id); + dev =per_cpu (cpuidle_devices, sys_dev->id);if (!(dev->status &CPUIDLE_STATUS_DETECTED )) {return 0 ;
@@ -166,6 +176,9 @@ static int __cpuidle_remove_device(struccpuidle_detach_driver (dev);cpuidle_remove_sysfs (sys_dev);list_del (&dev->device_list); +wait_for_completion (&dev->kobj_unregister); +per_cpu (cpuidle_devices, sys_dev->id) =NULL ; +kfree (dev);return 0 ; }
drivers/cpuidle/sysfs.c +45 -12
115 lines not on this page · raw message
include/linux/cpuidle.h +8 -5
@@ -41,8 +41,6 @@ struct cpuidle_state {int (*enter) (struct cpuidle_device *dev,struct cpuidle_state *state); - -struct kobject kobj; };/* Idle State Flags */
@@ -74,6 +72,12 @@ cpuidle_set_statedata(struct cpuidle_sta state->driver_data = data; } +struct cpuidle_state_kobj { +struct cpuidle_state *state; +struct completion kobj_unregister; +struct kobject kobj; +}; +struct cpuidle_device {unsigned int status;int cpu;
@@ -81,6 +85,7 @@ struct cpuidle_device {int last_residency;int state_count;struct cpuidle_state states[CPUIDLE_STATE_MAX ]; +struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX ];struct cpuidle_state *last_state;struct list_head device_list;
@@ -89,9 +94,7 @@ struct cpuidle_device {void *governor_data; }; -#define to_cpuidle_device (n) container_of(n, struct cpuidle_device, kobj); - -DECLARE_PER_CPU(struct cpuidle_device, cpuidle_devices); +DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);/* Device Status Flags */ #define CPUIDLE_STATUS_DETECTED (0x1)
Quoted 47 lines · Shaohua Li
Quoted 46 lines · Greg KH
Quoted 17 lines · Shaohua Li
Quoted 16 lines · Greg KH
Quoted 15 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
struct foo { kobject kobja; }Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
struct bar { struct foo foo[];Ick, don't do that...
why?
Quoted 1 line
Quoted 1 line
kobject kobjb
Because you have multiple kobjects in the same object.
It's just that simple, the lifetime rules for such a thing is almost impossible to track properly. Don't do it!
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
}
kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Quoted 5 lines
Quoted 2 lines
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
I still didn't get the reason why we couldn't do this in the way of my patch. As I said, there isn't risk to use 'freed memory'. I can make the 'struct foo' a pointer, but this will mess the cpuidle driver.
Again, the main point is you can not have more than one reference count for the same structure. It just does not work at all.
Quoted 6 lines
Quoted 5 lines
So please, fix the code, it is broken.
And yes, I know of other places in the kernel (scsi stack...) that violate this, but that only means that they are wrong, not that it is an excuse for you to do it also.
We don't use the kobject to track the reference count.
Then what do you use it for?
And it doesn't matter if you use it or not, the reference count _is_ used by the kobject and sysfs code, so you have to be aware of it.
Quoted 1 line
But anyway, below patch should make you happy.
I'm still confused as to why you are creating these "extra" kobjects. What are they used for?
But yes, it is "better" in that you are abiding by the reference count rules properly, although your completion handling seems like it might get into a deadlock, but I'll trust you that it works properly :)
thanks,
greg k-h
Quoted 57 lines · Greg KH
Quoted 47 lines · Shaohua Li
Quoted 46 lines · Greg KH
Quoted 17 lines · Shaohua Li
Quoted 16 lines · Greg KH
Quoted 15 lines · Shaohua Li
Quoted 8 lines · Greg KH
Putting more than one kobject in the same structure is a broken design. How can you control the lifetime rules properly if there are two reference counts for the same structure? It doesn't work.
If you really need something like this, then just use a pointer to a kobject for one of them instead of embedding it. Why do you need two different kobjects here?
Our data structure is something like below:
struct foo { kobject kobja; }Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
struct bar { struct foo foo[];Ick, don't do that...
why?
Quoted 1 line
Quoted 1 line
kobject kobjb
Because you have multiple kobjects in the same object.
It's just that simple, the lifetime rules for such a thing is almost impossible to track properly. Don't do it!
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
}
kobjb's .release will free struct bar. kobjb is the parent of kobja. if you have a reference on kobja, then kobjb can't be released too, right? So we only kobjb provide a .release to free the memory, kobja's .release isn't required.
Quoted 5 lines
Quoted 2 lines
Why not just use the "normal" parent/child relationship with the kobjects like the rest of the kernel does?
I still didn't get the reason why we couldn't do this in the way of my patch. As I said, there isn't risk to use 'freed memory'. I can make the 'struct foo' a pointer, but this will mess the cpuidle driver.
Again, the main point is you can not have more than one reference count for the same structure. It just does not work at all.
Quoted 6 lines
Quoted 5 lines
So please, fix the code, it is broken.
And yes, I know of other places in the kernel (scsi stack...) that violate this, but that only means that they are wrong, not that it is an excuse for you to do it also.
We don't use the kobject to track the reference count.
Then what do you use it for?
Quoted 7 lines
And it doesn't matter if you use it or not, the reference count _is_ used by the kobject and sysfs code, so you have to be aware of it.
Quoted 1 line
But anyway, below patch should make you happy.
I'm still confused as to why you are creating these "extra" kobjects. What are they used for?
It's for each idle state.
Quoted 3 lines
But yes, it is "better" in that you are abiding by the reference count rules properly, although your completion handling seems like it might get into a deadlock, but I'll trust you that it works properly :)
Yes, it works well in my test.
Thanks,
Shaohua
Quoted 5 lines · Shaohua Li
Quoted 3 lines · Greg KH
I'm still confused as to why you are creating these "extra" kobjects. What are they used for?
It's for each idle state.
Where are these states in sysfs? Is this the /sys/devices/system/cpu/cpu0/cache/indexN directories?
thanks,
greg k-h
Quoted 9 lines · Greg KH
Quoted 5 lines · Shaohua Li
Quoted 3 lines · Greg KH
I'm still confused as to why you are creating these "extra" kobjects. What are they used for?
It's for each idle state.
Where are these states in sysfs? Is this the
/sys/devices/system/cpu/cpu0/cache/indexNdirectories?
Similar with cache info, the sysfs is/sys/devices/system/cpu/cpu1/cpuidle/statex
Thanks,
Shaohua