aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2005-10-30 17:59:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 20:37:14 -0500
commit351619baf9878731b4272fa10dda0f84f5582241 (patch)
tree62bf45ba8368dddde3adb501a37c428ead5feff7 /kernel/power/swsusp.c
parentc32b6b8e524d2c337767d312814484d9289550cf (diff)
[PATCH] swsusp: rework image freeing
The following patch makes swsusp use PG_nosave and PG_nosave_free flags to mark pages that should be freed after the state of the system has been restored from the image (or in case of an error during suspend). This allows us to avoid storing metadata in swap twice and to reduce the amount of memory needed by swsusp.  Additionally, it allows us to simplify the code by removing a couple of functions that are no longer necessary. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Pavel Machek <pavel@suse.cz> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c159
1 files changed, 75 insertions, 84 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 016504ccfccf..ae46506e2137 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -708,24 +708,28 @@ static void count_data_pages(void)
708 } 708 }
709} 709}
710 710
711
712static void copy_data_pages(void) 711static void copy_data_pages(void)
713{ 712{
714 struct zone *zone; 713 struct zone *zone;
715 unsigned long zone_pfn; 714 unsigned long zone_pfn;
716 struct pbe * pbe = pagedir_nosave; 715 struct pbe *pbe = pagedir_nosave, *p;
717 716
718 pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages); 717 pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages);
719 for_each_zone (zone) { 718 for_each_zone (zone) {
720 if (is_highmem(zone)) 719 if (is_highmem(zone))
721 continue; 720 continue;
722 mark_free_pages(zone); 721 mark_free_pages(zone);
722 /* This is necessary for swsusp_free() */
723 for_each_pb_page (p, pagedir_nosave)
724 SetPageNosaveFree(virt_to_page(p));
725 for_each_pbe(p, pagedir_nosave)
726 SetPageNosaveFree(virt_to_page(p->address));
723 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { 727 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
724 if (saveable(zone, &zone_pfn)) { 728 if (saveable(zone, &zone_pfn)) {
725 struct page * page; 729 struct page * page;
726 page = pfn_to_page(zone_pfn + zone->zone_start_pfn); 730 page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
727 BUG_ON(!pbe); 731 BUG_ON(!pbe);
728 pbe->orig_address = (long) page_address(page); 732 pbe->orig_address = (unsigned long)page_address(page);
729 /* copy_page is not usable for copying task structs. */ 733 /* copy_page is not usable for copying task structs. */
730 memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE); 734 memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
731 pbe = pbe->next; 735 pbe = pbe->next;
@@ -737,15 +741,6 @@ static void copy_data_pages(void)
737 741
738 742
739/** 743/**
740 * calc_nr - Determine the number of pages needed for a pbe list.
741 */
742
743static int calc_nr(int nr_copy)
744{
745 return nr_copy + (nr_copy+PBES_PER_PAGE-2)/(PBES_PER_PAGE-1);
746}
747
748/**
749 * free_pagedir - free pages allocated with alloc_pagedir() 744 * free_pagedir - free pages allocated with alloc_pagedir()
750 */ 745 */
751 746
@@ -755,6 +750,8 @@ static inline void free_pagedir(struct pbe *pblist)
755 750
756 while (pblist) { 751 while (pblist) {
757 pbe = (pblist + PB_PAGE_SKIP)->next; 752 pbe = (pblist + PB_PAGE_SKIP)->next;
753 ClearPageNosave(virt_to_page(pblist));
754 ClearPageNosaveFree(virt_to_page(pblist));
758 free_page((unsigned long)pblist); 755 free_page((unsigned long)pblist);
759 pblist = pbe; 756 pblist = pbe;
760 } 757 }
@@ -800,6 +797,16 @@ static void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
800 pr_debug("create_pbe_list(): initialized %d PBEs\n", num); 797 pr_debug("create_pbe_list(): initialized %d PBEs\n", num);
801} 798}
802 799
800static void *alloc_image_page(void)
801{
802 void *res = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
803 if (res) {
804 SetPageNosave(virt_to_page(res));
805 SetPageNosaveFree(virt_to_page(res));
806 }
807 return res;
808}
809
803/** 810/**
804 * alloc_pagedir - Allocate the page directory. 811 * alloc_pagedir - Allocate the page directory.
805 * 812 *
@@ -822,11 +829,11 @@ static struct pbe * alloc_pagedir(unsigned nr_pages)
822 return NULL; 829 return NULL;
823 830
824 pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); 831 pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages);
825 pblist = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); 832 pblist = (struct pbe *)alloc_image_page();
826 for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; 833 for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages;
827 pbe = pbe->next, num += PBES_PER_PAGE) { 834 pbe = pbe->next, num += PBES_PER_PAGE) {
828 pbe += PB_PAGE_SKIP; 835 pbe += PB_PAGE_SKIP;
829 pbe->next = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); 836 pbe->next = (struct pbe *)alloc_image_page();
830 } 837 }
831 if (!pbe) { /* get_zeroed_page() failed */ 838 if (!pbe) { /* get_zeroed_page() failed */
832 free_pagedir(pblist); 839 free_pagedir(pblist);
@@ -836,52 +843,30 @@ static struct pbe * alloc_pagedir(unsigned nr_pages)
836} 843}
837 844
838/** 845/**
839 * free_image_pages - Free pages allocated for snapshot 846 * Free pages we allocated for suspend. Suspend pages are alocated
847 * before atomic copy, so we need to free them after resume.
840 */ 848 */
841 849
842static void free_image_pages(void) 850void swsusp_free(void)
843{ 851{
844 struct pbe * p; 852 struct zone *zone;
853 unsigned long zone_pfn;
845 854
846 for_each_pbe (p, pagedir_save) { 855 for_each_zone(zone) {
847 if (p->address) { 856 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
848 ClearPageNosave(virt_to_page(p->address)); 857 if (pfn_valid(zone_pfn + zone->zone_start_pfn)) {
849 free_page(p->address); 858 struct page * page;
850 p->address = 0; 859 page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
851 } 860 if (PageNosave(page) && PageNosaveFree(page)) {
861 ClearPageNosave(page);
862 ClearPageNosaveFree(page);
863 free_page((long) page_address(page));
864 }
865 }
852 } 866 }
853} 867}
854 868
855/** 869/**
856 * alloc_image_pages - Allocate pages for the snapshot.
857 */
858
859static int alloc_image_pages(void)
860{
861 struct pbe * p;
862
863 for_each_pbe (p, pagedir_save) {
864 p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
865 if (!p->address)
866 return -ENOMEM;
867 SetPageNosave(virt_to_page(p->address));
868 }
869 return 0;
870}
871
872/* Free pages we allocated for suspend. Suspend pages are alocated
873 * before atomic copy, so we need to free them after resume.
874 */
875void swsusp_free(void)
876{
877 BUG_ON(PageNosave(virt_to_page(pagedir_save)));
878 BUG_ON(PageNosaveFree(virt_to_page(pagedir_save)));
879 free_image_pages();
880 free_pagedir(pagedir_save);
881}
882
883
884/**
885 * enough_free_mem - Make sure we enough free memory to snapshot. 870 * enough_free_mem - Make sure we enough free memory to snapshot.
886 * 871 *
887 * Returns TRUE or FALSE after checking the number of available 872 * Returns TRUE or FALSE after checking the number of available
@@ -890,12 +875,9 @@ void swsusp_free(void)
890 875
891static int enough_free_mem(void) 876static int enough_free_mem(void)
892{ 877{
893 if (nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) { 878 pr_debug("swsusp: available memory: %u pages\n", nr_free_pages());
894 pr_debug("swsusp: Not enough free pages: Have %d\n", 879 return nr_free_pages() > (nr_copy_pages + PAGES_FOR_IO +
895 nr_free_pages()); 880 nr_copy_pages/PBES_PER_PAGE + !!(nr_copy_pages%PBES_PER_PAGE));
896 return 0;
897 }
898 return 1;
899} 881}
900 882
901 883
@@ -914,33 +896,16 @@ static int enough_swap(void)
914 struct sysinfo i; 896 struct sysinfo i;
915 897
916 si_swapinfo(&i); 898 si_swapinfo(&i);
917 if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO)) { 899 pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
918 pr_debug("swsusp: Not enough swap. Need %ld\n",i.freeswap); 900 return i.freeswap > (nr_copy_pages + PAGES_FOR_IO +
919 return 0; 901 nr_copy_pages/PBES_PER_PAGE + !!(nr_copy_pages%PBES_PER_PAGE));
920 }
921 return 1;
922} 902}
923 903
924static int swsusp_alloc(void) 904static int swsusp_alloc(void)
925{ 905{
926 int error; 906 struct pbe * p;
927 907
928 pagedir_nosave = NULL; 908 pagedir_nosave = NULL;
929 nr_copy_pages = calc_nr(nr_copy_pages);
930 nr_copy_pages_check = nr_copy_pages;
931
932 pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
933 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
934
935 if (!enough_free_mem())
936 return -ENOMEM;
937
938 if (!enough_swap())
939 return -ENOSPC;
940
941 if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE +
942 !!(nr_copy_pages % PBES_PER_PAGE))
943 return -ENOSPC;
944 909
945 if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { 910 if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
946 printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); 911 printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
@@ -948,10 +913,14 @@ static int swsusp_alloc(void)
948 } 913 }
949 create_pbe_list(pagedir_save, nr_copy_pages); 914 create_pbe_list(pagedir_save, nr_copy_pages);
950 pagedir_nosave = pagedir_save; 915 pagedir_nosave = pagedir_save;
951 if ((error = alloc_image_pages())) { 916
952 printk(KERN_ERR "suspend: Allocating image pages failed.\n"); 917 for_each_pbe (p, pagedir_save) {
953 swsusp_free(); 918 p->address = (unsigned long)alloc_image_page();
954 return error; 919 if (!p->address) {
920 printk(KERN_ERR "suspend: Allocating image pages failed.\n");
921 swsusp_free();
922 return -ENOMEM;
923 }
955 } 924 }
956 925
957 return 0; 926 return 0;
@@ -963,7 +932,7 @@ static int suspend_prepare_image(void)
963 932
964 pr_debug("swsusp: critical section: \n"); 933 pr_debug("swsusp: critical section: \n");
965 if (save_highmem()) { 934 if (save_highmem()) {
966 printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n"); 935 printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n");
967 restore_highmem(); 936 restore_highmem();
968 return -ENOMEM; 937 return -ENOMEM;
969 } 938 }
@@ -971,6 +940,28 @@ static int suspend_prepare_image(void)
971 drain_local_pages(); 940 drain_local_pages();
972 count_data_pages(); 941 count_data_pages();
973 printk("swsusp: Need to copy %u pages\n", nr_copy_pages); 942 printk("swsusp: Need to copy %u pages\n", nr_copy_pages);
943 nr_copy_pages_check = nr_copy_pages;
944
945 pr_debug("swsusp: pages needed: %u + %lu + %u, free: %u\n",
946 nr_copy_pages,
947 nr_copy_pages/PBES_PER_PAGE + !!(nr_copy_pages%PBES_PER_PAGE),
948 PAGES_FOR_IO, nr_free_pages());
949
950 if (!enough_free_mem()) {
951 printk(KERN_ERR "swsusp: Not enough free memory\n");
952 return -ENOMEM;
953 }
954
955 if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE +
956 !!(nr_copy_pages % PBES_PER_PAGE)) {
957 printk(KERN_ERR "swsusp: Too many image pages\n");
958 return -ENOSPC;
959 }
960
961 if (!enough_swap()) {
962 printk(KERN_ERR "swsusp: Not enough free swap\n");
963 return -ENOSPC;
964 }
974 965
975 error = swsusp_alloc(); 966 error = swsusp_alloc();
976 if (error) 967 if (error)