aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-09-11 18:50:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-09-11 18:50:53 -0400
commit84e1d836ef0759a152578a961894824bde89596f (patch)
tree47c439bfdc9e5ea91f9a71235d336257555fad78 /kernel
parent20f4cad6b247160055915db4f4aaeda82e6c50ed (diff)
parent6715045ddc7472a22be5e49d4047d2d89b391f45 (diff)
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: Avoid hitting OOM during preallocation of memory PM QoS: Correct pr_debug() misuse and improve parameter checks PM: Prevent waiting forever on asynchronous resume after failing suspend
Diffstat (limited to 'kernel')
-rw-r--r--kernel/pm_qos_params.c4
-rw-r--r--kernel/power/snapshot.c85
2 files changed, 68 insertions, 21 deletions
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index b7e4c362361b..645e541a45f6 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -389,10 +389,12 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
389 } else if (count == 11) { /* len('0x12345678/0') */ 389 } else if (count == 11) { /* len('0x12345678/0') */
390 if (copy_from_user(ascii_value, buf, 11)) 390 if (copy_from_user(ascii_value, buf, 11))
391 return -EFAULT; 391 return -EFAULT;
392 if (strlen(ascii_value) != 10)
393 return -EINVAL;
392 x = sscanf(ascii_value, "%x", &value); 394 x = sscanf(ascii_value, "%x", &value);
393 if (x != 1) 395 if (x != 1)
394 return -EINVAL; 396 return -EINVAL;
395 pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value); 397 pr_debug("%s, %d, 0x%x\n", ascii_value, x, value);
396 } else 398 } else
397 return -EINVAL; 399 return -EINVAL;
398 400
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index f6cd6faf84fd..d3f795f01bbc 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1121,9 +1121,19 @@ static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask)
1121 return nr_alloc; 1121 return nr_alloc;
1122} 1122}
1123 1123
1124static unsigned long preallocate_image_memory(unsigned long nr_pages) 1124static unsigned long preallocate_image_memory(unsigned long nr_pages,
1125 unsigned long avail_normal)
1125{ 1126{
1126 return preallocate_image_pages(nr_pages, GFP_IMAGE); 1127 unsigned long alloc;
1128
1129 if (avail_normal <= alloc_normal)
1130 return 0;
1131
1132 alloc = avail_normal - alloc_normal;
1133 if (nr_pages < alloc)
1134 alloc = nr_pages;
1135
1136 return preallocate_image_pages(alloc, GFP_IMAGE);
1127} 1137}
1128 1138
1129#ifdef CONFIG_HIGHMEM 1139#ifdef CONFIG_HIGHMEM
@@ -1169,15 +1179,22 @@ static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages,
1169 */ 1179 */
1170static void free_unnecessary_pages(void) 1180static void free_unnecessary_pages(void)
1171{ 1181{
1172 unsigned long save_highmem, to_free_normal, to_free_highmem; 1182 unsigned long save, to_free_normal, to_free_highmem;
1173 1183
1174 to_free_normal = alloc_normal - count_data_pages(); 1184 save = count_data_pages();
1175 save_highmem = count_highmem_pages(); 1185 if (alloc_normal >= save) {
1176 if (alloc_highmem > save_highmem) { 1186 to_free_normal = alloc_normal - save;
1177 to_free_highmem = alloc_highmem - save_highmem; 1187 save = 0;
1188 } else {
1189 to_free_normal = 0;
1190 save -= alloc_normal;
1191 }
1192 save += count_highmem_pages();
1193 if (alloc_highmem >= save) {
1194 to_free_highmem = alloc_highmem - save;
1178 } else { 1195 } else {
1179 to_free_highmem = 0; 1196 to_free_highmem = 0;
1180 to_free_normal -= save_highmem - alloc_highmem; 1197 to_free_normal -= save - alloc_highmem;
1181 } 1198 }
1182 1199
1183 memory_bm_position_reset(&copy_bm); 1200 memory_bm_position_reset(&copy_bm);
@@ -1258,7 +1275,7 @@ int hibernate_preallocate_memory(void)
1258{ 1275{
1259 struct zone *zone; 1276 struct zone *zone;
1260 unsigned long saveable, size, max_size, count, highmem, pages = 0; 1277 unsigned long saveable, size, max_size, count, highmem, pages = 0;
1261 unsigned long alloc, save_highmem, pages_highmem; 1278 unsigned long alloc, save_highmem, pages_highmem, avail_normal;
1262 struct timeval start, stop; 1279 struct timeval start, stop;
1263 int error; 1280 int error;
1264 1281
@@ -1295,6 +1312,7 @@ int hibernate_preallocate_memory(void)
1295 else 1312 else
1296 count += zone_page_state(zone, NR_FREE_PAGES); 1313 count += zone_page_state(zone, NR_FREE_PAGES);
1297 } 1314 }
1315 avail_normal = count;
1298 count += highmem; 1316 count += highmem;
1299 count -= totalreserve_pages; 1317 count -= totalreserve_pages;
1300 1318
@@ -1309,12 +1327,21 @@ int hibernate_preallocate_memory(void)
1309 */ 1327 */
1310 if (size >= saveable) { 1328 if (size >= saveable) {
1311 pages = preallocate_image_highmem(save_highmem); 1329 pages = preallocate_image_highmem(save_highmem);
1312 pages += preallocate_image_memory(saveable - pages); 1330 pages += preallocate_image_memory(saveable - pages, avail_normal);
1313 goto out; 1331 goto out;
1314 } 1332 }
1315 1333
1316 /* Estimate the minimum size of the image. */ 1334 /* Estimate the minimum size of the image. */
1317 pages = minimum_image_size(saveable); 1335 pages = minimum_image_size(saveable);
1336 /*
1337 * To avoid excessive pressure on the normal zone, leave room in it to
1338 * accommodate an image of the minimum size (unless it's already too
1339 * small, in which case don't preallocate pages from it at all).
1340 */
1341 if (avail_normal > pages)
1342 avail_normal -= pages;
1343 else
1344 avail_normal = 0;
1318 if (size < pages) 1345 if (size < pages)
1319 size = min_t(unsigned long, pages, max_size); 1346 size = min_t(unsigned long, pages, max_size);
1320 1347
@@ -1335,16 +1362,34 @@ int hibernate_preallocate_memory(void)
1335 */ 1362 */
1336 pages_highmem = preallocate_image_highmem(highmem / 2); 1363 pages_highmem = preallocate_image_highmem(highmem / 2);
1337 alloc = (count - max_size) - pages_highmem; 1364 alloc = (count - max_size) - pages_highmem;
1338 pages = preallocate_image_memory(alloc); 1365 pages = preallocate_image_memory(alloc, avail_normal);
1339 if (pages < alloc) 1366 if (pages < alloc) {
1340 goto err_out; 1367 /* We have exhausted non-highmem pages, try highmem. */
1341 size = max_size - size; 1368 alloc -= pages;
1342 alloc = size; 1369 pages += pages_highmem;
1343 size = preallocate_highmem_fraction(size, highmem, count); 1370 pages_highmem = preallocate_image_highmem(alloc);
1344 pages_highmem += size; 1371 if (pages_highmem < alloc)
1345 alloc -= size; 1372 goto err_out;
1346 pages += preallocate_image_memory(alloc); 1373 pages += pages_highmem;
1347 pages += pages_highmem; 1374 /*
1375 * size is the desired number of saveable pages to leave in
1376 * memory, so try to preallocate (all memory - size) pages.
1377 */
1378 alloc = (count - pages) - size;
1379 pages += preallocate_image_highmem(alloc);
1380 } else {
1381 /*
1382 * There are approximately max_size saveable pages at this point
1383 * and we want to reduce this number down to size.
1384 */
1385 alloc = max_size - size;
1386 size = preallocate_highmem_fraction(alloc, highmem, count);
1387 pages_highmem += size;
1388 alloc -= size;
1389 size = preallocate_image_memory(alloc, avail_normal);
1390 pages_highmem += preallocate_image_highmem(alloc - size);
1391 pages += pages_highmem + size;
1392 }
1348 1393
1349 /* 1394 /*
1350 * We only need as many page frames for the image as there are saveable 1395 * We only need as many page frames for the image as there are saveable