From: Sau Dan Lee <danlee@informatik.uni-freiburg.de>

    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;
 	}

_