diff options
author | Nitin Gupta <ngupta@vflare.org> | 2012-04-02 10:13:56 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-10 12:18:59 -0400 |
commit | f4477e90b3ea4c40466e8f418cf41a17aef09192 (patch) | |
tree | 7cba846e1a7a317bc3949b4063677942c614c150 | |
parent | 3fd654c22c7b002e8681accaed50a6d46656d815 (diff) |
staging: zsmalloc: fix memory leak
This patch fixes a memory leak in zsmalloc where the first
subpage of each zspage is leaked when the zspage is freed.
Signed-off-by: Nitin Gupta <ngupta@vflare.org>
Acked-by: Seth Jennings <sjenning@linux.vnet.ibm.com>
Acked-by: Dan Magenheimer <dan.magenheimer@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/zsmalloc/zsmalloc-main.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 09caa4f2687e..917461c66014 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c | |||
@@ -267,33 +267,39 @@ static unsigned long obj_idx_to_offset(struct page *page, | |||
267 | return off + obj_idx * class_size; | 267 | return off + obj_idx * class_size; |
268 | } | 268 | } |
269 | 269 | ||
270 | static void reset_page(struct page *page) | ||
271 | { | ||
272 | clear_bit(PG_private, &page->flags); | ||
273 | clear_bit(PG_private_2, &page->flags); | ||
274 | set_page_private(page, 0); | ||
275 | page->mapping = NULL; | ||
276 | page->freelist = NULL; | ||
277 | reset_page_mapcount(page); | ||
278 | } | ||
279 | |||
270 | static void free_zspage(struct page *first_page) | 280 | static void free_zspage(struct page *first_page) |
271 | { | 281 | { |
272 | struct page *nextp, *tmp; | 282 | struct page *nextp, *tmp, *head_extra; |
273 | 283 | ||
274 | BUG_ON(!is_first_page(first_page)); | 284 | BUG_ON(!is_first_page(first_page)); |
275 | BUG_ON(first_page->inuse); | 285 | BUG_ON(first_page->inuse); |
276 | 286 | ||
277 | nextp = (struct page *)page_private(first_page); | 287 | head_extra = (struct page *)page_private(first_page); |
278 | 288 | ||
279 | clear_bit(PG_private, &first_page->flags); | 289 | reset_page(first_page); |
280 | clear_bit(PG_private_2, &first_page->flags); | ||
281 | set_page_private(first_page, 0); | ||
282 | first_page->mapping = NULL; | ||
283 | first_page->freelist = NULL; | ||
284 | reset_page_mapcount(first_page); | ||
285 | __free_page(first_page); | 290 | __free_page(first_page); |
286 | 291 | ||
287 | /* zspage with only 1 system page */ | 292 | /* zspage with only 1 system page */ |
288 | if (!nextp) | 293 | if (!head_extra) |
289 | return; | 294 | return; |
290 | 295 | ||
291 | list_for_each_entry_safe(nextp, tmp, &nextp->lru, lru) { | 296 | list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) { |
292 | list_del(&nextp->lru); | 297 | list_del(&nextp->lru); |
293 | clear_bit(PG_private_2, &nextp->flags); | 298 | reset_page(nextp); |
294 | nextp->index = 0; | ||
295 | __free_page(nextp); | 299 | __free_page(nextp); |
296 | } | 300 | } |
301 | reset_page(head_extra); | ||
302 | __free_page(head_extra); | ||
297 | } | 303 | } |
298 | 304 | ||
299 | /* Initialize a newly allocated zspage */ | 305 | /* Initialize a newly allocated zspage */ |