Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+68 -37
+2 -2
include/linux/gfp.h
··· 360 360 361 361 extern gfp_t gfp_allowed_mask; 362 362 363 - extern void set_gfp_allowed_mask(gfp_t mask); 364 - extern gfp_t clear_gfp_allowed_mask(gfp_t mask); 363 + extern void pm_restrict_gfp_mask(void); 364 + extern void pm_restore_gfp_mask(void); 365 365 366 366 #endif /* __LINUX_GFP_H */
+12 -10
kernel/power/hibernate.c
··· 327 327 int hibernation_snapshot(int platform_mode) 328 328 { 329 329 int error; 330 - gfp_t saved_mask; 331 330 332 331 error = platform_begin(platform_mode); 333 332 if (error) ··· 338 339 goto Close; 339 340 340 341 suspend_console(); 341 - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); 342 + pm_restrict_gfp_mask(); 342 343 error = dpm_suspend_start(PMSG_FREEZE); 343 344 if (error) 344 345 goto Recover_platform; ··· 347 348 goto Recover_platform; 348 349 349 350 error = create_image(platform_mode); 350 - /* Control returns here after successful restore */ 351 + /* 352 + * Control returns here (1) after the image has been created or the 353 + * image creation has failed and (2) after a successful restore. 354 + */ 351 355 352 356 Resume_devices: 353 357 /* We may need to release the preallocated image pages here. */ ··· 359 357 360 358 dpm_resume_end(in_suspend ? 361 359 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 362 - set_gfp_allowed_mask(saved_mask); 360 + 361 + if (error || !in_suspend) 362 + pm_restore_gfp_mask(); 363 + 363 364 resume_console(); 364 365 Close: 365 366 platform_end(platform_mode); ··· 457 452 int hibernation_restore(int platform_mode) 458 453 { 459 454 int error; 460 - gfp_t saved_mask; 461 455 462 456 pm_prepare_console(); 463 457 suspend_console(); 464 - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); 458 + pm_restrict_gfp_mask(); 465 459 error = dpm_suspend_start(PMSG_QUIESCE); 466 460 if (!error) { 467 461 error = resume_target_kernel(platform_mode); 468 462 dpm_resume_end(PMSG_RECOVER); 469 463 } 470 - set_gfp_allowed_mask(saved_mask); 464 + pm_restore_gfp_mask(); 471 465 resume_console(); 472 466 pm_restore_console(); 473 467 return error; ··· 480 476 int hibernation_platform_enter(void) 481 477 { 482 478 int error; 483 - gfp_t saved_mask; 484 479 485 480 if (!hibernation_ops) 486 481 return -ENOSYS; ··· 495 492 496 493 entering_platform_hibernation = true; 497 494 suspend_console(); 498 - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); 499 495 error = dpm_suspend_start(PMSG_HIBERNATE); 500 496 if (error) { 501 497 if (hibernation_ops->recover) ··· 538 536 Resume_devices: 539 537 entering_platform_hibernation = false; 540 538 dpm_resume_end(PMSG_RESTORE); 541 - set_gfp_allowed_mask(saved_mask); 542 539 resume_console(); 543 540 544 541 Close: ··· 647 646 swsusp_free(); 648 647 if (!error) 649 648 power_down(); 649 + pm_restore_gfp_mask(); 650 650 } else { 651 651 pr_debug("PM: Image restored successfully.\n"); 652 652 }
+2 -3
kernel/power/suspend.c
··· 197 197 int suspend_devices_and_enter(suspend_state_t state) 198 198 { 199 199 int error; 200 - gfp_t saved_mask; 201 200 202 201 if (!suspend_ops) 203 202 return -ENOSYS; ··· 207 208 goto Close; 208 209 } 209 210 suspend_console(); 210 - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); 211 + pm_restrict_gfp_mask(); 211 212 suspend_test_start(); 212 213 error = dpm_suspend_start(PMSG_SUSPEND); 213 214 if (error) { ··· 224 225 suspend_test_start(); 225 226 dpm_resume_end(PMSG_RESUME); 226 227 suspend_test_finish("resume devices"); 227 - set_gfp_allowed_mask(saved_mask); 228 + pm_restore_gfp_mask(); 228 229 resume_console(); 229 230 Close: 230 231 if (suspend_ops->end)
+38 -15
kernel/power/swap.c
··· 6 6 * 7 7 * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz> 8 8 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> 9 + * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com> 9 10 * 10 11 * This file is released under the GPLv2. 11 12 * ··· 754 753 { 755 754 unsigned int m; 756 755 int error = 0; 756 + struct bio *bio; 757 757 struct timeval start; 758 758 struct timeval stop; 759 759 unsigned nr_pages; 760 - size_t off, unc_len, cmp_len; 761 - unsigned char *unc, *cmp, *page; 760 + size_t i, off, unc_len, cmp_len; 761 + unsigned char *unc, *cmp, *page[LZO_CMP_PAGES]; 762 762 763 - page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); 764 - if (!page) { 765 - printk(KERN_ERR "PM: Failed to allocate LZO page\n"); 766 - return -ENOMEM; 763 + for (i = 0; i < LZO_CMP_PAGES; i++) { 764 + page[i] = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); 765 + if (!page[i]) { 766 + printk(KERN_ERR "PM: Failed to allocate LZO page\n"); 767 + 768 + while (i) 769 + free_page((unsigned long)page[--i]); 770 + 771 + return -ENOMEM; 772 + } 767 773 } 768 774 769 775 unc = vmalloc(LZO_UNC_SIZE); 770 776 if (!unc) { 771 777 printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n"); 772 - free_page((unsigned long)page); 778 + 779 + for (i = 0; i < LZO_CMP_PAGES; i++) 780 + free_page((unsigned long)page[i]); 781 + 773 782 return -ENOMEM; 774 783 } 775 784 776 785 cmp = vmalloc(LZO_CMP_SIZE); 777 786 if (!cmp) { 778 787 printk(KERN_ERR "PM: Failed to allocate LZO compressed\n"); 788 + 779 789 vfree(unc); 780 - free_page((unsigned long)page); 790 + for (i = 0; i < LZO_CMP_PAGES; i++) 791 + free_page((unsigned long)page[i]); 792 + 781 793 return -ENOMEM; 782 794 } 783 795 ··· 801 787 if (!m) 802 788 m = 1; 803 789 nr_pages = 0; 790 + bio = NULL; 804 791 do_gettimeofday(&start); 805 792 806 793 error = snapshot_write_next(snapshot); ··· 809 794 goto out_finish; 810 795 811 796 for (;;) { 812 - error = swap_read_page(handle, page, NULL); /* sync */ 797 + error = swap_read_page(handle, page[0], NULL); /* sync */ 813 798 if (error) 814 799 break; 815 800 816 - cmp_len = *(size_t *)page; 801 + cmp_len = *(size_t *)page[0]; 817 802 if (unlikely(!cmp_len || 818 803 cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) { 819 804 printk(KERN_ERR "PM: Invalid LZO compressed length\n"); ··· 821 806 break; 822 807 } 823 808 824 - memcpy(cmp, page, PAGE_SIZE); 825 - for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) { 826 - error = swap_read_page(handle, page, NULL); /* sync */ 809 + for (off = PAGE_SIZE, i = 1; 810 + off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) { 811 + error = swap_read_page(handle, page[i], &bio); 827 812 if (error) 828 813 goto out_finish; 814 + } 829 815 830 - memcpy(cmp + off, page, PAGE_SIZE); 816 + error = hib_wait_on_bio_chain(&bio); /* need all data now */ 817 + if (error) 818 + goto out_finish; 819 + 820 + for (off = 0, i = 0; 821 + off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) { 822 + memcpy(cmp + off, page[i], PAGE_SIZE); 831 823 } 832 824 833 825 unc_len = LZO_UNC_SIZE; ··· 879 857 880 858 vfree(cmp); 881 859 vfree(unc); 882 - free_page((unsigned long)page); 860 + for (i = 0; i < LZO_CMP_PAGES; i++) 861 + free_page((unsigned long)page[i]); 883 862 884 863 return error; 885 864 }
+2
kernel/power/user.c
··· 263 263 case SNAPSHOT_UNFREEZE: 264 264 if (!data->frozen || data->ready) 265 265 break; 266 + pm_restore_gfp_mask(); 266 267 thaw_processes(); 267 268 usermodehelper_enable(); 268 269 data->frozen = 0; ··· 276 275 error = -EPERM; 277 276 break; 278 277 } 278 + pm_restore_gfp_mask(); 279 279 error = hibernation_snapshot(data->platform_support); 280 280 if (!error) 281 281 error = put_user(in_suspend, (int __user *)arg);
+12 -7
mm/page_alloc.c
··· 104 104 * only be modified with pm_mutex held, unless the suspend/hibernate code is 105 105 * guaranteed not to run in parallel with that modification). 106 106 */ 107 - void set_gfp_allowed_mask(gfp_t mask) 107 + 108 + static gfp_t saved_gfp_mask; 109 + 110 + void pm_restore_gfp_mask(void) 108 111 { 109 112 WARN_ON(!mutex_is_locked(&pm_mutex)); 110 - gfp_allowed_mask = mask; 113 + if (saved_gfp_mask) { 114 + gfp_allowed_mask = saved_gfp_mask; 115 + saved_gfp_mask = 0; 116 + } 111 117 } 112 118 113 - gfp_t clear_gfp_allowed_mask(gfp_t mask) 119 + void pm_restrict_gfp_mask(void) 114 120 { 115 - gfp_t ret = gfp_allowed_mask; 116 - 117 121 WARN_ON(!mutex_is_locked(&pm_mutex)); 118 - gfp_allowed_mask &= ~mask; 119 - return ret; 122 + WARN_ON(saved_gfp_mask); 123 + saved_gfp_mask = gfp_allowed_mask; 124 + gfp_allowed_mask &= ~GFP_IOFS; 120 125 } 121 126 #endif /* CONFIG_PM_SLEEP */ 122 127