diff options
author | Wen Congyang <wency@cn.fujitsu.com> | 2012-11-15 20:06:06 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2012-11-15 20:06:06 -0500 |
commit | 386e52b95550db87c93455e3c0efe3cc4543f036 (patch) | |
tree | b40db18da36cd3caf71f467ed4f754b96527886b /drivers/acpi/acpi_memhotplug.c | |
parent | 315bbae9c5cb1f54a6d6fd47b9cf325fbedccf05 (diff) |
ACPI / memhotplug: fix memory leak when memory device is unbound from acpi_memhotplug
We allocate memory to store acpi_memory_info, so we should free it before
freeing mem_device.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Reviewed-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpi_memhotplug.c')
-rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 6e12042658b8..c5e7b6d08ef3 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
@@ -125,12 +125,20 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context) | |||
125 | return AE_OK; | 125 | return AE_OK; |
126 | } | 126 | } |
127 | 127 | ||
128 | static void | ||
129 | acpi_memory_free_device_resources(struct acpi_memory_device *mem_device) | ||
130 | { | ||
131 | struct acpi_memory_info *info, *n; | ||
132 | |||
133 | list_for_each_entry_safe(info, n, &mem_device->res_list, list) | ||
134 | kfree(info); | ||
135 | INIT_LIST_HEAD(&mem_device->res_list); | ||
136 | } | ||
137 | |||
128 | static int | 138 | static int |
129 | acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) | 139 | acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) |
130 | { | 140 | { |
131 | acpi_status status; | 141 | acpi_status status; |
132 | struct acpi_memory_info *info, *n; | ||
133 | |||
134 | 142 | ||
135 | if (!list_empty(&mem_device->res_list)) | 143 | if (!list_empty(&mem_device->res_list)) |
136 | return 0; | 144 | return 0; |
@@ -138,9 +146,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) | |||
138 | status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, | 146 | status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, |
139 | acpi_memory_get_resource, mem_device); | 147 | acpi_memory_get_resource, mem_device); |
140 | if (ACPI_FAILURE(status)) { | 148 | if (ACPI_FAILURE(status)) { |
141 | list_for_each_entry_safe(info, n, &mem_device->res_list, list) | 149 | acpi_memory_free_device_resources(mem_device); |
142 | kfree(info); | ||
143 | INIT_LIST_HEAD(&mem_device->res_list); | ||
144 | return -EINVAL; | 150 | return -EINVAL; |
145 | } | 151 | } |
146 | 152 | ||
@@ -363,6 +369,15 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) | |||
363 | return; | 369 | return; |
364 | } | 370 | } |
365 | 371 | ||
372 | static void acpi_memory_device_free(struct acpi_memory_device *mem_device) | ||
373 | { | ||
374 | if (!mem_device) | ||
375 | return; | ||
376 | |||
377 | acpi_memory_free_device_resources(mem_device); | ||
378 | kfree(mem_device); | ||
379 | } | ||
380 | |||
366 | static int acpi_memory_device_add(struct acpi_device *device) | 381 | static int acpi_memory_device_add(struct acpi_device *device) |
367 | { | 382 | { |
368 | int result; | 383 | int result; |
@@ -427,7 +442,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type) | |||
427 | if (result) | 442 | if (result) |
428 | return result; | 443 | return result; |
429 | 444 | ||
430 | kfree(mem_device); | 445 | acpi_memory_device_free(mem_device); |
431 | 446 | ||
432 | return 0; | 447 | return 0; |
433 | } | 448 | } |