diff options
author | Sergey Senozhatsky <sergey.senozhatsky@gmail.com> | 2011-08-05 18:34:08 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-08-05 22:15:18 -0400 |
commit | 69d94ec6d83d84044252d9ba03f6a8970816e350 (patch) | |
tree | 3749073c792366acba59bede614db2200ef99d08 /drivers/acpi | |
parent | eb03cb02b74df6dd0b653d5f6d976f16a434dfaf (diff) |
Battery: sysfs_remove_battery(): possible circular locking
Commit 9c921c22a7f33397a6774d7fa076db9b6a0fd669
Author: Lan Tianyu <tianyu.lan@intel.com>
ACPI / Battery: Resolve the race condition in the sysfs_remove_battery()
fixed BUG https://bugzilla.kernel.org/show_bug.cgi?id=35642 , but as a side
effect made lockdep unhappy with sysfs_remove_battery():
[14818.477168]
[14818.477170] =======================================================
[14818.477200] [ INFO: possible circular locking dependency detected ]
[14818.477221] 3.1.0-dbg-07865-g1280ea8-dirty #668
[14818.477236] -------------------------------------------------------
[14818.477257] s2ram/1599 is trying to acquire lock:
[14818.477276] (s_active#8){++++.+}, at: [<ffffffff81169147>] sysfs_addrm_finish+0x31/0x5a
[14818.477323]
[14818.477325] but task is already holding lock:
[14818.477350] (&battery->lock){+.+.+.}, at: [<ffffffffa0047278>] sysfs_remove_battery+0x10/0x4b [battery]
[14818.477395]
[14818.477397] which lock already depends on the new lock.
[14818.477399]
[..]
[14818.479121] stack backtrace:
[14818.479148] Pid: 1599, comm: s2ram Not tainted 3.1.0-dbg-07865-g1280ea8-dirty #668
[14818.479175] Call Trace:
[14818.479198] [<ffffffff814828c3>] print_circular_bug+0x293/0x2a4
[14818.479228] [<ffffffff81070cb5>] __lock_acquire+0xfe4/0x164b
[14818.479260] [<ffffffff81169147>] ? sysfs_addrm_finish+0x31/0x5a
[14818.479288] [<ffffffff810718d2>] lock_acquire+0x138/0x1ac
[14818.479316] [<ffffffff81169147>] ? sysfs_addrm_finish+0x31/0x5a
[14818.479345] [<ffffffff81168a79>] sysfs_deactivate+0x9b/0xec
[14818.479373] [<ffffffff81169147>] ? sysfs_addrm_finish+0x31/0x5a
[14818.479405] [<ffffffff81169147>] sysfs_addrm_finish+0x31/0x5a
[14818.479433] [<ffffffff81167bc5>] sysfs_hash_and_remove+0x54/0x77
[14818.479461] [<ffffffff811681b9>] sysfs_remove_file+0x12/0x14
[14818.479488] [<ffffffff81385bf8>] device_remove_file+0x12/0x14
[14818.479516] [<ffffffff81386504>] device_del+0x119/0x17c
[14818.479542] [<ffffffff81386575>] device_unregister+0xe/0x1a
[14818.479570] [<ffffffff813c6ef9>] power_supply_unregister+0x23/0x27
[14818.479601] [<ffffffffa004729c>] sysfs_remove_battery+0x34/0x4b [battery]
[14818.479632] [<ffffffffa004778f>] battery_notify+0x2c/0x3a [battery]
[14818.479662] [<ffffffff8148fe82>] notifier_call_chain+0x74/0xa1
[14818.479692] [<ffffffff810624b4>] __blocking_notifier_call_chain+0x6c/0x89
[14818.479722] [<ffffffff810624e0>] blocking_notifier_call_chain+0xf/0x11
[14818.479751] [<ffffffff8107e40e>] pm_notifier_call_chain+0x15/0x27
[14818.479770] [<ffffffff8107ee1a>] enter_state+0xa7/0xd5
[14818.479782] [<ffffffff8107e341>] state_store+0xaa/0xc0
[14818.479795] [<ffffffff8107e297>] ? pm_async_store+0x45/0x45
[14818.479807] [<ffffffff81248837>] kobj_attr_store+0x17/0x19
[14818.479820] [<ffffffff81167e27>] sysfs_write_file+0x103/0x13f
[14818.479834] [<ffffffff81109037>] vfs_write+0xad/0x13d
[14818.479847] [<ffffffff811092b2>] sys_write+0x45/0x6c
[14818.479860] [<ffffffff81492f92>] system_call_fastpath+0x16/0x1b
This patch introduces separate lock to struct acpi_battery to
grab in sysfs_remove_battery() instead of battery->lock.
So fix by Lan Tianyu is still there, we just grab independent lock.
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Tested-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/battery.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index ffce2f06dd8d..8953b7087091 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -99,6 +99,7 @@ enum { | |||
99 | 99 | ||
100 | struct acpi_battery { | 100 | struct acpi_battery { |
101 | struct mutex lock; | 101 | struct mutex lock; |
102 | struct mutex sysfs_lock; | ||
102 | struct power_supply bat; | 103 | struct power_supply bat; |
103 | struct acpi_device *device; | 104 | struct acpi_device *device; |
104 | struct notifier_block pm_nb; | 105 | struct notifier_block pm_nb; |
@@ -573,16 +574,16 @@ static int sysfs_add_battery(struct acpi_battery *battery) | |||
573 | 574 | ||
574 | static void sysfs_remove_battery(struct acpi_battery *battery) | 575 | static void sysfs_remove_battery(struct acpi_battery *battery) |
575 | { | 576 | { |
576 | mutex_lock(&battery->lock); | 577 | mutex_lock(&battery->sysfs_lock); |
577 | if (!battery->bat.dev) { | 578 | if (!battery->bat.dev) { |
578 | mutex_unlock(&battery->lock); | 579 | mutex_unlock(&battery->sysfs_lock); |
579 | return; | 580 | return; |
580 | } | 581 | } |
581 | 582 | ||
582 | device_remove_file(battery->bat.dev, &alarm_attr); | 583 | device_remove_file(battery->bat.dev, &alarm_attr); |
583 | power_supply_unregister(&battery->bat); | 584 | power_supply_unregister(&battery->bat); |
584 | battery->bat.dev = NULL; | 585 | battery->bat.dev = NULL; |
585 | mutex_unlock(&battery->lock); | 586 | mutex_unlock(&battery->sysfs_lock); |
586 | } | 587 | } |
587 | 588 | ||
588 | /* | 589 | /* |
@@ -982,6 +983,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
982 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); | 983 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); |
983 | device->driver_data = battery; | 984 | device->driver_data = battery; |
984 | mutex_init(&battery->lock); | 985 | mutex_init(&battery->lock); |
986 | mutex_init(&battery->sysfs_lock); | ||
985 | if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, | 987 | if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, |
986 | "_BIX", &handle))) | 988 | "_BIX", &handle))) |
987 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); | 989 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); |
@@ -1010,6 +1012,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
1010 | fail: | 1012 | fail: |
1011 | sysfs_remove_battery(battery); | 1013 | sysfs_remove_battery(battery); |
1012 | mutex_destroy(&battery->lock); | 1014 | mutex_destroy(&battery->lock); |
1015 | mutex_destroy(&battery->sysfs_lock); | ||
1013 | kfree(battery); | 1016 | kfree(battery); |
1014 | return result; | 1017 | return result; |
1015 | } | 1018 | } |
@@ -1027,6 +1030,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
1027 | #endif | 1030 | #endif |
1028 | sysfs_remove_battery(battery); | 1031 | sysfs_remove_battery(battery); |
1029 | mutex_destroy(&battery->lock); | 1032 | mutex_destroy(&battery->lock); |
1033 | mutex_destroy(&battery->sysfs_lock); | ||
1030 | kfree(battery); | 1034 | kfree(battery); |
1031 | return 0; | 1035 | return 0; |
1032 | } | 1036 | } |