diff options
Diffstat (limited to 'kernel/power/snapshot.c')
-rw-r--r-- | kernel/power/snapshot.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 5d2ab836e998..955c8cc91838 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -519,6 +519,14 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
519 | return test_bit(bit, addr); | 519 | return test_bit(bit, addr); |
520 | } | 520 | } |
521 | 521 | ||
522 | static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn) | ||
523 | { | ||
524 | void *addr; | ||
525 | unsigned int bit; | ||
526 | |||
527 | return !memory_bm_find_bit(bm, pfn, &addr, &bit); | ||
528 | } | ||
529 | |||
522 | /** | 530 | /** |
523 | * memory_bm_next_pfn - find the pfn that corresponds to the next set bit | 531 | * memory_bm_next_pfn - find the pfn that corresponds to the next set bit |
524 | * in the bitmap @bm. If the pfn cannot be found, BM_END_OF_MAP is | 532 | * in the bitmap @bm. If the pfn cannot be found, BM_END_OF_MAP is |
@@ -1459,9 +1467,7 @@ load_header(struct swsusp_info *info) | |||
1459 | * unpack_orig_pfns - for each element of @buf[] (1 page at a time) set | 1467 | * unpack_orig_pfns - for each element of @buf[] (1 page at a time) set |
1460 | * the corresponding bit in the memory bitmap @bm | 1468 | * the corresponding bit in the memory bitmap @bm |
1461 | */ | 1469 | */ |
1462 | 1470 | static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) | |
1463 | static inline void | ||
1464 | unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) | ||
1465 | { | 1471 | { |
1466 | int j; | 1472 | int j; |
1467 | 1473 | ||
@@ -1469,8 +1475,13 @@ unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) | |||
1469 | if (unlikely(buf[j] == BM_END_OF_MAP)) | 1475 | if (unlikely(buf[j] == BM_END_OF_MAP)) |
1470 | break; | 1476 | break; |
1471 | 1477 | ||
1472 | memory_bm_set_bit(bm, buf[j]); | 1478 | if (memory_bm_pfn_present(bm, buf[j])) |
1479 | memory_bm_set_bit(bm, buf[j]); | ||
1480 | else | ||
1481 | return -EFAULT; | ||
1473 | } | 1482 | } |
1483 | |||
1484 | return 0; | ||
1474 | } | 1485 | } |
1475 | 1486 | ||
1476 | /* List of "safe" pages that may be used to store data loaded from the suspend | 1487 | /* List of "safe" pages that may be used to store data loaded from the suspend |
@@ -1608,7 +1619,7 @@ get_highmem_page_buffer(struct page *page, struct chain_allocator *ca) | |||
1608 | pbe = chain_alloc(ca, sizeof(struct highmem_pbe)); | 1619 | pbe = chain_alloc(ca, sizeof(struct highmem_pbe)); |
1609 | if (!pbe) { | 1620 | if (!pbe) { |
1610 | swsusp_free(); | 1621 | swsusp_free(); |
1611 | return NULL; | 1622 | return ERR_PTR(-ENOMEM); |
1612 | } | 1623 | } |
1613 | pbe->orig_page = page; | 1624 | pbe->orig_page = page; |
1614 | if (safe_highmem_pages > 0) { | 1625 | if (safe_highmem_pages > 0) { |
@@ -1677,7 +1688,7 @@ prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p) | |||
1677 | static inline void * | 1688 | static inline void * |
1678 | get_highmem_page_buffer(struct page *page, struct chain_allocator *ca) | 1689 | get_highmem_page_buffer(struct page *page, struct chain_allocator *ca) |
1679 | { | 1690 | { |
1680 | return NULL; | 1691 | return ERR_PTR(-EINVAL); |
1681 | } | 1692 | } |
1682 | 1693 | ||
1683 | static inline void copy_last_highmem_page(void) {} | 1694 | static inline void copy_last_highmem_page(void) {} |
@@ -1788,8 +1799,13 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) | |||
1788 | static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) | 1799 | static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) |
1789 | { | 1800 | { |
1790 | struct pbe *pbe; | 1801 | struct pbe *pbe; |
1791 | struct page *page = pfn_to_page(memory_bm_next_pfn(bm)); | 1802 | struct page *page; |
1803 | unsigned long pfn = memory_bm_next_pfn(bm); | ||
1792 | 1804 | ||
1805 | if (pfn == BM_END_OF_MAP) | ||
1806 | return ERR_PTR(-EFAULT); | ||
1807 | |||
1808 | page = pfn_to_page(pfn); | ||
1793 | if (PageHighMem(page)) | 1809 | if (PageHighMem(page)) |
1794 | return get_highmem_page_buffer(page, ca); | 1810 | return get_highmem_page_buffer(page, ca); |
1795 | 1811 | ||
@@ -1805,7 +1821,7 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) | |||
1805 | pbe = chain_alloc(ca, sizeof(struct pbe)); | 1821 | pbe = chain_alloc(ca, sizeof(struct pbe)); |
1806 | if (!pbe) { | 1822 | if (!pbe) { |
1807 | swsusp_free(); | 1823 | swsusp_free(); |
1808 | return NULL; | 1824 | return ERR_PTR(-ENOMEM); |
1809 | } | 1825 | } |
1810 | pbe->orig_address = page_address(page); | 1826 | pbe->orig_address = page_address(page); |
1811 | pbe->address = safe_pages_list; | 1827 | pbe->address = safe_pages_list; |
@@ -1868,7 +1884,10 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count) | |||
1868 | return error; | 1884 | return error; |
1869 | 1885 | ||
1870 | } else if (handle->prev <= nr_meta_pages) { | 1886 | } else if (handle->prev <= nr_meta_pages) { |
1871 | unpack_orig_pfns(buffer, ©_bm); | 1887 | error = unpack_orig_pfns(buffer, ©_bm); |
1888 | if (error) | ||
1889 | return error; | ||
1890 | |||
1872 | if (handle->prev == nr_meta_pages) { | 1891 | if (handle->prev == nr_meta_pages) { |
1873 | error = prepare_image(&orig_bm, ©_bm); | 1892 | error = prepare_image(&orig_bm, ©_bm); |
1874 | if (error) | 1893 | if (error) |
@@ -1879,12 +1898,14 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count) | |||
1879 | restore_pblist = NULL; | 1898 | restore_pblist = NULL; |
1880 | handle->buffer = get_buffer(&orig_bm, &ca); | 1899 | handle->buffer = get_buffer(&orig_bm, &ca); |
1881 | handle->sync_read = 0; | 1900 | handle->sync_read = 0; |
1882 | if (!handle->buffer) | 1901 | if (IS_ERR(handle->buffer)) |
1883 | return -ENOMEM; | 1902 | return PTR_ERR(handle->buffer); |
1884 | } | 1903 | } |
1885 | } else { | 1904 | } else { |
1886 | copy_last_highmem_page(); | 1905 | copy_last_highmem_page(); |
1887 | handle->buffer = get_buffer(&orig_bm, &ca); | 1906 | handle->buffer = get_buffer(&orig_bm, &ca); |
1907 | if (IS_ERR(handle->buffer)) | ||
1908 | return PTR_ERR(handle->buffer); | ||
1888 | if (handle->buffer != buffer) | 1909 | if (handle->buffer != buffer) |
1889 | handle->sync_read = 0; | 1910 | handle->sync_read = 0; |
1890 | } | 1911 | } |