From: Sau Dan Lee Dan> I've enabled ACPI and boot with "acpi=force". I loaded the Dan> ACPI modules "processor", "ac", "battery" and "button". When Dan> I unload any of these modules, I get an oops. Unloading of Dan> these modules didn't occur in 2.6.5 and 2.6.2. The bug is due to the removal of procfs entries that are non-empty directories. This leads to a failed assertion in the procfs code, which dumps an oops message. (Would this leak to kernel memory leak?) (Why this doesn't happen in 2.6.5 and 2.6.2 is still mysterious to me.) The fix is to remove all entries created by the corresponding ACPI modules before removing a directory in /proc. --- 25-akpm/drivers/acpi/ac.c | 3 +++ 25-akpm/drivers/acpi/battery.c | 7 +++++++ 25-akpm/drivers/acpi/button.c | 10 ++++++++++ 25-akpm/drivers/acpi/ec.c | 6 ++++++ 25-akpm/drivers/acpi/fan.c | 2 ++ 25-akpm/drivers/acpi/power.c | 2 ++ 25-akpm/drivers/acpi/thermal.c | 10 ++++++++++ 7 files changed, 40 insertions(+) diff -puN drivers/acpi/ac.c~acpi-procfs-fix drivers/acpi/ac.c --- 25/drivers/acpi/ac.c~acpi-procfs-fix 2004-05-12 17:08:00.416886960 -0700 +++ 25-akpm/drivers/acpi/ac.c 2004-05-12 17:08:00.428885136 -0700 @@ -185,6 +185,9 @@ acpi_ac_remove_fs ( ACPI_FUNCTION_TRACE("acpi_ac_remove_fs"); if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_AC_FILE_STATE, + acpi_device_dir(device)); + remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); acpi_device_dir(device) = NULL; } diff -puN drivers/acpi/battery.c~acpi-procfs-fix drivers/acpi/battery.c --- 25/drivers/acpi/battery.c~acpi-procfs-fix 2004-05-12 17:08:00.417886808 -0700 +++ 25-akpm/drivers/acpi/battery.c 2004-05-12 17:08:00.428885136 -0700 @@ -679,6 +679,13 @@ acpi_battery_remove_fs ( ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_BATTERY_FILE_ALARM, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BATTERY_FILE_STATUS, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BATTERY_FILE_INFO, + acpi_device_dir(device)); + remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); acpi_device_dir(device) = NULL; } diff -puN drivers/acpi/button.c~acpi-procfs-fix drivers/acpi/button.c --- 25/drivers/acpi/button.c~acpi-procfs-fix 2004-05-12 17:08:00.419886504 -0700 +++ 25-akpm/drivers/acpi/button.c 2004-05-12 17:08:00.429884984 -0700 @@ -241,6 +241,16 @@ acpi_button_remove_fs ( button = acpi_driver_data(device); if (acpi_device_dir(device)) { + if (button->type == ACPI_BUTTON_TYPE_LID) + remove_proc_entry(ACPI_BUTTON_FILE_STATE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BUTTON_FILE_INFO, + acpi_device_dir(device)); + + remove_proc_entry(acpi_device_bid(device), + acpi_device_dir(device)->parent); + + switch (button->type) { case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWERF: diff -puN drivers/acpi/ec.c~acpi-procfs-fix drivers/acpi/ec.c --- 25/drivers/acpi/ec.c~acpi-procfs-fix 2004-05-12 17:08:00.420886352 -0700 +++ 25-akpm/drivers/acpi/ec.c 2004-05-12 17:08:00.430884832 -0700 @@ -548,6 +548,12 @@ acpi_ec_remove_fs ( { ACPI_FUNCTION_TRACE("acpi_ec_remove_fs"); + if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device)); + remove_proc_entry(acpi_device_bid(device), acpi_ec_dir); + acpi_device_dir(device) = NULL; + } + return_VALUE(0); } diff -puN drivers/acpi/fan.c~acpi-procfs-fix drivers/acpi/fan.c --- 25/drivers/acpi/fan.c~acpi-procfs-fix 2004-05-12 17:08:00.421886200 -0700 +++ 25-akpm/drivers/acpi/fan.c 2004-05-12 17:08:00.430884832 -0700 @@ -185,6 +185,8 @@ acpi_fan_remove_fs ( ACPI_FUNCTION_TRACE("acpi_fan_remove_fs"); if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_FAN_FILE_STATE, + acpi_device_dir(device)); remove_proc_entry(acpi_device_bid(device), acpi_fan_dir); acpi_device_dir(device) = NULL; } diff -puN drivers/acpi/power.c~acpi-procfs-fix drivers/acpi/power.c --- 25/drivers/acpi/power.c~acpi-procfs-fix 2004-05-12 17:08:00.423885896 -0700 +++ 25-akpm/drivers/acpi/power.c 2004-05-12 17:08:00.431884680 -0700 @@ -482,6 +482,8 @@ acpi_power_remove_fs ( ACPI_FUNCTION_TRACE("acpi_power_remove_fs"); if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_POWER_FILE_STATUS, + acpi_device_dir(device)); remove_proc_entry(acpi_device_bid(device), acpi_power_dir); acpi_device_dir(device) = NULL; } diff -puN drivers/acpi/thermal.c~acpi-procfs-fix drivers/acpi/thermal.c --- 25/drivers/acpi/thermal.c~acpi-procfs-fix 2004-05-12 17:08:00.424885744 -0700 +++ 25-akpm/drivers/acpi/thermal.c 2004-05-12 17:08:00.432884528 -0700 @@ -1139,6 +1139,16 @@ acpi_thermal_remove_fs ( ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs"); if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, + acpi_device_dir(device)); + remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, + acpi_device_dir(device)); + remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_THERMAL_FILE_STATE, + acpi_device_dir(device)); remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); acpi_device_dir(device) = NULL; } _