diff options
Diffstat (limited to 'kernel/power/snapshot.c')
-rw-r--r-- | kernel/power/snapshot.c | 205 |
1 files changed, 158 insertions, 47 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 523a451b45d3..a3a175fa0a46 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -1066,69 +1066,180 @@ void swsusp_free(void) | |||
1066 | buffer = NULL; | 1066 | buffer = NULL; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | /* Helper functions used for the shrinking of memory. */ | ||
1070 | |||
1071 | #define GFP_IMAGE (GFP_KERNEL | __GFP_NOWARN) | ||
1072 | |||
1069 | /** | 1073 | /** |
1070 | * swsusp_shrink_memory - Try to free as much memory as needed | 1074 | * preallocate_image_pages - Allocate a number of pages for hibernation image |
1071 | * | 1075 | * @nr_pages: Number of page frames to allocate. |
1072 | * ... but do not OOM-kill anyone | 1076 | * @mask: GFP flags to use for the allocation. |
1073 | * | 1077 | * |
1074 | * Notice: all userland should be stopped before it is called, or | 1078 | * Return value: Number of page frames actually allocated |
1075 | * livelock is possible. | ||
1076 | */ | 1079 | */ |
1080 | static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask) | ||
1081 | { | ||
1082 | unsigned long nr_alloc = 0; | ||
1083 | |||
1084 | while (nr_pages > 0) { | ||
1085 | if (!alloc_image_page(mask)) | ||
1086 | break; | ||
1087 | nr_pages--; | ||
1088 | nr_alloc++; | ||
1089 | } | ||
1077 | 1090 | ||
1078 | #define SHRINK_BITE 10000 | 1091 | return nr_alloc; |
1079 | static inline unsigned long __shrink_memory(long tmp) | 1092 | } |
1093 | |||
1094 | static unsigned long preallocate_image_memory(unsigned long nr_pages) | ||
1095 | { | ||
1096 | return preallocate_image_pages(nr_pages, GFP_IMAGE); | ||
1097 | } | ||
1098 | |||
1099 | #ifdef CONFIG_HIGHMEM | ||
1100 | static unsigned long preallocate_image_highmem(unsigned long nr_pages) | ||
1080 | { | 1101 | { |
1081 | if (tmp > SHRINK_BITE) | 1102 | return preallocate_image_pages(nr_pages, GFP_IMAGE | __GFP_HIGHMEM); |
1082 | tmp = SHRINK_BITE; | ||
1083 | return shrink_all_memory(tmp); | ||
1084 | } | 1103 | } |
1085 | 1104 | ||
1105 | /** | ||
1106 | * __fraction - Compute (an approximation of) x * (multiplier / base) | ||
1107 | */ | ||
1108 | static unsigned long __fraction(u64 x, u64 multiplier, u64 base) | ||
1109 | { | ||
1110 | x *= multiplier; | ||
1111 | do_div(x, base); | ||
1112 | return (unsigned long)x; | ||
1113 | } | ||
1114 | |||
1115 | static unsigned long preallocate_highmem_fraction(unsigned long nr_pages, | ||
1116 | unsigned long highmem, | ||
1117 | unsigned long total) | ||
1118 | { | ||
1119 | unsigned long alloc = __fraction(nr_pages, highmem, total); | ||
1120 | |||
1121 | return preallocate_image_pages(alloc, GFP_IMAGE | __GFP_HIGHMEM); | ||
1122 | } | ||
1123 | #else /* CONFIG_HIGHMEM */ | ||
1124 | static inline unsigned long preallocate_image_highmem(unsigned long nr_pages) | ||
1125 | { | ||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages, | ||
1130 | unsigned long highmem, | ||
1131 | unsigned long total) | ||
1132 | { | ||
1133 | return 0; | ||
1134 | } | ||
1135 | #endif /* CONFIG_HIGHMEM */ | ||
1136 | |||
1137 | /** | ||
1138 | * swsusp_shrink_memory - Make the kernel release as much memory as needed | ||
1139 | * | ||
1140 | * To create a hibernation image it is necessary to make a copy of every page | ||
1141 | * frame in use. We also need a number of page frames to be free during | ||
1142 | * hibernation for allocations made while saving the image and for device | ||
1143 | * drivers, in case they need to allocate memory from their hibernation | ||
1144 | * callbacks (these two numbers are given by PAGES_FOR_IO and SPARE_PAGES, | ||
1145 | * respectively, both of which are rough estimates). To make this happen, we | ||
1146 | * compute the total number of available page frames and allocate at least | ||
1147 | * | ||
1148 | * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 + 2 * SPARE_PAGES | ||
1149 | * | ||
1150 | * of them, which corresponds to the maximum size of a hibernation image. | ||
1151 | * | ||
1152 | * If image_size is set below the number following from the above formula, | ||
1153 | * the preallocation of memory is continued until the total number of saveable | ||
1154 | * pages in the system is below the requested image size or it is impossible to | ||
1155 | * allocate more memory, whichever happens first. | ||
1156 | */ | ||
1086 | int swsusp_shrink_memory(void) | 1157 | int swsusp_shrink_memory(void) |
1087 | { | 1158 | { |
1088 | long tmp; | ||
1089 | struct zone *zone; | 1159 | struct zone *zone; |
1090 | unsigned long pages = 0; | 1160 | unsigned long saveable, size, max_size, count, highmem, pages = 0; |
1091 | unsigned int i = 0; | 1161 | unsigned long alloc, pages_highmem; |
1092 | char *p = "-\\|/"; | ||
1093 | struct timeval start, stop; | 1162 | struct timeval start, stop; |
1163 | int error = 0; | ||
1094 | 1164 | ||
1095 | printk(KERN_INFO "PM: Shrinking memory... "); | 1165 | printk(KERN_INFO "PM: Shrinking memory... "); |
1096 | do_gettimeofday(&start); | 1166 | do_gettimeofday(&start); |
1097 | do { | ||
1098 | long size, highmem_size; | ||
1099 | |||
1100 | highmem_size = count_highmem_pages(); | ||
1101 | size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES; | ||
1102 | tmp = size; | ||
1103 | size += highmem_size; | ||
1104 | for_each_populated_zone(zone) { | ||
1105 | tmp += snapshot_additional_pages(zone); | ||
1106 | if (is_highmem(zone)) { | ||
1107 | highmem_size -= | ||
1108 | zone_page_state(zone, NR_FREE_PAGES); | ||
1109 | } else { | ||
1110 | tmp -= zone_page_state(zone, NR_FREE_PAGES); | ||
1111 | tmp += zone->lowmem_reserve[ZONE_NORMAL]; | ||
1112 | } | ||
1113 | } | ||
1114 | 1167 | ||
1115 | if (highmem_size < 0) | 1168 | /* Count the number of saveable data pages. */ |
1116 | highmem_size = 0; | 1169 | highmem = count_highmem_pages(); |
1170 | saveable = count_data_pages(); | ||
1117 | 1171 | ||
1118 | tmp += highmem_size; | 1172 | /* |
1119 | if (tmp > 0) { | 1173 | * Compute the total number of page frames we can use (count) and the |
1120 | tmp = __shrink_memory(tmp); | 1174 | * number of pages needed for image metadata (size). |
1121 | if (!tmp) | 1175 | */ |
1122 | return -ENOMEM; | 1176 | count = saveable; |
1123 | pages += tmp; | 1177 | saveable += highmem; |
1124 | } else if (size > image_size / PAGE_SIZE) { | 1178 | size = 0; |
1125 | tmp = __shrink_memory(size - (image_size / PAGE_SIZE)); | 1179 | for_each_populated_zone(zone) { |
1126 | pages += tmp; | 1180 | size += snapshot_additional_pages(zone); |
1127 | } | 1181 | if (is_highmem(zone)) |
1128 | printk("\b%c", p[i++%4]); | 1182 | highmem += zone_page_state(zone, NR_FREE_PAGES); |
1129 | } while (tmp > 0); | 1183 | else |
1184 | count += zone_page_state(zone, NR_FREE_PAGES); | ||
1185 | } | ||
1186 | count += highmem; | ||
1187 | count -= totalreserve_pages; | ||
1188 | |||
1189 | /* Compute the maximum number of saveable pages to leave in memory. */ | ||
1190 | max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES; | ||
1191 | size = DIV_ROUND_UP(image_size, PAGE_SIZE); | ||
1192 | if (size > max_size) | ||
1193 | size = max_size; | ||
1194 | /* | ||
1195 | * If the maximum is not less than the current number of saveable pages | ||
1196 | * in memory, we don't need to do anything more. | ||
1197 | */ | ||
1198 | if (size >= saveable) | ||
1199 | goto out; | ||
1200 | |||
1201 | /* | ||
1202 | * Let the memory management subsystem know that we're going to need a | ||
1203 | * large number of page frames to allocate and make it free some memory. | ||
1204 | * NOTE: If this is not done, performance will be hurt badly in some | ||
1205 | * test cases. | ||
1206 | */ | ||
1207 | shrink_all_memory(saveable - size); | ||
1208 | |||
1209 | /* | ||
1210 | * The number of saveable pages in memory was too high, so apply some | ||
1211 | * pressure to decrease it. First, make room for the largest possible | ||
1212 | * image and fail if that doesn't work. Next, try to decrease the size | ||
1213 | * of the image as much as indicated by image_size using allocations | ||
1214 | * from highmem and non-highmem zones separately. | ||
1215 | */ | ||
1216 | pages_highmem = preallocate_image_highmem(highmem / 2); | ||
1217 | alloc = (count - max_size) - pages_highmem; | ||
1218 | pages = preallocate_image_memory(alloc); | ||
1219 | if (pages < alloc) { | ||
1220 | error = -ENOMEM; | ||
1221 | goto free_out; | ||
1222 | } | ||
1223 | size = max_size - size; | ||
1224 | alloc = size; | ||
1225 | size = preallocate_highmem_fraction(size, highmem, count); | ||
1226 | pages_highmem += size; | ||
1227 | alloc -= size; | ||
1228 | pages += preallocate_image_memory(alloc); | ||
1229 | pages += pages_highmem; | ||
1230 | |||
1231 | free_out: | ||
1232 | /* Release all of the preallocated page frames. */ | ||
1233 | swsusp_free(); | ||
1234 | |||
1235 | if (error) { | ||
1236 | printk(KERN_CONT "\n"); | ||
1237 | return error; | ||
1238 | } | ||
1239 | |||
1240 | out: | ||
1130 | do_gettimeofday(&stop); | 1241 | do_gettimeofday(&stop); |
1131 | printk("\bdone (%lu pages freed)\n", pages); | 1242 | printk(KERN_CONT "done (preallocated %lu free pages)\n", pages); |
1132 | swsusp_show_speed(&start, &stop, pages, "Freed"); | 1243 | swsusp_show_speed(&start, &stop, pages, "Freed"); |
1133 | 1244 | ||
1134 | return 0; | 1245 | return 0; |