aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-07-08 07:23:51 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2009-09-14 14:26:58 -0400
commit4bb334353ebd821bc8eeabeb019eaac33c7307df (patch)
treefc827906f10eebaed4c0483b25beaaba70b0b1dc
parente681c9dd62fe8fcc5bba28a3ca3f7dc8be940206 (diff)
PM/Hibernate: Rework shrinking of memory
Rework swsusp_shrink_memory() so that it calls shrink_all_memory() just once to make some room for the image and then allocates memory to apply more pressure to the memory management subsystem, if necessary. Unfortunately, we don't seem to be able to drop shrink_all_memory() entirely just yet, because that would lead to huge performance regressions in some test cases. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz>
-rw-r--r--kernel/power/snapshot.c205
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 */
1080static 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;
1079static inline unsigned long __shrink_memory(long tmp) 1092}
1093
1094static 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
1100static 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 */
1108static 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
1115static 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 */
1124static inline unsigned long preallocate_image_highmem(unsigned long nr_pages)
1125{
1126 return 0;
1127}
1128
1129static 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 */
1086int swsusp_shrink_memory(void) 1157int 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;