aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-03-09 13:55:17 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-03-09 13:55:17 -0500
commitb675b3667f6729dcd1036a2a129b35445947f905 (patch)
tree0d58791e9063d3ca2c352da6f3e7df2bdb876f9d /kernel/power
parent104a5f3cad8f2f27cadbdf0029400ecd9e17ccc0 (diff)
parent192cfd58774b4d17b2fe8bdc77d89c2ef4e0591d (diff)
Merge commit 'v3.3-rc6' into next
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/hibernate.c104
-rw-r--r--kernel/power/main.c10
-rw-r--r--kernel/power/power.h26
-rw-r--r--kernel/power/process.c93
-rw-r--r--kernel/power/snapshot.c9
-rw-r--r--kernel/power/suspend.c12
-rw-r--r--kernel/power/swap.c14
-rw-r--r--kernel/power/user.c195
8 files changed, 227 insertions, 236 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 196c01268ebd..6d6d28870335 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -43,8 +43,6 @@ int in_suspend __nosavedata;
43enum { 43enum {
44 HIBERNATION_INVALID, 44 HIBERNATION_INVALID,
45 HIBERNATION_PLATFORM, 45 HIBERNATION_PLATFORM,
46 HIBERNATION_TEST,
47 HIBERNATION_TESTPROC,
48 HIBERNATION_SHUTDOWN, 46 HIBERNATION_SHUTDOWN,
49 HIBERNATION_REBOOT, 47 HIBERNATION_REBOOT,
50 /* keep last */ 48 /* keep last */
@@ -55,7 +53,7 @@ enum {
55 53
56static int hibernation_mode = HIBERNATION_SHUTDOWN; 54static int hibernation_mode = HIBERNATION_SHUTDOWN;
57 55
58static bool freezer_test_done; 56bool freezer_test_done;
59 57
60static const struct platform_hibernation_ops *hibernation_ops; 58static const struct platform_hibernation_ops *hibernation_ops;
61 59
@@ -71,14 +69,14 @@ void hibernation_set_ops(const struct platform_hibernation_ops *ops)
71 WARN_ON(1); 69 WARN_ON(1);
72 return; 70 return;
73 } 71 }
74 mutex_lock(&pm_mutex); 72 lock_system_sleep();
75 hibernation_ops = ops; 73 hibernation_ops = ops;
76 if (ops) 74 if (ops)
77 hibernation_mode = HIBERNATION_PLATFORM; 75 hibernation_mode = HIBERNATION_PLATFORM;
78 else if (hibernation_mode == HIBERNATION_PLATFORM) 76 else if (hibernation_mode == HIBERNATION_PLATFORM)
79 hibernation_mode = HIBERNATION_SHUTDOWN; 77 hibernation_mode = HIBERNATION_SHUTDOWN;
80 78
81 mutex_unlock(&pm_mutex); 79 unlock_system_sleep();
82} 80}
83 81
84static bool entering_platform_hibernation; 82static bool entering_platform_hibernation;
@@ -96,15 +94,6 @@ static void hibernation_debug_sleep(void)
96 mdelay(5000); 94 mdelay(5000);
97} 95}
98 96
99static int hibernation_testmode(int mode)
100{
101 if (hibernation_mode == mode) {
102 hibernation_debug_sleep();
103 return 1;
104 }
105 return 0;
106}
107
108static int hibernation_test(int level) 97static int hibernation_test(int level)
109{ 98{
110 if (pm_test_level == level) { 99 if (pm_test_level == level) {
@@ -114,7 +103,6 @@ static int hibernation_test(int level)
114 return 0; 103 return 0;
115} 104}
116#else /* !CONFIG_PM_DEBUG */ 105#else /* !CONFIG_PM_DEBUG */
117static int hibernation_testmode(int mode) { return 0; }
118static int hibernation_test(int level) { return 0; } 106static int hibernation_test(int level) { return 0; }
119#endif /* !CONFIG_PM_DEBUG */ 107#endif /* !CONFIG_PM_DEBUG */
120 108
@@ -278,8 +266,7 @@ static int create_image(int platform_mode)
278 goto Platform_finish; 266 goto Platform_finish;
279 267
280 error = disable_nonboot_cpus(); 268 error = disable_nonboot_cpus();
281 if (error || hibernation_test(TEST_CPUS) 269 if (error || hibernation_test(TEST_CPUS))
282 || hibernation_testmode(HIBERNATION_TEST))
283 goto Enable_cpus; 270 goto Enable_cpus;
284 271
285 local_irq_disable(); 272 local_irq_disable();
@@ -333,7 +320,7 @@ static int create_image(int platform_mode)
333 */ 320 */
334int hibernation_snapshot(int platform_mode) 321int hibernation_snapshot(int platform_mode)
335{ 322{
336 pm_message_t msg = PMSG_RECOVER; 323 pm_message_t msg;
337 int error; 324 int error;
338 325
339 error = platform_begin(platform_mode); 326 error = platform_begin(platform_mode);
@@ -347,39 +334,40 @@ int hibernation_snapshot(int platform_mode)
347 334
348 error = freeze_kernel_threads(); 335 error = freeze_kernel_threads();
349 if (error) 336 if (error)
350 goto Close; 337 goto Cleanup;
351 338
352 if (hibernation_test(TEST_FREEZER) || 339 if (hibernation_test(TEST_FREEZER)) {
353 hibernation_testmode(HIBERNATION_TESTPROC)) {
354 340
355 /* 341 /*
356 * Indicate to the caller that we are returning due to a 342 * Indicate to the caller that we are returning due to a
357 * successful freezer test. 343 * successful freezer test.
358 */ 344 */
359 freezer_test_done = true; 345 freezer_test_done = true;
360 goto Close; 346 goto Cleanup;
361 } 347 }
362 348
363 error = dpm_prepare(PMSG_FREEZE); 349 error = dpm_prepare(PMSG_FREEZE);
364 if (error) 350 if (error) {
365 goto Complete_devices; 351 dpm_complete(PMSG_RECOVER);
352 goto Cleanup;
353 }
366 354
367 suspend_console(); 355 suspend_console();
368 pm_restrict_gfp_mask(); 356 pm_restrict_gfp_mask();
357
369 error = dpm_suspend(PMSG_FREEZE); 358 error = dpm_suspend(PMSG_FREEZE);
370 if (error)
371 goto Recover_platform;
372 359
373 if (hibernation_test(TEST_DEVICES)) 360 if (error || hibernation_test(TEST_DEVICES))
374 goto Recover_platform; 361 platform_recover(platform_mode);
362 else
363 error = create_image(platform_mode);
375 364
376 error = create_image(platform_mode);
377 /* 365 /*
378 * Control returns here (1) after the image has been created or the 366 * In the case that we call create_image() above, the control
367 * returns here (1) after the image has been created or the
379 * image creation has failed and (2) after a successful restore. 368 * image creation has failed and (2) after a successful restore.
380 */ 369 */
381 370
382 Resume_devices:
383 /* We may need to release the preallocated image pages here. */ 371 /* We may need to release the preallocated image pages here. */
384 if (error || !in_suspend) 372 if (error || !in_suspend)
385 swsusp_free(); 373 swsusp_free();
@@ -391,17 +379,15 @@ int hibernation_snapshot(int platform_mode)
391 pm_restore_gfp_mask(); 379 pm_restore_gfp_mask();
392 380
393 resume_console(); 381 resume_console();
394
395 Complete_devices:
396 dpm_complete(msg); 382 dpm_complete(msg);
397 383
398 Close: 384 Close:
399 platform_end(platform_mode); 385 platform_end(platform_mode);
400 return error; 386 return error;
401 387
402 Recover_platform: 388 Cleanup:
403 platform_recover(platform_mode); 389 swsusp_free();
404 goto Resume_devices; 390 goto Close;
405} 391}
406 392
407/** 393/**
@@ -586,9 +572,6 @@ int hibernation_platform_enter(void)
586static void power_down(void) 572static void power_down(void)
587{ 573{
588 switch (hibernation_mode) { 574 switch (hibernation_mode) {
589 case HIBERNATION_TEST:
590 case HIBERNATION_TESTPROC:
591 break;
592 case HIBERNATION_REBOOT: 575 case HIBERNATION_REBOOT:
593 kernel_restart(NULL); 576 kernel_restart(NULL);
594 break; 577 break;
@@ -607,17 +590,6 @@ static void power_down(void)
607 while(1); 590 while(1);
608} 591}
609 592
610static int prepare_processes(void)
611{
612 int error = 0;
613
614 if (freeze_processes()) {
615 error = -EBUSY;
616 thaw_processes();
617 }
618 return error;
619}
620
621/** 593/**
622 * hibernate - Carry out system hibernation, including saving the image. 594 * hibernate - Carry out system hibernation, including saving the image.
623 */ 595 */
@@ -625,7 +597,7 @@ int hibernate(void)
625{ 597{
626 int error; 598 int error;
627 599
628 mutex_lock(&pm_mutex); 600 lock_system_sleep();
629 /* The snapshot device should not be opened while we're running */ 601 /* The snapshot device should not be opened while we're running */
630 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { 602 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
631 error = -EBUSY; 603 error = -EBUSY;
@@ -650,7 +622,7 @@ int hibernate(void)
650 sys_sync(); 622 sys_sync();
651 printk("done.\n"); 623 printk("done.\n");
652 624
653 error = prepare_processes(); 625 error = freeze_processes();
654 if (error) 626 if (error)
655 goto Finish; 627 goto Finish;
656 628
@@ -693,7 +665,7 @@ int hibernate(void)
693 pm_restore_console(); 665 pm_restore_console();
694 atomic_inc(&snapshot_device_available); 666 atomic_inc(&snapshot_device_available);
695 Unlock: 667 Unlock:
696 mutex_unlock(&pm_mutex); 668 unlock_system_sleep();
697 return error; 669 return error;
698} 670}
699 671
@@ -807,11 +779,13 @@ static int software_resume(void)
807 goto close_finish; 779 goto close_finish;
808 780
809 error = create_basic_memory_bitmaps(); 781 error = create_basic_memory_bitmaps();
810 if (error) 782 if (error) {
783 usermodehelper_enable();
811 goto close_finish; 784 goto close_finish;
785 }
812 786
813 pr_debug("PM: Preparing processes for restore.\n"); 787 pr_debug("PM: Preparing processes for restore.\n");
814 error = prepare_processes(); 788 error = freeze_processes();
815 if (error) { 789 if (error) {
816 swsusp_close(FMODE_READ); 790 swsusp_close(FMODE_READ);
817 goto Done; 791 goto Done;
@@ -851,8 +825,6 @@ static const char * const hibernation_modes[] = {
851 [HIBERNATION_PLATFORM] = "platform", 825 [HIBERNATION_PLATFORM] = "platform",
852 [HIBERNATION_SHUTDOWN] = "shutdown", 826 [HIBERNATION_SHUTDOWN] = "shutdown",
853 [HIBERNATION_REBOOT] = "reboot", 827 [HIBERNATION_REBOOT] = "reboot",
854 [HIBERNATION_TEST] = "test",
855 [HIBERNATION_TESTPROC] = "testproc",
856}; 828};
857 829
858/* 830/*
@@ -861,17 +833,15 @@ static const char * const hibernation_modes[] = {
861 * Hibernation can be handled in several ways. There are a few different ways 833 * Hibernation can be handled in several ways. There are a few different ways
862 * to put the system into the sleep state: using the platform driver (e.g. ACPI 834 * to put the system into the sleep state: using the platform driver (e.g. ACPI
863 * or other hibernation_ops), powering it off or rebooting it (for testing 835 * or other hibernation_ops), powering it off or rebooting it (for testing
864 * mostly), or using one of the two available test modes. 836 * mostly).
865 * 837 *
866 * The sysfs file /sys/power/disk provides an interface for selecting the 838 * The sysfs file /sys/power/disk provides an interface for selecting the
867 * hibernation mode to use. Reading from this file causes the available modes 839 * hibernation mode to use. Reading from this file causes the available modes
868 * to be printed. There are 5 modes that can be supported: 840 * to be printed. There are 3 modes that can be supported:
869 * 841 *
870 * 'platform' 842 * 'platform'
871 * 'shutdown' 843 * 'shutdown'
872 * 'reboot' 844 * 'reboot'
873 * 'test'
874 * 'testproc'
875 * 845 *
876 * If a platform hibernation driver is in use, 'platform' will be supported 846 * If a platform hibernation driver is in use, 'platform' will be supported
877 * and will be used by default. Otherwise, 'shutdown' will be used by default. 847 * and will be used by default. Otherwise, 'shutdown' will be used by default.
@@ -895,8 +865,6 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
895 switch (i) { 865 switch (i) {
896 case HIBERNATION_SHUTDOWN: 866 case HIBERNATION_SHUTDOWN:
897 case HIBERNATION_REBOOT: 867 case HIBERNATION_REBOOT:
898 case HIBERNATION_TEST:
899 case HIBERNATION_TESTPROC:
900 break; 868 break;
901 case HIBERNATION_PLATFORM: 869 case HIBERNATION_PLATFORM:
902 if (hibernation_ops) 870 if (hibernation_ops)
@@ -925,7 +893,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
925 p = memchr(buf, '\n', n); 893 p = memchr(buf, '\n', n);
926 len = p ? p - buf : n; 894 len = p ? p - buf : n;
927 895
928 mutex_lock(&pm_mutex); 896 lock_system_sleep();
929 for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { 897 for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
930 if (len == strlen(hibernation_modes[i]) 898 if (len == strlen(hibernation_modes[i])
931 && !strncmp(buf, hibernation_modes[i], len)) { 899 && !strncmp(buf, hibernation_modes[i], len)) {
@@ -937,8 +905,6 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
937 switch (mode) { 905 switch (mode) {
938 case HIBERNATION_SHUTDOWN: 906 case HIBERNATION_SHUTDOWN:
939 case HIBERNATION_REBOOT: 907 case HIBERNATION_REBOOT:
940 case HIBERNATION_TEST:
941 case HIBERNATION_TESTPROC:
942 hibernation_mode = mode; 908 hibernation_mode = mode;
943 break; 909 break;
944 case HIBERNATION_PLATFORM: 910 case HIBERNATION_PLATFORM:
@@ -953,7 +919,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
953 if (!error) 919 if (!error)
954 pr_debug("PM: Hibernation mode set to '%s'\n", 920 pr_debug("PM: Hibernation mode set to '%s'\n",
955 hibernation_modes[mode]); 921 hibernation_modes[mode]);
956 mutex_unlock(&pm_mutex); 922 unlock_system_sleep();
957 return error ? error : n; 923 return error ? error : n;
958} 924}
959 925
@@ -980,9 +946,9 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
980 if (maj != MAJOR(res) || min != MINOR(res)) 946 if (maj != MAJOR(res) || min != MINOR(res))
981 goto out; 947 goto out;
982 948
983 mutex_lock(&pm_mutex); 949 lock_system_sleep();
984 swsusp_resume_device = res; 950 swsusp_resume_device = res;
985 mutex_unlock(&pm_mutex); 951 unlock_system_sleep();
986 printk(KERN_INFO "PM: Starting manual resume from disk\n"); 952 printk(KERN_INFO "PM: Starting manual resume from disk\n");
987 noresume = 0; 953 noresume = 0;
988 software_resume(); 954 software_resume();
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 36e0f0903c32..9824b41e5a18 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (c) 2003 Patrick Mochel 4 * Copyright (c) 2003 Patrick Mochel
5 * Copyright (c) 2003 Open Source Development Lab 5 * Copyright (c) 2003 Open Source Development Lab
6 * 6 *
7 * This file is released under the GPLv2 7 * This file is released under the GPLv2
8 * 8 *
9 */ 9 */
@@ -116,7 +116,7 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
116 p = memchr(buf, '\n', n); 116 p = memchr(buf, '\n', n);
117 len = p ? p - buf : n; 117 len = p ? p - buf : n;
118 118
119 mutex_lock(&pm_mutex); 119 lock_system_sleep();
120 120
121 level = TEST_FIRST; 121 level = TEST_FIRST;
122 for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++) 122 for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
@@ -126,7 +126,7 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
126 break; 126 break;
127 } 127 }
128 128
129 mutex_unlock(&pm_mutex); 129 unlock_system_sleep();
130 130
131 return error ? error : n; 131 return error ? error : n;
132} 132}
@@ -240,7 +240,7 @@ struct kobject *power_kobj;
240 * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and 240 * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
241 * 'disk' (Suspend-to-Disk). 241 * 'disk' (Suspend-to-Disk).
242 * 242 *
243 * store() accepts one of those strings, translates it into the 243 * store() accepts one of those strings, translates it into the
244 * proper enumerated value, and initiates a suspend transition. 244 * proper enumerated value, and initiates a suspend transition.
245 */ 245 */
246static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, 246static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -282,7 +282,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
282 /* First, check if we are requested to hibernate */ 282 /* First, check if we are requested to hibernate */
283 if (len == 4 && !strncmp(buf, "disk", len)) { 283 if (len == 4 && !strncmp(buf, "disk", len)) {
284 error = hibernate(); 284 error = hibernate();
285 goto Exit; 285 goto Exit;
286 } 286 }
287 287
288#ifdef CONFIG_SUSPEND 288#ifdef CONFIG_SUSPEND
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 23a2db1ec442..21724eee5206 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -50,6 +50,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
50#define SPARE_PAGES ((1024 * 1024) >> PAGE_SHIFT) 50#define SPARE_PAGES ((1024 * 1024) >> PAGE_SHIFT)
51 51
52/* kernel/power/hibernate.c */ 52/* kernel/power/hibernate.c */
53extern bool freezer_test_done;
54
53extern int hibernation_snapshot(int platform_mode); 55extern int hibernation_snapshot(int platform_mode);
54extern int hibernation_restore(int platform_mode); 56extern int hibernation_restore(int platform_mode);
55extern int hibernation_platform_enter(void); 57extern int hibernation_platform_enter(void);
@@ -229,8 +231,28 @@ extern int pm_test_level;
229#ifdef CONFIG_SUSPEND_FREEZER 231#ifdef CONFIG_SUSPEND_FREEZER
230static inline int suspend_freeze_processes(void) 232static inline int suspend_freeze_processes(void)
231{ 233{
232 int error = freeze_processes(); 234 int error;
233 return error ? : freeze_kernel_threads(); 235
236 error = freeze_processes();
237
238 /*
239 * freeze_processes() automatically thaws every task if freezing
240 * fails. So we need not do anything extra upon error.
241 */
242 if (error)
243 goto Finish;
244
245 error = freeze_kernel_threads();
246
247 /*
248 * freeze_kernel_threads() thaws only kernel threads upon freezing
249 * failure. So we have to thaw the userspace tasks ourselves.
250 */
251 if (error)
252 thaw_processes();
253
254 Finish:
255 return error;
234} 256}
235 257
236static inline void suspend_thaw_processes(void) 258static inline void suspend_thaw_processes(void)
diff --git a/kernel/power/process.c b/kernel/power/process.c
index addbbe5531bc..7e426459e60a 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -22,16 +22,7 @@
22 */ 22 */
23#define TIMEOUT (20 * HZ) 23#define TIMEOUT (20 * HZ)
24 24
25static inline int freezable(struct task_struct * p) 25static int try_to_freeze_tasks(bool user_only)
26{
27 if ((p == current) ||
28 (p->flags & PF_NOFREEZE) ||
29 (p->exit_state != 0))
30 return 0;
31 return 1;
32}
33
34static int try_to_freeze_tasks(bool sig_only)
35{ 26{
36 struct task_struct *g, *p; 27 struct task_struct *g, *p;
37 unsigned long end_time; 28 unsigned long end_time;
@@ -46,17 +37,14 @@ static int try_to_freeze_tasks(bool sig_only)
46 37
47 end_time = jiffies + TIMEOUT; 38 end_time = jiffies + TIMEOUT;
48 39
49 if (!sig_only) 40 if (!user_only)
50 freeze_workqueues_begin(); 41 freeze_workqueues_begin();
51 42
52 while (true) { 43 while (true) {
53 todo = 0; 44 todo = 0;
54 read_lock(&tasklist_lock); 45 read_lock(&tasklist_lock);
55 do_each_thread(g, p) { 46 do_each_thread(g, p) {
56 if (frozen(p) || !freezable(p)) 47 if (p == current || !freeze_task(p))
57 continue;
58
59 if (!freeze_task(p, sig_only))
60 continue; 48 continue;
61 49
62 /* 50 /*
@@ -77,7 +65,7 @@ static int try_to_freeze_tasks(bool sig_only)
77 } while_each_thread(g, p); 65 } while_each_thread(g, p);
78 read_unlock(&tasklist_lock); 66 read_unlock(&tasklist_lock);
79 67
80 if (!sig_only) { 68 if (!user_only) {
81 wq_busy = freeze_workqueues_busy(); 69 wq_busy = freeze_workqueues_busy();
82 todo += wq_busy; 70 todo += wq_busy;
83 } 71 }
@@ -103,11 +91,6 @@ static int try_to_freeze_tasks(bool sig_only)
103 elapsed_csecs = elapsed_csecs64; 91 elapsed_csecs = elapsed_csecs64;
104 92
105 if (todo) { 93 if (todo) {
106 /* This does not unfreeze processes that are already frozen
107 * (we have slightly ugly calling convention in that respect,
108 * and caller must call thaw_processes() if something fails),
109 * but it cleans up leftover PF_FREEZE requests.
110 */
111 printk("\n"); 94 printk("\n");
112 printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " 95 printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
113 "(%d tasks refusing to freeze, wq_busy=%d):\n", 96 "(%d tasks refusing to freeze, wq_busy=%d):\n",
@@ -115,15 +98,11 @@ static int try_to_freeze_tasks(bool sig_only)
115 elapsed_csecs / 100, elapsed_csecs % 100, 98 elapsed_csecs / 100, elapsed_csecs % 100,
116 todo - wq_busy, wq_busy); 99 todo - wq_busy, wq_busy);
117 100
118 thaw_workqueues();
119
120 read_lock(&tasklist_lock); 101 read_lock(&tasklist_lock);
121 do_each_thread(g, p) { 102 do_each_thread(g, p) {
122 task_lock(p); 103 if (!wakeup && !freezer_should_skip(p) &&
123 if (!wakeup && freezing(p) && !freezer_should_skip(p)) 104 p != current && freezing(p) && !frozen(p))
124 sched_show_task(p); 105 sched_show_task(p);
125 cancel_freezing(p);
126 task_unlock(p);
127 } while_each_thread(g, p); 106 } while_each_thread(g, p);
128 read_unlock(&tasklist_lock); 107 read_unlock(&tasklist_lock);
129 } else { 108 } else {
@@ -136,12 +115,18 @@ static int try_to_freeze_tasks(bool sig_only)
136 115
137/** 116/**
138 * freeze_processes - Signal user space processes to enter the refrigerator. 117 * freeze_processes - Signal user space processes to enter the refrigerator.
118 *
119 * On success, returns 0. On failure, -errno and system is fully thawed.
139 */ 120 */
140int freeze_processes(void) 121int freeze_processes(void)
141{ 122{
142 int error; 123 int error;
143 124
125 if (!pm_freezing)
126 atomic_inc(&system_freezing_cnt);
127
144 printk("Freezing user space processes ... "); 128 printk("Freezing user space processes ... ");
129 pm_freezing = true;
145 error = try_to_freeze_tasks(true); 130 error = try_to_freeze_tasks(true);
146 if (!error) { 131 if (!error) {
147 printk("done."); 132 printk("done.");
@@ -150,17 +135,25 @@ int freeze_processes(void)
150 printk("\n"); 135 printk("\n");
151 BUG_ON(in_atomic()); 136 BUG_ON(in_atomic());
152 137
138 if (error)
139 thaw_processes();
153 return error; 140 return error;
154} 141}
155 142
156/** 143/**
157 * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. 144 * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
145 *
146 * On success, returns 0. On failure, -errno and only the kernel threads are
147 * thawed, so as to give a chance to the caller to do additional cleanups
148 * (if any) before thawing the userspace tasks. So, it is the responsibility
149 * of the caller to thaw the userspace tasks, when the time is right.
158 */ 150 */
159int freeze_kernel_threads(void) 151int freeze_kernel_threads(void)
160{ 152{
161 int error; 153 int error;
162 154
163 printk("Freezing remaining freezable tasks ... "); 155 printk("Freezing remaining freezable tasks ... ");
156 pm_nosig_freezing = true;
164 error = try_to_freeze_tasks(false); 157 error = try_to_freeze_tasks(false);
165 if (!error) 158 if (!error)
166 printk("done."); 159 printk("done.");
@@ -168,38 +161,52 @@ int freeze_kernel_threads(void)
168 printk("\n"); 161 printk("\n");
169 BUG_ON(in_atomic()); 162 BUG_ON(in_atomic());
170 163
164 if (error)
165 thaw_kernel_threads();
171 return error; 166 return error;
172} 167}
173 168
174static void thaw_tasks(bool nosig_only) 169void thaw_processes(void)
175{ 170{
176 struct task_struct *g, *p; 171 struct task_struct *g, *p;
177 172
178 read_lock(&tasklist_lock); 173 if (pm_freezing)
179 do_each_thread(g, p) { 174 atomic_dec(&system_freezing_cnt);
180 if (!freezable(p)) 175 pm_freezing = false;
181 continue; 176 pm_nosig_freezing = false;
182 177
183 if (nosig_only && should_send_signal(p)) 178 oom_killer_enable();
184 continue; 179
180 printk("Restarting tasks ... ");
185 181
186 if (cgroup_freezing_or_frozen(p)) 182 thaw_workqueues();
187 continue;
188 183
189 thaw_process(p); 184 read_lock(&tasklist_lock);
185 do_each_thread(g, p) {
186 __thaw_task(p);
190 } while_each_thread(g, p); 187 } while_each_thread(g, p);
191 read_unlock(&tasklist_lock); 188 read_unlock(&tasklist_lock);
189
190 schedule();
191 printk("done.\n");
192} 192}
193 193
194void thaw_processes(void) 194void thaw_kernel_threads(void)
195{ 195{
196 oom_killer_enable(); 196 struct task_struct *g, *p;
197
198 pm_nosig_freezing = false;
199 printk("Restarting kernel threads ... ");
197 200
198 printk("Restarting tasks ... ");
199 thaw_workqueues(); 201 thaw_workqueues();
200 thaw_tasks(true); 202
201 thaw_tasks(false); 203 read_lock(&tasklist_lock);
204 do_each_thread(g, p) {
205 if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
206 __thaw_task(p);
207 } while_each_thread(g, p);
208 read_unlock(&tasklist_lock);
209
202 schedule(); 210 schedule();
203 printk("done.\n"); 211 printk("done.\n");
204} 212}
205
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index cbe2c1441392..6a768e537001 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -812,7 +812,8 @@ unsigned int snapshot_additional_pages(struct zone *zone)
812 unsigned int res; 812 unsigned int res;
813 813
814 res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK); 814 res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK);
815 res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE); 815 res += DIV_ROUND_UP(res * sizeof(struct bm_block),
816 LINKED_PAGE_DATA_SIZE);
816 return 2 * res; 817 return 2 * res;
817} 818}
818 819
@@ -858,6 +859,9 @@ static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)
858 PageReserved(page)) 859 PageReserved(page))
859 return NULL; 860 return NULL;
860 861
862 if (page_is_guard(page))
863 return NULL;
864
861 return page; 865 return page;
862} 866}
863 867
@@ -920,6 +924,9 @@ static struct page *saveable_page(struct zone *zone, unsigned long pfn)
920 && (!kernel_page_present(page) || pfn_is_nosave(pfn))) 924 && (!kernel_page_present(page) || pfn_is_nosave(pfn)))
921 return NULL; 925 return NULL;
922 926
927 if (page_is_guard(page))
928 return NULL;
929
923 return page; 930 return page;
924} 931}
925 932
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 4953dc054c53..4fd51beed879 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -42,9 +42,9 @@ static const struct platform_suspend_ops *suspend_ops;
42 */ 42 */
43void suspend_set_ops(const struct platform_suspend_ops *ops) 43void suspend_set_ops(const struct platform_suspend_ops *ops)
44{ 44{
45 mutex_lock(&pm_mutex); 45 lock_system_sleep();
46 suspend_ops = ops; 46 suspend_ops = ops;
47 mutex_unlock(&pm_mutex); 47 unlock_system_sleep();
48} 48}
49EXPORT_SYMBOL_GPL(suspend_set_ops); 49EXPORT_SYMBOL_GPL(suspend_set_ops);
50 50
@@ -106,13 +106,11 @@ static int suspend_prepare(void)
106 goto Finish; 106 goto Finish;
107 107
108 error = suspend_freeze_processes(); 108 error = suspend_freeze_processes();
109 if (error) { 109 if (!error)
110 suspend_stats.failed_freeze++;
111 dpm_save_failed_step(SUSPEND_FREEZE);
112 } else
113 return 0; 110 return 0;
114 111
115 suspend_thaw_processes(); 112 suspend_stats.failed_freeze++;
113 dpm_save_failed_step(SUSPEND_FREEZE);
116 usermodehelper_enable(); 114 usermodehelper_enable();
117 Finish: 115 Finish:
118 pm_notifier_call_chain(PM_POST_SUSPEND); 116 pm_notifier_call_chain(PM_POST_SUSPEND);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 11a594c4ba25..8742fd013a94 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -18,7 +18,6 @@
18#include <linux/bitops.h> 18#include <linux/bitops.h>
19#include <linux/genhd.h> 19#include <linux/genhd.h>
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/buffer_head.h>
22#include <linux/bio.h> 21#include <linux/bio.h>
23#include <linux/blkdev.h> 22#include <linux/blkdev.h>
24#include <linux/swap.h> 23#include <linux/swap.h>
@@ -774,8 +773,7 @@ static int enough_swap(unsigned int nr_pages, unsigned int flags)
774 773
775 pr_debug("PM: Free swap pages: %u\n", free_swap); 774 pr_debug("PM: Free swap pages: %u\n", free_swap);
776 775
777 required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ? 776 required = PAGES_FOR_IO + nr_pages;
778 nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1);
779 return free_swap > required; 777 return free_swap > required;
780} 778}
781 779
@@ -803,10 +801,12 @@ int swsusp_write(unsigned int flags)
803 printk(KERN_ERR "PM: Cannot get swap writer\n"); 801 printk(KERN_ERR "PM: Cannot get swap writer\n");
804 return error; 802 return error;
805 } 803 }
806 if (!enough_swap(pages, flags)) { 804 if (flags & SF_NOCOMPRESS_MODE) {
807 printk(KERN_ERR "PM: Not enough free swap\n"); 805 if (!enough_swap(pages, flags)) {
808 error = -ENOSPC; 806 printk(KERN_ERR "PM: Not enough free swap\n");
809 goto out_finish; 807 error = -ENOSPC;
808 goto out_finish;
809 }
810 } 810 }
811 memset(&snapshot, 0, sizeof(struct snapshot_handle)); 811 memset(&snapshot, 0, sizeof(struct snapshot_handle));
812 error = snapshot_read_next(&snapshot); 812 error = snapshot_read_next(&snapshot);
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 6d8f535c2b88..3e100075b13c 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -21,6 +21,7 @@
21#include <linux/swapops.h> 21#include <linux/swapops.h>
22#include <linux/pm.h> 22#include <linux/pm.h>
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/compat.h>
24#include <linux/console.h> 25#include <linux/console.h>
25#include <linux/cpu.h> 26#include <linux/cpu.h>
26#include <linux/freezer.h> 27#include <linux/freezer.h>
@@ -30,28 +31,6 @@
30 31
31#include "power.h" 32#include "power.h"
32 33
33/*
34 * NOTE: The SNAPSHOT_SET_SWAP_FILE and SNAPSHOT_PMOPS ioctls are obsolete and
35 * will be removed in the future. They are only preserved here for
36 * compatibility with existing userland utilities.
37 */
38#define SNAPSHOT_SET_SWAP_FILE _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int)
39#define SNAPSHOT_PMOPS _IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int)
40
41#define PMOPS_PREPARE 1
42#define PMOPS_ENTER 2
43#define PMOPS_FINISH 3
44
45/*
46 * NOTE: The following ioctl definitions are wrong and have been replaced with
47 * correct ones. They are only preserved here for compatibility with existing
48 * userland utilities and will be removed in the future.
49 */
50#define SNAPSHOT_ATOMIC_SNAPSHOT _IOW(SNAPSHOT_IOC_MAGIC, 3, void *)
51#define SNAPSHOT_SET_IMAGE_SIZE _IOW(SNAPSHOT_IOC_MAGIC, 6, unsigned long)
52#define SNAPSHOT_AVAIL_SWAP _IOR(SNAPSHOT_IOC_MAGIC, 7, void *)
53#define SNAPSHOT_GET_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 8, void *)
54
55 34
56#define SNAPSHOT_MINOR 231 35#define SNAPSHOT_MINOR 231
57 36
@@ -71,7 +50,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
71 struct snapshot_data *data; 50 struct snapshot_data *data;
72 int error; 51 int error;
73 52
74 mutex_lock(&pm_mutex); 53 lock_system_sleep();
75 54
76 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { 55 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
77 error = -EBUSY; 56 error = -EBUSY;
@@ -123,7 +102,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
123 data->platform_support = 0; 102 data->platform_support = 0;
124 103
125 Unlock: 104 Unlock:
126 mutex_unlock(&pm_mutex); 105 unlock_system_sleep();
127 106
128 return error; 107 return error;
129} 108}
@@ -132,7 +111,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
132{ 111{
133 struct snapshot_data *data; 112 struct snapshot_data *data;
134 113
135 mutex_lock(&pm_mutex); 114 lock_system_sleep();
136 115
137 swsusp_free(); 116 swsusp_free();
138 free_basic_memory_bitmaps(); 117 free_basic_memory_bitmaps();
@@ -146,7 +125,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
146 PM_POST_HIBERNATION : PM_POST_RESTORE); 125 PM_POST_HIBERNATION : PM_POST_RESTORE);
147 atomic_inc(&snapshot_device_available); 126 atomic_inc(&snapshot_device_available);
148 127
149 mutex_unlock(&pm_mutex); 128 unlock_system_sleep();
150 129
151 return 0; 130 return 0;
152} 131}
@@ -158,7 +137,7 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf,
158 ssize_t res; 137 ssize_t res;
159 loff_t pg_offp = *offp & ~PAGE_MASK; 138 loff_t pg_offp = *offp & ~PAGE_MASK;
160 139
161 mutex_lock(&pm_mutex); 140 lock_system_sleep();
162 141
163 data = filp->private_data; 142 data = filp->private_data;
164 if (!data->ready) { 143 if (!data->ready) {
@@ -179,7 +158,7 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf,
179 *offp += res; 158 *offp += res;
180 159
181 Unlock: 160 Unlock:
182 mutex_unlock(&pm_mutex); 161 unlock_system_sleep();
183 162
184 return res; 163 return res;
185} 164}
@@ -191,7 +170,7 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
191 ssize_t res; 170 ssize_t res;
192 loff_t pg_offp = *offp & ~PAGE_MASK; 171 loff_t pg_offp = *offp & ~PAGE_MASK;
193 172
194 mutex_lock(&pm_mutex); 173 lock_system_sleep();
195 174
196 data = filp->private_data; 175 data = filp->private_data;
197 176
@@ -208,20 +187,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
208 if (res > 0) 187 if (res > 0)
209 *offp += res; 188 *offp += res;
210unlock: 189unlock:
211 mutex_unlock(&pm_mutex); 190 unlock_system_sleep();
212 191
213 return res; 192 return res;
214} 193}
215 194
216static void snapshot_deprecated_ioctl(unsigned int cmd)
217{
218 if (printk_ratelimit())
219 printk(KERN_NOTICE "%pf: ioctl '%.8x' is deprecated and will "
220 "be removed soon, update your suspend-to-disk "
221 "utilities\n",
222 __builtin_return_address(0), cmd);
223}
224
225static long snapshot_ioctl(struct file *filp, unsigned int cmd, 195static long snapshot_ioctl(struct file *filp, unsigned int cmd,
226 unsigned long arg) 196 unsigned long arg)
227{ 197{
@@ -257,11 +227,9 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
257 break; 227 break;
258 228
259 error = freeze_processes(); 229 error = freeze_processes();
260 if (error) { 230 if (error)
261 thaw_processes();
262 usermodehelper_enable(); 231 usermodehelper_enable();
263 } 232 else
264 if (!error)
265 data->frozen = 1; 233 data->frozen = 1;
266 break; 234 break;
267 235
@@ -274,8 +242,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
274 data->frozen = 0; 242 data->frozen = 0;
275 break; 243 break;
276 244
277 case SNAPSHOT_ATOMIC_SNAPSHOT:
278 snapshot_deprecated_ioctl(cmd);
279 case SNAPSHOT_CREATE_IMAGE: 245 case SNAPSHOT_CREATE_IMAGE:
280 if (data->mode != O_RDONLY || !data->frozen || data->ready) { 246 if (data->mode != O_RDONLY || !data->frozen || data->ready) {
281 error = -EPERM; 247 error = -EPERM;
@@ -283,10 +249,17 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
283 } 249 }
284 pm_restore_gfp_mask(); 250 pm_restore_gfp_mask();
285 error = hibernation_snapshot(data->platform_support); 251 error = hibernation_snapshot(data->platform_support);
286 if (!error) 252 if (error) {
253 thaw_kernel_threads();
254 } else {
287 error = put_user(in_suspend, (int __user *)arg); 255 error = put_user(in_suspend, (int __user *)arg);
288 if (!error) 256 if (!error && !freezer_test_done)
289 data->ready = 1; 257 data->ready = 1;
258 if (freezer_test_done) {
259 freezer_test_done = false;
260 thaw_kernel_threads();
261 }
262 }
290 break; 263 break;
291 264
292 case SNAPSHOT_ATOMIC_RESTORE: 265 case SNAPSHOT_ATOMIC_RESTORE:
@@ -303,10 +276,17 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
303 swsusp_free(); 276 swsusp_free();
304 memset(&data->handle, 0, sizeof(struct snapshot_handle)); 277 memset(&data->handle, 0, sizeof(struct snapshot_handle));
305 data->ready = 0; 278 data->ready = 0;
279 /*
280 * It is necessary to thaw kernel threads here, because
281 * SNAPSHOT_CREATE_IMAGE may be invoked directly after
282 * SNAPSHOT_FREE. In that case, if kernel threads were not
283 * thawed, the preallocation of memory carried out by
284 * hibernation_snapshot() might run into problems (i.e. it
285 * might fail or even deadlock).
286 */
287 thaw_kernel_threads();
306 break; 288 break;
307 289
308 case SNAPSHOT_SET_IMAGE_SIZE:
309 snapshot_deprecated_ioctl(cmd);
310 case SNAPSHOT_PREF_IMAGE_SIZE: 290 case SNAPSHOT_PREF_IMAGE_SIZE:
311 image_size = arg; 291 image_size = arg;
312 break; 292 break;
@@ -321,16 +301,12 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
321 error = put_user(size, (loff_t __user *)arg); 301 error = put_user(size, (loff_t __user *)arg);
322 break; 302 break;
323 303
324 case SNAPSHOT_AVAIL_SWAP:
325 snapshot_deprecated_ioctl(cmd);
326 case SNAPSHOT_AVAIL_SWAP_SIZE: 304 case SNAPSHOT_AVAIL_SWAP_SIZE:
327 size = count_swap_pages(data->swap, 1); 305 size = count_swap_pages(data->swap, 1);
328 size <<= PAGE_SHIFT; 306 size <<= PAGE_SHIFT;
329 error = put_user(size, (loff_t __user *)arg); 307 error = put_user(size, (loff_t __user *)arg);
330 break; 308 break;
331 309
332 case SNAPSHOT_GET_SWAP_PAGE:
333 snapshot_deprecated_ioctl(cmd);
334 case SNAPSHOT_ALLOC_SWAP_PAGE: 310 case SNAPSHOT_ALLOC_SWAP_PAGE:
335 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { 311 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
336 error = -ENODEV; 312 error = -ENODEV;
@@ -353,27 +329,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
353 free_all_swap_pages(data->swap); 329 free_all_swap_pages(data->swap);
354 break; 330 break;
355 331
356 case SNAPSHOT_SET_SWAP_FILE: /* This ioctl is deprecated */
357 snapshot_deprecated_ioctl(cmd);
358 if (!swsusp_swap_in_use()) {
359 /*
360 * User space encodes device types as two-byte values,
361 * so we need to recode them
362 */
363 if (old_decode_dev(arg)) {
364 data->swap = swap_type_of(old_decode_dev(arg),
365 0, NULL);
366 if (data->swap < 0)
367 error = -ENODEV;
368 } else {
369 data->swap = -1;
370 error = -EINVAL;
371 }
372 } else {
373 error = -EPERM;
374 }
375 break;
376
377 case SNAPSHOT_S2RAM: 332 case SNAPSHOT_S2RAM:
378 if (!data->frozen) { 333 if (!data->frozen) {
379 error = -EPERM; 334 error = -EPERM;
@@ -396,33 +351,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
396 error = hibernation_platform_enter(); 351 error = hibernation_platform_enter();
397 break; 352 break;
398 353
399 case SNAPSHOT_PMOPS: /* This ioctl is deprecated */
400 snapshot_deprecated_ioctl(cmd);
401 error = -EINVAL;
402
403 switch (arg) {
404
405 case PMOPS_PREPARE:
406 data->platform_support = 1;
407 error = 0;
408 break;
409
410 case PMOPS_ENTER:
411 if (data->platform_support)
412 error = hibernation_platform_enter();
413 break;
414
415 case PMOPS_FINISH:
416 if (data->platform_support)
417 error = 0;
418 break;
419
420 default:
421 printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);
422
423 }
424 break;
425
426 case SNAPSHOT_SET_SWAP_AREA: 354 case SNAPSHOT_SET_SWAP_AREA:
427 if (swsusp_swap_in_use()) { 355 if (swsusp_swap_in_use()) {
428 error = -EPERM; 356 error = -EPERM;
@@ -464,6 +392,66 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
464 return error; 392 return error;
465} 393}
466 394
395#ifdef CONFIG_COMPAT
396
397struct compat_resume_swap_area {
398 compat_loff_t offset;
399 u32 dev;
400} __packed;
401
402static long
403snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
404{
405 BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
406
407 switch (cmd) {
408 case SNAPSHOT_GET_IMAGE_SIZE:
409 case SNAPSHOT_AVAIL_SWAP_SIZE:
410 case SNAPSHOT_ALLOC_SWAP_PAGE: {
411 compat_loff_t __user *uoffset = compat_ptr(arg);
412 loff_t offset;
413 mm_segment_t old_fs;
414 int err;
415
416 old_fs = get_fs();
417 set_fs(KERNEL_DS);
418 err = snapshot_ioctl(file, cmd, (unsigned long) &offset);
419 set_fs(old_fs);
420 if (!err && put_user(offset, uoffset))
421 err = -EFAULT;
422 return err;
423 }
424
425 case SNAPSHOT_CREATE_IMAGE:
426 return snapshot_ioctl(file, cmd,
427 (unsigned long) compat_ptr(arg));
428
429 case SNAPSHOT_SET_SWAP_AREA: {
430 struct compat_resume_swap_area __user *u_swap_area =
431 compat_ptr(arg);
432 struct resume_swap_area swap_area;
433 mm_segment_t old_fs;
434 int err;
435
436 err = get_user(swap_area.offset, &u_swap_area->offset);
437 err |= get_user(swap_area.dev, &u_swap_area->dev);
438 if (err)
439 return -EFAULT;
440 old_fs = get_fs();
441 set_fs(KERNEL_DS);
442 err = snapshot_ioctl(file, SNAPSHOT_SET_SWAP_AREA,
443 (unsigned long) &swap_area);
444 set_fs(old_fs);
445 return err;
446 }
447
448 default:
449 return snapshot_ioctl(file, cmd, arg);
450 }
451}
452
453#endif /* CONFIG_COMPAT */
454
467static const struct file_operations snapshot_fops = { 455static const struct file_operations snapshot_fops = {
468 .open = snapshot_open, 456 .open = snapshot_open,
469 .release = snapshot_release, 457 .release = snapshot_release,
@@ -471,6 +459,9 @@ static const struct file_operations snapshot_fops = {
471 .write = snapshot_write, 459 .write = snapshot_write,
472 .llseek = no_llseek, 460 .llseek = no_llseek,
473 .unlocked_ioctl = snapshot_ioctl, 461 .unlocked_ioctl = snapshot_ioctl,
462#ifdef CONFIG_COMPAT
463 .compat_ioctl = snapshot_compat_ioctl,
464#endif
474}; 465};
475 466
476static struct miscdevice snapshot_device = { 467static struct miscdevice snapshot_device = {