forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'pm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/…
…git/rafael/suspend-2.6 * 'pm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6: PM / Hibernate: Fix memory corruption related to swap PM / Hibernate: Use async I/O when reading compressed hibernation image
- Loading branch information
Showing
6 changed files
with
68 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
* | ||
* Copyright (C) 1998,2001-2005 Pavel Machek <[email protected]> | ||
* Copyright (C) 2006 Rafael J. Wysocki <[email protected]> | ||
* Copyright (C) 2010 Bojan Smojver <[email protected]> | ||
* | ||
* This file is released under the GPLv2. | ||
* | ||
|
@@ -753,30 +754,43 @@ static int load_image_lzo(struct swap_map_handle *handle, | |
{ | ||
unsigned int m; | ||
int error = 0; | ||
struct bio *bio; | ||
struct timeval start; | ||
struct timeval stop; | ||
unsigned nr_pages; | ||
size_t off, unc_len, cmp_len; | ||
unsigned char *unc, *cmp, *page; | ||
size_t i, off, unc_len, cmp_len; | ||
unsigned char *unc, *cmp, *page[LZO_CMP_PAGES]; | ||
|
||
page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); | ||
if (!page) { | ||
printk(KERN_ERR "PM: Failed to allocate LZO page\n"); | ||
return -ENOMEM; | ||
for (i = 0; i < LZO_CMP_PAGES; i++) { | ||
page[i] = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); | ||
if (!page[i]) { | ||
printk(KERN_ERR "PM: Failed to allocate LZO page\n"); | ||
|
||
while (i) | ||
free_page((unsigned long)page[--i]); | ||
|
||
return -ENOMEM; | ||
} | ||
} | ||
|
||
unc = vmalloc(LZO_UNC_SIZE); | ||
if (!unc) { | ||
printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n"); | ||
free_page((unsigned long)page); | ||
|
||
for (i = 0; i < LZO_CMP_PAGES; i++) | ||
free_page((unsigned long)page[i]); | ||
|
||
return -ENOMEM; | ||
} | ||
|
||
cmp = vmalloc(LZO_CMP_SIZE); | ||
if (!cmp) { | ||
printk(KERN_ERR "PM: Failed to allocate LZO compressed\n"); | ||
|
||
vfree(unc); | ||
free_page((unsigned long)page); | ||
for (i = 0; i < LZO_CMP_PAGES; i++) | ||
free_page((unsigned long)page[i]); | ||
|
||
return -ENOMEM; | ||
} | ||
|
||
|
@@ -787,32 +801,40 @@ static int load_image_lzo(struct swap_map_handle *handle, | |
if (!m) | ||
m = 1; | ||
nr_pages = 0; | ||
bio = NULL; | ||
do_gettimeofday(&start); | ||
|
||
error = snapshot_write_next(snapshot); | ||
if (error <= 0) | ||
goto out_finish; | ||
|
||
for (;;) { | ||
error = swap_read_page(handle, page, NULL); /* sync */ | ||
error = swap_read_page(handle, page[0], NULL); /* sync */ | ||
if (error) | ||
break; | ||
|
||
cmp_len = *(size_t *)page; | ||
cmp_len = *(size_t *)page[0]; | ||
if (unlikely(!cmp_len || | ||
cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) { | ||
printk(KERN_ERR "PM: Invalid LZO compressed length\n"); | ||
error = -1; | ||
break; | ||
} | ||
|
||
memcpy(cmp, page, PAGE_SIZE); | ||
for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) { | ||
error = swap_read_page(handle, page, NULL); /* sync */ | ||
for (off = PAGE_SIZE, i = 1; | ||
off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) { | ||
error = swap_read_page(handle, page[i], &bio); | ||
if (error) | ||
goto out_finish; | ||
} | ||
|
||
memcpy(cmp + off, page, PAGE_SIZE); | ||
error = hib_wait_on_bio_chain(&bio); /* need all data now */ | ||
if (error) | ||
goto out_finish; | ||
|
||
for (off = 0, i = 0; | ||
off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) { | ||
memcpy(cmp + off, page[i], PAGE_SIZE); | ||
} | ||
|
||
unc_len = LZO_UNC_SIZE; | ||
|
@@ -857,7 +879,8 @@ static int load_image_lzo(struct swap_map_handle *handle, | |
|
||
vfree(cmp); | ||
vfree(unc); | ||
free_page((unsigned long)page); | ||
for (i = 0; i < LZO_CMP_PAGES; i++) | ||
free_page((unsigned long)page[i]); | ||
|
||
return error; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters