diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-07 16:35:17 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-07 16:35:17 -0500 |
commit | 21b4e736922f546e0f1aa7b9d6c442f309a2444a (patch) | |
tree | e1be8645297f8ebe87445251743ebcc52081a20d /kernel/power | |
parent | 34161db6b14d984fb9b06c735b7b42f8803f6851 (diff) | |
parent | 68380b581383c028830f79ec2670f4a193854aa6 (diff) |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/ into merge_linus
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/Kconfig | 2 | ||||
-rw-r--r-- | kernel/power/disk.c | 66 | ||||
-rw-r--r-- | kernel/power/main.c | 14 | ||||
-rw-r--r-- | kernel/power/power.h | 32 | ||||
-rw-r--r-- | kernel/power/process.c | 130 | ||||
-rw-r--r-- | kernel/power/snapshot.c | 860 | ||||
-rw-r--r-- | kernel/power/swap.c | 347 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 98 | ||||
-rw-r--r-- | kernel/power/user.c | 102 |
9 files changed, 1139 insertions, 512 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 825068ca3479..710ed084e7c5 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -78,7 +78,7 @@ config PM_SYSFS_DEPRECATED | |||
78 | 78 | ||
79 | config SOFTWARE_SUSPEND | 79 | config SOFTWARE_SUSPEND |
80 | bool "Software Suspend" | 80 | bool "Software Suspend" |
81 | depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP) && !X86_PAE) || ((FRV || PPC32) && !SMP)) | 81 | depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)) |
82 | ---help--- | 82 | ---help--- |
83 | Enable the possibility of suspending the machine. | 83 | Enable the possibility of suspending the machine. |
84 | It doesn't need ACPI or APM. | 84 | It doesn't need ACPI or APM. |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index b1fb7866b0b3..0b00f56c2ad0 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/console.h> | 21 | #include <linux/console.h> |
22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
23 | #include <linux/freezer.h> | ||
23 | 24 | ||
24 | #include "power.h" | 25 | #include "power.h" |
25 | 26 | ||
@@ -27,6 +28,23 @@ | |||
27 | static int noresume = 0; | 28 | static int noresume = 0; |
28 | char resume_file[256] = CONFIG_PM_STD_PARTITION; | 29 | char resume_file[256] = CONFIG_PM_STD_PARTITION; |
29 | dev_t swsusp_resume_device; | 30 | dev_t swsusp_resume_device; |
31 | sector_t swsusp_resume_block; | ||
32 | |||
33 | /** | ||
34 | * platform_prepare - prepare the machine for hibernation using the | ||
35 | * platform driver if so configured and return an error code if it fails | ||
36 | */ | ||
37 | |||
38 | static inline int platform_prepare(void) | ||
39 | { | ||
40 | int error = 0; | ||
41 | |||
42 | if (pm_disk_mode == PM_DISK_PLATFORM) { | ||
43 | if (pm_ops && pm_ops->prepare) | ||
44 | error = pm_ops->prepare(PM_SUSPEND_DISK); | ||
45 | } | ||
46 | return error; | ||
47 | } | ||
30 | 48 | ||
31 | /** | 49 | /** |
32 | * power_down - Shut machine down for hibernate. | 50 | * power_down - Shut machine down for hibernate. |
@@ -40,12 +58,10 @@ dev_t swsusp_resume_device; | |||
40 | 58 | ||
41 | static void power_down(suspend_disk_method_t mode) | 59 | static void power_down(suspend_disk_method_t mode) |
42 | { | 60 | { |
43 | int error = 0; | ||
44 | |||
45 | switch(mode) { | 61 | switch(mode) { |
46 | case PM_DISK_PLATFORM: | 62 | case PM_DISK_PLATFORM: |
47 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); | 63 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); |
48 | error = pm_ops->enter(PM_SUSPEND_DISK); | 64 | pm_ops->enter(PM_SUSPEND_DISK); |
49 | break; | 65 | break; |
50 | case PM_DISK_SHUTDOWN: | 66 | case PM_DISK_SHUTDOWN: |
51 | kernel_power_off(); | 67 | kernel_power_off(); |
@@ -90,12 +106,18 @@ static int prepare_processes(void) | |||
90 | goto thaw; | 106 | goto thaw; |
91 | } | 107 | } |
92 | 108 | ||
109 | error = platform_prepare(); | ||
110 | if (error) | ||
111 | goto thaw; | ||
112 | |||
93 | /* Free memory before shutting down devices. */ | 113 | /* Free memory before shutting down devices. */ |
94 | if (!(error = swsusp_shrink_memory())) | 114 | if (!(error = swsusp_shrink_memory())) |
95 | return 0; | 115 | return 0; |
96 | thaw: | 116 | |
117 | platform_finish(); | ||
118 | thaw: | ||
97 | thaw_processes(); | 119 | thaw_processes(); |
98 | enable_cpus: | 120 | enable_cpus: |
99 | enable_nonboot_cpus(); | 121 | enable_nonboot_cpus(); |
100 | pm_restore_console(); | 122 | pm_restore_console(); |
101 | return error; | 123 | return error; |
@@ -127,7 +149,7 @@ int pm_suspend_disk(void) | |||
127 | return error; | 149 | return error; |
128 | 150 | ||
129 | if (pm_disk_mode == PM_DISK_TESTPROC) | 151 | if (pm_disk_mode == PM_DISK_TESTPROC) |
130 | goto Thaw; | 152 | return 0; |
131 | 153 | ||
132 | suspend_console(); | 154 | suspend_console(); |
133 | error = device_suspend(PMSG_FREEZE); | 155 | error = device_suspend(PMSG_FREEZE); |
@@ -189,10 +211,10 @@ static int software_resume(void) | |||
189 | { | 211 | { |
190 | int error; | 212 | int error; |
191 | 213 | ||
192 | down(&pm_sem); | 214 | mutex_lock(&pm_mutex); |
193 | if (!swsusp_resume_device) { | 215 | if (!swsusp_resume_device) { |
194 | if (!strlen(resume_file)) { | 216 | if (!strlen(resume_file)) { |
195 | up(&pm_sem); | 217 | mutex_unlock(&pm_mutex); |
196 | return -ENOENT; | 218 | return -ENOENT; |
197 | } | 219 | } |
198 | swsusp_resume_device = name_to_dev_t(resume_file); | 220 | swsusp_resume_device = name_to_dev_t(resume_file); |
@@ -207,7 +229,7 @@ static int software_resume(void) | |||
207 | * FIXME: If noresume is specified, we need to find the partition | 229 | * FIXME: If noresume is specified, we need to find the partition |
208 | * and reset it back to normal swap space. | 230 | * and reset it back to normal swap space. |
209 | */ | 231 | */ |
210 | up(&pm_sem); | 232 | mutex_unlock(&pm_mutex); |
211 | return 0; | 233 | return 0; |
212 | } | 234 | } |
213 | 235 | ||
@@ -251,7 +273,7 @@ static int software_resume(void) | |||
251 | unprepare_processes(); | 273 | unprepare_processes(); |
252 | Done: | 274 | Done: |
253 | /* For success case, the suspend path will release the lock */ | 275 | /* For success case, the suspend path will release the lock */ |
254 | up(&pm_sem); | 276 | mutex_unlock(&pm_mutex); |
255 | pr_debug("PM: Resume from disk failed.\n"); | 277 | pr_debug("PM: Resume from disk failed.\n"); |
256 | return 0; | 278 | return 0; |
257 | } | 279 | } |
@@ -312,7 +334,7 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) | |||
312 | p = memchr(buf, '\n', n); | 334 | p = memchr(buf, '\n', n); |
313 | len = p ? p - buf : n; | 335 | len = p ? p - buf : n; |
314 | 336 | ||
315 | down(&pm_sem); | 337 | mutex_lock(&pm_mutex); |
316 | for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) { | 338 | for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) { |
317 | if (!strncmp(buf, pm_disk_modes[i], len)) { | 339 | if (!strncmp(buf, pm_disk_modes[i], len)) { |
318 | mode = i; | 340 | mode = i; |
@@ -336,7 +358,7 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) | |||
336 | 358 | ||
337 | pr_debug("PM: suspend-to-disk mode set to '%s'\n", | 359 | pr_debug("PM: suspend-to-disk mode set to '%s'\n", |
338 | pm_disk_modes[mode]); | 360 | pm_disk_modes[mode]); |
339 | up(&pm_sem); | 361 | mutex_unlock(&pm_mutex); |
340 | return error ? error : n; | 362 | return error ? error : n; |
341 | } | 363 | } |
342 | 364 | ||
@@ -361,14 +383,14 @@ static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n) | |||
361 | if (maj != MAJOR(res) || min != MINOR(res)) | 383 | if (maj != MAJOR(res) || min != MINOR(res)) |
362 | goto out; | 384 | goto out; |
363 | 385 | ||
364 | down(&pm_sem); | 386 | mutex_lock(&pm_mutex); |
365 | swsusp_resume_device = res; | 387 | swsusp_resume_device = res; |
366 | up(&pm_sem); | 388 | mutex_unlock(&pm_mutex); |
367 | printk("Attempting manual resume\n"); | 389 | printk("Attempting manual resume\n"); |
368 | noresume = 0; | 390 | noresume = 0; |
369 | software_resume(); | 391 | software_resume(); |
370 | ret = n; | 392 | ret = n; |
371 | out: | 393 | out: |
372 | return ret; | 394 | return ret; |
373 | } | 395 | } |
374 | 396 | ||
@@ -423,6 +445,19 @@ static int __init resume_setup(char *str) | |||
423 | return 1; | 445 | return 1; |
424 | } | 446 | } |
425 | 447 | ||
448 | static int __init resume_offset_setup(char *str) | ||
449 | { | ||
450 | unsigned long long offset; | ||
451 | |||
452 | if (noresume) | ||
453 | return 1; | ||
454 | |||
455 | if (sscanf(str, "%llu", &offset) == 1) | ||
456 | swsusp_resume_block = offset; | ||
457 | |||
458 | return 1; | ||
459 | } | ||
460 | |||
426 | static int __init noresume_setup(char *str) | 461 | static int __init noresume_setup(char *str) |
427 | { | 462 | { |
428 | noresume = 1; | 463 | noresume = 1; |
@@ -430,4 +465,5 @@ static int __init noresume_setup(char *str) | |||
430 | } | 465 | } |
431 | 466 | ||
432 | __setup("noresume", noresume_setup); | 467 | __setup("noresume", noresume_setup); |
468 | __setup("resume_offset=", resume_offset_setup); | ||
433 | __setup("resume=", resume_setup); | 469 | __setup("resume=", resume_setup); |
diff --git a/kernel/power/main.c b/kernel/power/main.c index 873228c71dab..500eb87f643d 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/module.h> | ||
11 | #include <linux/suspend.h> | 12 | #include <linux/suspend.h> |
12 | #include <linux/kobject.h> | 13 | #include <linux/kobject.h> |
13 | #include <linux/string.h> | 14 | #include <linux/string.h> |
@@ -18,13 +19,14 @@ | |||
18 | #include <linux/console.h> | 19 | #include <linux/console.h> |
19 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
20 | #include <linux/resume-trace.h> | 21 | #include <linux/resume-trace.h> |
22 | #include <linux/freezer.h> | ||
21 | 23 | ||
22 | #include "power.h" | 24 | #include "power.h" |
23 | 25 | ||
24 | /*This is just an arbitrary number */ | 26 | /*This is just an arbitrary number */ |
25 | #define FREE_PAGE_NUMBER (100) | 27 | #define FREE_PAGE_NUMBER (100) |
26 | 28 | ||
27 | DECLARE_MUTEX(pm_sem); | 29 | DEFINE_MUTEX(pm_mutex); |
28 | 30 | ||
29 | struct pm_ops *pm_ops; | 31 | struct pm_ops *pm_ops; |
30 | suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN; | 32 | suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN; |
@@ -36,9 +38,9 @@ suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN; | |||
36 | 38 | ||
37 | void pm_set_ops(struct pm_ops * ops) | 39 | void pm_set_ops(struct pm_ops * ops) |
38 | { | 40 | { |
39 | down(&pm_sem); | 41 | mutex_lock(&pm_mutex); |
40 | pm_ops = ops; | 42 | pm_ops = ops; |
41 | up(&pm_sem); | 43 | mutex_unlock(&pm_mutex); |
42 | } | 44 | } |
43 | 45 | ||
44 | 46 | ||
@@ -182,7 +184,7 @@ static int enter_state(suspend_state_t state) | |||
182 | 184 | ||
183 | if (!valid_state(state)) | 185 | if (!valid_state(state)) |
184 | return -ENODEV; | 186 | return -ENODEV; |
185 | if (down_trylock(&pm_sem)) | 187 | if (!mutex_trylock(&pm_mutex)) |
186 | return -EBUSY; | 188 | return -EBUSY; |
187 | 189 | ||
188 | if (state == PM_SUSPEND_DISK) { | 190 | if (state == PM_SUSPEND_DISK) { |
@@ -200,7 +202,7 @@ static int enter_state(suspend_state_t state) | |||
200 | pr_debug("PM: Finishing wakeup.\n"); | 202 | pr_debug("PM: Finishing wakeup.\n"); |
201 | suspend_finish(state); | 203 | suspend_finish(state); |
202 | Unlock: | 204 | Unlock: |
203 | up(&pm_sem); | 205 | mutex_unlock(&pm_mutex); |
204 | return error; | 206 | return error; |
205 | } | 207 | } |
206 | 208 | ||
@@ -229,7 +231,7 @@ int pm_suspend(suspend_state_t state) | |||
229 | return -EINVAL; | 231 | return -EINVAL; |
230 | } | 232 | } |
231 | 233 | ||
232 | 234 | EXPORT_SYMBOL(pm_suspend); | |
233 | 235 | ||
234 | decl_subsys(power,NULL,NULL); | 236 | decl_subsys(power,NULL,NULL); |
235 | 237 | ||
diff --git a/kernel/power/power.h b/kernel/power/power.h index bfe999f7b272..eb461b816bf4 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -22,7 +22,9 @@ static inline int pm_suspend_disk(void) | |||
22 | return -EPERM; | 22 | return -EPERM; |
23 | } | 23 | } |
24 | #endif | 24 | #endif |
25 | extern struct semaphore pm_sem; | 25 | |
26 | extern struct mutex pm_mutex; | ||
27 | |||
26 | #define power_attr(_name) \ | 28 | #define power_attr(_name) \ |
27 | static struct subsys_attribute _name##_attr = { \ | 29 | static struct subsys_attribute _name##_attr = { \ |
28 | .attr = { \ | 30 | .attr = { \ |
@@ -42,6 +44,7 @@ extern const void __nosave_begin, __nosave_end; | |||
42 | extern unsigned long image_size; | 44 | extern unsigned long image_size; |
43 | extern int in_suspend; | 45 | extern int in_suspend; |
44 | extern dev_t swsusp_resume_device; | 46 | extern dev_t swsusp_resume_device; |
47 | extern sector_t swsusp_resume_block; | ||
45 | 48 | ||
46 | extern asmlinkage int swsusp_arch_suspend(void); | 49 | extern asmlinkage int swsusp_arch_suspend(void); |
47 | extern asmlinkage int swsusp_arch_resume(void); | 50 | extern asmlinkage int swsusp_arch_resume(void); |
@@ -102,8 +105,18 @@ struct snapshot_handle { | |||
102 | extern unsigned int snapshot_additional_pages(struct zone *zone); | 105 | extern unsigned int snapshot_additional_pages(struct zone *zone); |
103 | extern int snapshot_read_next(struct snapshot_handle *handle, size_t count); | 106 | extern int snapshot_read_next(struct snapshot_handle *handle, size_t count); |
104 | extern int snapshot_write_next(struct snapshot_handle *handle, size_t count); | 107 | extern int snapshot_write_next(struct snapshot_handle *handle, size_t count); |
108 | extern void snapshot_write_finalize(struct snapshot_handle *handle); | ||
105 | extern int snapshot_image_loaded(struct snapshot_handle *handle); | 109 | extern int snapshot_image_loaded(struct snapshot_handle *handle); |
106 | extern void snapshot_free_unused_memory(struct snapshot_handle *handle); | 110 | |
111 | /* | ||
112 | * This structure is used to pass the values needed for the identification | ||
113 | * of the resume swap area from a user space to the kernel via the | ||
114 | * SNAPSHOT_SET_SWAP_AREA ioctl | ||
115 | */ | ||
116 | struct resume_swap_area { | ||
117 | loff_t offset; | ||
118 | u_int32_t dev; | ||
119 | } __attribute__((packed)); | ||
107 | 120 | ||
108 | #define SNAPSHOT_IOC_MAGIC '3' | 121 | #define SNAPSHOT_IOC_MAGIC '3' |
109 | #define SNAPSHOT_FREEZE _IO(SNAPSHOT_IOC_MAGIC, 1) | 122 | #define SNAPSHOT_FREEZE _IO(SNAPSHOT_IOC_MAGIC, 1) |
@@ -117,7 +130,14 @@ extern void snapshot_free_unused_memory(struct snapshot_handle *handle); | |||
117 | #define SNAPSHOT_FREE_SWAP_PAGES _IO(SNAPSHOT_IOC_MAGIC, 9) | 130 | #define SNAPSHOT_FREE_SWAP_PAGES _IO(SNAPSHOT_IOC_MAGIC, 9) |
118 | #define SNAPSHOT_SET_SWAP_FILE _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int) | 131 | #define SNAPSHOT_SET_SWAP_FILE _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int) |
119 | #define SNAPSHOT_S2RAM _IO(SNAPSHOT_IOC_MAGIC, 11) | 132 | #define SNAPSHOT_S2RAM _IO(SNAPSHOT_IOC_MAGIC, 11) |
120 | #define SNAPSHOT_IOC_MAXNR 11 | 133 | #define SNAPSHOT_PMOPS _IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int) |
134 | #define SNAPSHOT_SET_SWAP_AREA _IOW(SNAPSHOT_IOC_MAGIC, 13, \ | ||
135 | struct resume_swap_area) | ||
136 | #define SNAPSHOT_IOC_MAXNR 13 | ||
137 | |||
138 | #define PMOPS_PREPARE 1 | ||
139 | #define PMOPS_ENTER 2 | ||
140 | #define PMOPS_FINISH 3 | ||
121 | 141 | ||
122 | /** | 142 | /** |
123 | * The bitmap is used for tracing allocated swap pages | 143 | * The bitmap is used for tracing allocated swap pages |
@@ -141,7 +161,7 @@ struct bitmap_page { | |||
141 | 161 | ||
142 | extern void free_bitmap(struct bitmap_page *bitmap); | 162 | extern void free_bitmap(struct bitmap_page *bitmap); |
143 | extern struct bitmap_page *alloc_bitmap(unsigned int nr_bits); | 163 | extern struct bitmap_page *alloc_bitmap(unsigned int nr_bits); |
144 | extern unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap); | 164 | extern sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap); |
145 | extern void free_all_swap_pages(int swap, struct bitmap_page *bitmap); | 165 | extern void free_all_swap_pages(int swap, struct bitmap_page *bitmap); |
146 | 166 | ||
147 | extern int swsusp_check(void); | 167 | extern int swsusp_check(void); |
@@ -153,3 +173,7 @@ extern int swsusp_read(void); | |||
153 | extern int swsusp_write(void); | 173 | extern int swsusp_write(void); |
154 | extern void swsusp_close(void); | 174 | extern void swsusp_close(void); |
155 | extern int suspend_enter(suspend_state_t state); | 175 | extern int suspend_enter(suspend_state_t state); |
176 | |||
177 | struct timeval; | ||
178 | extern void swsusp_show_speed(struct timeval *, struct timeval *, | ||
179 | unsigned int, char *); | ||
diff --git a/kernel/power/process.c b/kernel/power/process.c index 72e72d2c61e6..99eeb119b06d 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -13,12 +13,15 @@ | |||
13 | #include <linux/suspend.h> | 13 | #include <linux/suspend.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/syscalls.h> | 15 | #include <linux/syscalls.h> |
16 | #include <linux/freezer.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * Timeout for stopping processes | 19 | * Timeout for stopping processes |
19 | */ | 20 | */ |
20 | #define TIMEOUT (20 * HZ) | 21 | #define TIMEOUT (20 * HZ) |
21 | 22 | ||
23 | #define FREEZER_KERNEL_THREADS 0 | ||
24 | #define FREEZER_USER_SPACE 1 | ||
22 | 25 | ||
23 | static inline int freezeable(struct task_struct * p) | 26 | static inline int freezeable(struct task_struct * p) |
24 | { | 27 | { |
@@ -39,7 +42,6 @@ void refrigerator(void) | |||
39 | long save; | 42 | long save; |
40 | save = current->state; | 43 | save = current->state; |
41 | pr_debug("%s entered refrigerator\n", current->comm); | 44 | pr_debug("%s entered refrigerator\n", current->comm); |
42 | printk("="); | ||
43 | 45 | ||
44 | frozen_process(current); | 46 | frozen_process(current); |
45 | spin_lock_irq(¤t->sighand->siglock); | 47 | spin_lock_irq(¤t->sighand->siglock); |
@@ -79,96 +81,136 @@ static void cancel_freezing(struct task_struct *p) | |||
79 | } | 81 | } |
80 | } | 82 | } |
81 | 83 | ||
82 | /* 0 = success, else # of processes that we failed to stop */ | 84 | static inline int is_user_space(struct task_struct *p) |
83 | int freeze_processes(void) | 85 | { |
86 | return p->mm && !(p->flags & PF_BORROWED_MM); | ||
87 | } | ||
88 | |||
89 | static unsigned int try_to_freeze_tasks(int freeze_user_space) | ||
84 | { | 90 | { |
85 | int todo, nr_user, user_frozen; | ||
86 | unsigned long start_time; | ||
87 | struct task_struct *g, *p; | 91 | struct task_struct *g, *p; |
92 | unsigned long end_time; | ||
93 | unsigned int todo; | ||
88 | 94 | ||
89 | printk( "Stopping tasks: " ); | 95 | end_time = jiffies + TIMEOUT; |
90 | start_time = jiffies; | ||
91 | user_frozen = 0; | ||
92 | do { | 96 | do { |
93 | nr_user = todo = 0; | 97 | todo = 0; |
94 | read_lock(&tasklist_lock); | 98 | read_lock(&tasklist_lock); |
95 | do_each_thread(g, p) { | 99 | do_each_thread(g, p) { |
96 | if (!freezeable(p)) | 100 | if (!freezeable(p)) |
97 | continue; | 101 | continue; |
102 | |||
98 | if (frozen(p)) | 103 | if (frozen(p)) |
99 | continue; | 104 | continue; |
100 | if (p->state == TASK_TRACED && frozen(p->parent)) { | 105 | |
106 | if (p->state == TASK_TRACED && | ||
107 | (frozen(p->parent) || | ||
108 | p->parent->state == TASK_STOPPED)) { | ||
101 | cancel_freezing(p); | 109 | cancel_freezing(p); |
102 | continue; | 110 | continue; |
103 | } | 111 | } |
104 | if (p->mm && !(p->flags & PF_BORROWED_MM)) { | 112 | if (is_user_space(p)) { |
105 | /* The task is a user-space one. | 113 | if (!freeze_user_space) |
106 | * Freeze it unless there's a vfork completion | 114 | continue; |
107 | * pending | 115 | |
116 | /* Freeze the task unless there is a vfork | ||
117 | * completion pending | ||
108 | */ | 118 | */ |
109 | if (!p->vfork_done) | 119 | if (!p->vfork_done) |
110 | freeze_process(p); | 120 | freeze_process(p); |
111 | nr_user++; | ||
112 | } else { | 121 | } else { |
113 | /* Freeze only if the user space is frozen */ | 122 | if (freeze_user_space) |
114 | if (user_frozen) | 123 | continue; |
115 | freeze_process(p); | 124 | |
116 | todo++; | 125 | freeze_process(p); |
117 | } | 126 | } |
127 | todo++; | ||
118 | } while_each_thread(g, p); | 128 | } while_each_thread(g, p); |
119 | read_unlock(&tasklist_lock); | 129 | read_unlock(&tasklist_lock); |
120 | todo += nr_user; | ||
121 | if (!user_frozen && !nr_user) { | ||
122 | sys_sync(); | ||
123 | start_time = jiffies; | ||
124 | } | ||
125 | user_frozen = !nr_user; | ||
126 | yield(); /* Yield is okay here */ | 130 | yield(); /* Yield is okay here */ |
127 | if (todo && time_after(jiffies, start_time + TIMEOUT)) | 131 | if (todo && time_after(jiffies, end_time)) |
128 | break; | 132 | break; |
129 | } while(todo); | 133 | } while (todo); |
130 | 134 | ||
131 | /* This does not unfreeze processes that are already frozen | ||
132 | * (we have slightly ugly calling convention in that respect, | ||
133 | * and caller must call thaw_processes() if something fails), | ||
134 | * but it cleans up leftover PF_FREEZE requests. | ||
135 | */ | ||
136 | if (todo) { | 135 | if (todo) { |
137 | printk( "\n" ); | 136 | /* This does not unfreeze processes that are already frozen |
138 | printk(KERN_ERR " stopping tasks timed out " | 137 | * (we have slightly ugly calling convention in that respect, |
139 | "after %d seconds (%d tasks remaining):\n", | 138 | * and caller must call thaw_processes() if something fails), |
140 | TIMEOUT / HZ, todo); | 139 | * but it cleans up leftover PF_FREEZE requests. |
140 | */ | ||
141 | printk("\n"); | ||
142 | printk(KERN_ERR "Stopping %s timed out after %d seconds " | ||
143 | "(%d tasks refusing to freeze):\n", | ||
144 | freeze_user_space ? "user space processes" : | ||
145 | "kernel threads", | ||
146 | TIMEOUT / HZ, todo); | ||
141 | read_lock(&tasklist_lock); | 147 | read_lock(&tasklist_lock); |
142 | do_each_thread(g, p) { | 148 | do_each_thread(g, p) { |
149 | if (is_user_space(p) == !freeze_user_space) | ||
150 | continue; | ||
151 | |||
143 | if (freezeable(p) && !frozen(p)) | 152 | if (freezeable(p) && !frozen(p)) |
144 | printk(KERN_ERR " %s\n", p->comm); | 153 | printk(KERN_ERR " %s\n", p->comm); |
154 | |||
145 | cancel_freezing(p); | 155 | cancel_freezing(p); |
146 | } while_each_thread(g, p); | 156 | } while_each_thread(g, p); |
147 | read_unlock(&tasklist_lock); | 157 | read_unlock(&tasklist_lock); |
148 | return todo; | ||
149 | } | 158 | } |
150 | 159 | ||
151 | printk( "|\n" ); | 160 | return todo; |
161 | } | ||
162 | |||
163 | /** | ||
164 | * freeze_processes - tell processes to enter the refrigerator | ||
165 | * | ||
166 | * Returns 0 on success, or the number of processes that didn't freeze, | ||
167 | * although they were told to. | ||
168 | */ | ||
169 | int freeze_processes(void) | ||
170 | { | ||
171 | unsigned int nr_unfrozen; | ||
172 | |||
173 | printk("Stopping tasks ... "); | ||
174 | nr_unfrozen = try_to_freeze_tasks(FREEZER_USER_SPACE); | ||
175 | if (nr_unfrozen) | ||
176 | return nr_unfrozen; | ||
177 | |||
178 | sys_sync(); | ||
179 | nr_unfrozen = try_to_freeze_tasks(FREEZER_KERNEL_THREADS); | ||
180 | if (nr_unfrozen) | ||
181 | return nr_unfrozen; | ||
182 | |||
183 | printk("done.\n"); | ||
152 | BUG_ON(in_atomic()); | 184 | BUG_ON(in_atomic()); |
153 | return 0; | 185 | return 0; |
154 | } | 186 | } |
155 | 187 | ||
156 | void thaw_processes(void) | 188 | static void thaw_tasks(int thaw_user_space) |
157 | { | 189 | { |
158 | struct task_struct *g, *p; | 190 | struct task_struct *g, *p; |
159 | 191 | ||
160 | printk( "Restarting tasks..." ); | ||
161 | read_lock(&tasklist_lock); | 192 | read_lock(&tasklist_lock); |
162 | do_each_thread(g, p) { | 193 | do_each_thread(g, p) { |
163 | if (!freezeable(p)) | 194 | if (!freezeable(p)) |
164 | continue; | 195 | continue; |
196 | |||
197 | if (is_user_space(p) == !thaw_user_space) | ||
198 | continue; | ||
199 | |||
165 | if (!thaw_process(p)) | 200 | if (!thaw_process(p)) |
166 | printk(KERN_INFO " Strange, %s not stopped\n", p->comm ); | 201 | printk(KERN_WARNING " Strange, %s not stopped\n", |
202 | p->comm ); | ||
167 | } while_each_thread(g, p); | 203 | } while_each_thread(g, p); |
168 | |||
169 | read_unlock(&tasklist_lock); | 204 | read_unlock(&tasklist_lock); |
205 | } | ||
206 | |||
207 | void thaw_processes(void) | ||
208 | { | ||
209 | printk("Restarting tasks ... "); | ||
210 | thaw_tasks(FREEZER_KERNEL_THREADS); | ||
211 | thaw_tasks(FREEZER_USER_SPACE); | ||
170 | schedule(); | 212 | schedule(); |
171 | printk( " done\n" ); | 213 | printk("done.\n"); |
172 | } | 214 | } |
173 | 215 | ||
174 | EXPORT_SYMBOL(refrigerator); | 216 | EXPORT_SYMBOL(refrigerator); |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 99f9b7d177d6..c024606221c4 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -1,15 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * linux/kernel/power/snapshot.c | 2 | * linux/kernel/power/snapshot.c |
3 | * | 3 | * |
4 | * This file provide system snapshot/restore functionality. | 4 | * This file provides system snapshot/restore functionality for swsusp. |
5 | * | 5 | * |
6 | * Copyright (C) 1998-2005 Pavel Machek <pavel@suse.cz> | 6 | * Copyright (C) 1998-2005 Pavel Machek <pavel@suse.cz> |
7 | * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> | ||
7 | * | 8 | * |
8 | * This file is released under the GPLv2, and is based on swsusp.c. | 9 | * This file is released under the GPLv2. |
9 | * | 10 | * |
10 | */ | 11 | */ |
11 | 12 | ||
12 | |||
13 | #include <linux/version.h> | 13 | #include <linux/version.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
@@ -34,137 +34,24 @@ | |||
34 | 34 | ||
35 | #include "power.h" | 35 | #include "power.h" |
36 | 36 | ||
37 | /* List of PBEs used for creating and restoring the suspend image */ | 37 | /* List of PBEs needed for restoring the pages that were allocated before |
38 | * the suspend and included in the suspend image, but have also been | ||
39 | * allocated by the "resume" kernel, so their contents cannot be written | ||
40 | * directly to their "original" page frames. | ||
41 | */ | ||
38 | struct pbe *restore_pblist; | 42 | struct pbe *restore_pblist; |
39 | 43 | ||
40 | static unsigned int nr_copy_pages; | 44 | /* Pointer to an auxiliary buffer (1 page) */ |
41 | static unsigned int nr_meta_pages; | ||
42 | static void *buffer; | 45 | static void *buffer; |
43 | 46 | ||
44 | #ifdef CONFIG_HIGHMEM | ||
45 | unsigned int count_highmem_pages(void) | ||
46 | { | ||
47 | struct zone *zone; | ||
48 | unsigned long zone_pfn; | ||
49 | unsigned int n = 0; | ||
50 | |||
51 | for_each_zone (zone) | ||
52 | if (is_highmem(zone)) { | ||
53 | mark_free_pages(zone); | ||
54 | for (zone_pfn = 0; zone_pfn < zone->spanned_pages; zone_pfn++) { | ||
55 | struct page *page; | ||
56 | unsigned long pfn = zone_pfn + zone->zone_start_pfn; | ||
57 | if (!pfn_valid(pfn)) | ||
58 | continue; | ||
59 | page = pfn_to_page(pfn); | ||
60 | if (PageReserved(page)) | ||
61 | continue; | ||
62 | if (PageNosaveFree(page)) | ||
63 | continue; | ||
64 | n++; | ||
65 | } | ||
66 | } | ||
67 | return n; | ||
68 | } | ||
69 | |||
70 | struct highmem_page { | ||
71 | char *data; | ||
72 | struct page *page; | ||
73 | struct highmem_page *next; | ||
74 | }; | ||
75 | |||
76 | static struct highmem_page *highmem_copy; | ||
77 | |||
78 | static int save_highmem_zone(struct zone *zone) | ||
79 | { | ||
80 | unsigned long zone_pfn; | ||
81 | mark_free_pages(zone); | ||
82 | for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { | ||
83 | struct page *page; | ||
84 | struct highmem_page *save; | ||
85 | void *kaddr; | ||
86 | unsigned long pfn = zone_pfn + zone->zone_start_pfn; | ||
87 | |||
88 | if (!(pfn%10000)) | ||
89 | printk("."); | ||
90 | if (!pfn_valid(pfn)) | ||
91 | continue; | ||
92 | page = pfn_to_page(pfn); | ||
93 | /* | ||
94 | * This condition results from rvmalloc() sans vmalloc_32() | ||
95 | * and architectural memory reservations. This should be | ||
96 | * corrected eventually when the cases giving rise to this | ||
97 | * are better understood. | ||
98 | */ | ||
99 | if (PageReserved(page)) | ||
100 | continue; | ||
101 | BUG_ON(PageNosave(page)); | ||
102 | if (PageNosaveFree(page)) | ||
103 | continue; | ||
104 | save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC); | ||
105 | if (!save) | ||
106 | return -ENOMEM; | ||
107 | save->next = highmem_copy; | ||
108 | save->page = page; | ||
109 | save->data = (void *) get_zeroed_page(GFP_ATOMIC); | ||
110 | if (!save->data) { | ||
111 | kfree(save); | ||
112 | return -ENOMEM; | ||
113 | } | ||
114 | kaddr = kmap_atomic(page, KM_USER0); | ||
115 | memcpy(save->data, kaddr, PAGE_SIZE); | ||
116 | kunmap_atomic(kaddr, KM_USER0); | ||
117 | highmem_copy = save; | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | int save_highmem(void) | ||
123 | { | ||
124 | struct zone *zone; | ||
125 | int res = 0; | ||
126 | |||
127 | pr_debug("swsusp: Saving Highmem"); | ||
128 | drain_local_pages(); | ||
129 | for_each_zone (zone) { | ||
130 | if (is_highmem(zone)) | ||
131 | res = save_highmem_zone(zone); | ||
132 | if (res) | ||
133 | return res; | ||
134 | } | ||
135 | printk("\n"); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | int restore_highmem(void) | ||
140 | { | ||
141 | printk("swsusp: Restoring Highmem\n"); | ||
142 | while (highmem_copy) { | ||
143 | struct highmem_page *save = highmem_copy; | ||
144 | void *kaddr; | ||
145 | highmem_copy = save->next; | ||
146 | |||
147 | kaddr = kmap_atomic(save->page, KM_USER0); | ||
148 | memcpy(kaddr, save->data, PAGE_SIZE); | ||
149 | kunmap_atomic(kaddr, KM_USER0); | ||
150 | free_page((long) save->data); | ||
151 | kfree(save); | ||
152 | } | ||
153 | return 0; | ||
154 | } | ||
155 | #else | ||
156 | static inline unsigned int count_highmem_pages(void) {return 0;} | ||
157 | static inline int save_highmem(void) {return 0;} | ||
158 | static inline int restore_highmem(void) {return 0;} | ||
159 | #endif | ||
160 | |||
161 | /** | 47 | /** |
162 | * @safe_needed - on resume, for storing the PBE list and the image, | 48 | * @safe_needed - on resume, for storing the PBE list and the image, |
163 | * we can only use memory pages that do not conflict with the pages | 49 | * we can only use memory pages that do not conflict with the pages |
164 | * used before suspend. | 50 | * used before suspend. The unsafe pages have PageNosaveFree set |
51 | * and we count them using unsafe_pages. | ||
165 | * | 52 | * |
166 | * The unsafe pages are marked with the PG_nosave_free flag | 53 | * Each allocated image page is marked as PageNosave and PageNosaveFree |
167 | * and we count them using unsafe_pages | 54 | * so that swsusp_free() can release it. |
168 | */ | 55 | */ |
169 | 56 | ||
170 | #define PG_ANY 0 | 57 | #define PG_ANY 0 |
@@ -174,7 +61,7 @@ static inline int restore_highmem(void) {return 0;} | |||
174 | 61 | ||
175 | static unsigned int allocated_unsafe_pages; | 62 | static unsigned int allocated_unsafe_pages; |
176 | 63 | ||
177 | static void *alloc_image_page(gfp_t gfp_mask, int safe_needed) | 64 | static void *get_image_page(gfp_t gfp_mask, int safe_needed) |
178 | { | 65 | { |
179 | void *res; | 66 | void *res; |
180 | 67 | ||
@@ -195,20 +82,39 @@ static void *alloc_image_page(gfp_t gfp_mask, int safe_needed) | |||
195 | 82 | ||
196 | unsigned long get_safe_page(gfp_t gfp_mask) | 83 | unsigned long get_safe_page(gfp_t gfp_mask) |
197 | { | 84 | { |
198 | return (unsigned long)alloc_image_page(gfp_mask, PG_SAFE); | 85 | return (unsigned long)get_image_page(gfp_mask, PG_SAFE); |
86 | } | ||
87 | |||
88 | static struct page *alloc_image_page(gfp_t gfp_mask) | ||
89 | { | ||
90 | struct page *page; | ||
91 | |||
92 | page = alloc_page(gfp_mask); | ||
93 | if (page) { | ||
94 | SetPageNosave(page); | ||
95 | SetPageNosaveFree(page); | ||
96 | } | ||
97 | return page; | ||
199 | } | 98 | } |
200 | 99 | ||
201 | /** | 100 | /** |
202 | * free_image_page - free page represented by @addr, allocated with | 101 | * free_image_page - free page represented by @addr, allocated with |
203 | * alloc_image_page (page flags set by it must be cleared) | 102 | * get_image_page (page flags set by it must be cleared) |
204 | */ | 103 | */ |
205 | 104 | ||
206 | static inline void free_image_page(void *addr, int clear_nosave_free) | 105 | static inline void free_image_page(void *addr, int clear_nosave_free) |
207 | { | 106 | { |
208 | ClearPageNosave(virt_to_page(addr)); | 107 | struct page *page; |
108 | |||
109 | BUG_ON(!virt_addr_valid(addr)); | ||
110 | |||
111 | page = virt_to_page(addr); | ||
112 | |||
113 | ClearPageNosave(page); | ||
209 | if (clear_nosave_free) | 114 | if (clear_nosave_free) |
210 | ClearPageNosaveFree(virt_to_page(addr)); | 115 | ClearPageNosaveFree(page); |
211 | free_page((unsigned long)addr); | 116 | |
117 | __free_page(page); | ||
212 | } | 118 | } |
213 | 119 | ||
214 | /* struct linked_page is used to build chains of pages */ | 120 | /* struct linked_page is used to build chains of pages */ |
@@ -269,7 +175,7 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size) | |||
269 | if (LINKED_PAGE_DATA_SIZE - ca->used_space < size) { | 175 | if (LINKED_PAGE_DATA_SIZE - ca->used_space < size) { |
270 | struct linked_page *lp; | 176 | struct linked_page *lp; |
271 | 177 | ||
272 | lp = alloc_image_page(ca->gfp_mask, ca->safe_needed); | 178 | lp = get_image_page(ca->gfp_mask, ca->safe_needed); |
273 | if (!lp) | 179 | if (!lp) |
274 | return NULL; | 180 | return NULL; |
275 | 181 | ||
@@ -446,8 +352,8 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) | |||
446 | 352 | ||
447 | /* Compute the number of zones */ | 353 | /* Compute the number of zones */ |
448 | nr = 0; | 354 | nr = 0; |
449 | for_each_zone (zone) | 355 | for_each_zone(zone) |
450 | if (populated_zone(zone) && !is_highmem(zone)) | 356 | if (populated_zone(zone)) |
451 | nr++; | 357 | nr++; |
452 | 358 | ||
453 | /* Allocate the list of zones bitmap objects */ | 359 | /* Allocate the list of zones bitmap objects */ |
@@ -459,10 +365,10 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) | |||
459 | } | 365 | } |
460 | 366 | ||
461 | /* Initialize the zone bitmap objects */ | 367 | /* Initialize the zone bitmap objects */ |
462 | for_each_zone (zone) { | 368 | for_each_zone(zone) { |
463 | unsigned long pfn; | 369 | unsigned long pfn; |
464 | 370 | ||
465 | if (!populated_zone(zone) || is_highmem(zone)) | 371 | if (!populated_zone(zone)) |
466 | continue; | 372 | continue; |
467 | 373 | ||
468 | zone_bm->start_pfn = zone->zone_start_pfn; | 374 | zone_bm->start_pfn = zone->zone_start_pfn; |
@@ -481,7 +387,7 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) | |||
481 | while (bb) { | 387 | while (bb) { |
482 | unsigned long *ptr; | 388 | unsigned long *ptr; |
483 | 389 | ||
484 | ptr = alloc_image_page(gfp_mask, safe_needed); | 390 | ptr = get_image_page(gfp_mask, safe_needed); |
485 | bb->data = ptr; | 391 | bb->data = ptr; |
486 | if (!ptr) | 392 | if (!ptr) |
487 | goto Free; | 393 | goto Free; |
@@ -505,7 +411,7 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) | |||
505 | memory_bm_position_reset(bm); | 411 | memory_bm_position_reset(bm); |
506 | return 0; | 412 | return 0; |
507 | 413 | ||
508 | Free: | 414 | Free: |
509 | bm->p_list = ca.chain; | 415 | bm->p_list = ca.chain; |
510 | memory_bm_free(bm, PG_UNSAFE_CLEAR); | 416 | memory_bm_free(bm, PG_UNSAFE_CLEAR); |
511 | return -ENOMEM; | 417 | return -ENOMEM; |
@@ -651,7 +557,7 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm) | |||
651 | memory_bm_position_reset(bm); | 557 | memory_bm_position_reset(bm); |
652 | return BM_END_OF_MAP; | 558 | return BM_END_OF_MAP; |
653 | 559 | ||
654 | Return_pfn: | 560 | Return_pfn: |
655 | bm->cur.chunk = chunk; | 561 | bm->cur.chunk = chunk; |
656 | bm->cur.bit = bit; | 562 | bm->cur.bit = bit; |
657 | return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit; | 563 | return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit; |
@@ -669,10 +575,82 @@ unsigned int snapshot_additional_pages(struct zone *zone) | |||
669 | 575 | ||
670 | res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK); | 576 | res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK); |
671 | res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE); | 577 | res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE); |
672 | return res; | 578 | return 2 * res; |
579 | } | ||
580 | |||
581 | #ifdef CONFIG_HIGHMEM | ||
582 | /** | ||
583 | * count_free_highmem_pages - compute the total number of free highmem | ||
584 | * pages, system-wide. | ||
585 | */ | ||
586 | |||
587 | static unsigned int count_free_highmem_pages(void) | ||
588 | { | ||
589 | struct zone *zone; | ||
590 | unsigned int cnt = 0; | ||
591 | |||
592 | for_each_zone(zone) | ||
593 | if (populated_zone(zone) && is_highmem(zone)) | ||
594 | cnt += zone->free_pages; | ||
595 | |||
596 | return cnt; | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * saveable_highmem_page - Determine whether a highmem page should be | ||
601 | * included in the suspend image. | ||
602 | * | ||
603 | * We should save the page if it isn't Nosave or NosaveFree, or Reserved, | ||
604 | * and it isn't a part of a free chunk of pages. | ||
605 | */ | ||
606 | |||
607 | static struct page *saveable_highmem_page(unsigned long pfn) | ||
608 | { | ||
609 | struct page *page; | ||
610 | |||
611 | if (!pfn_valid(pfn)) | ||
612 | return NULL; | ||
613 | |||
614 | page = pfn_to_page(pfn); | ||
615 | |||
616 | BUG_ON(!PageHighMem(page)); | ||
617 | |||
618 | if (PageNosave(page) || PageReserved(page) || PageNosaveFree(page)) | ||
619 | return NULL; | ||
620 | |||
621 | return page; | ||
673 | } | 622 | } |
674 | 623 | ||
675 | /** | 624 | /** |
625 | * count_highmem_pages - compute the total number of saveable highmem | ||
626 | * pages. | ||
627 | */ | ||
628 | |||
629 | unsigned int count_highmem_pages(void) | ||
630 | { | ||
631 | struct zone *zone; | ||
632 | unsigned int n = 0; | ||
633 | |||
634 | for_each_zone(zone) { | ||
635 | unsigned long pfn, max_zone_pfn; | ||
636 | |||
637 | if (!is_highmem(zone)) | ||
638 | continue; | ||
639 | |||
640 | mark_free_pages(zone); | ||
641 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; | ||
642 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | ||
643 | if (saveable_highmem_page(pfn)) | ||
644 | n++; | ||
645 | } | ||
646 | return n; | ||
647 | } | ||
648 | #else | ||
649 | static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; } | ||
650 | static inline unsigned int count_highmem_pages(void) { return 0; } | ||
651 | #endif /* CONFIG_HIGHMEM */ | ||
652 | |||
653 | /** | ||
676 | * pfn_is_nosave - check if given pfn is in the 'nosave' section | 654 | * pfn_is_nosave - check if given pfn is in the 'nosave' section |
677 | */ | 655 | */ |
678 | 656 | ||
@@ -684,12 +662,12 @@ static inline int pfn_is_nosave(unsigned long pfn) | |||
684 | } | 662 | } |
685 | 663 | ||
686 | /** | 664 | /** |
687 | * saveable - Determine whether a page should be cloned or not. | 665 | * saveable - Determine whether a non-highmem page should be included in |
688 | * @pfn: The page | 666 | * the suspend image. |
689 | * | 667 | * |
690 | * We save a page if it isn't Nosave, and is not in the range of pages | 668 | * We should save the page if it isn't Nosave, and is not in the range |
691 | * statically defined as 'unsaveable', and it | 669 | * of pages statically defined as 'unsaveable', and it isn't a part of |
692 | * isn't a part of a free chunk of pages. | 670 | * a free chunk of pages. |
693 | */ | 671 | */ |
694 | 672 | ||
695 | static struct page *saveable_page(unsigned long pfn) | 673 | static struct page *saveable_page(unsigned long pfn) |
@@ -701,76 +679,130 @@ static struct page *saveable_page(unsigned long pfn) | |||
701 | 679 | ||
702 | page = pfn_to_page(pfn); | 680 | page = pfn_to_page(pfn); |
703 | 681 | ||
704 | if (PageNosave(page)) | 682 | BUG_ON(PageHighMem(page)); |
683 | |||
684 | if (PageNosave(page) || PageNosaveFree(page)) | ||
705 | return NULL; | 685 | return NULL; |
686 | |||
706 | if (PageReserved(page) && pfn_is_nosave(pfn)) | 687 | if (PageReserved(page) && pfn_is_nosave(pfn)) |
707 | return NULL; | 688 | return NULL; |
708 | if (PageNosaveFree(page)) | ||
709 | return NULL; | ||
710 | 689 | ||
711 | return page; | 690 | return page; |
712 | } | 691 | } |
713 | 692 | ||
693 | /** | ||
694 | * count_data_pages - compute the total number of saveable non-highmem | ||
695 | * pages. | ||
696 | */ | ||
697 | |||
714 | unsigned int count_data_pages(void) | 698 | unsigned int count_data_pages(void) |
715 | { | 699 | { |
716 | struct zone *zone; | 700 | struct zone *zone; |
717 | unsigned long pfn, max_zone_pfn; | 701 | unsigned long pfn, max_zone_pfn; |
718 | unsigned int n = 0; | 702 | unsigned int n = 0; |
719 | 703 | ||
720 | for_each_zone (zone) { | 704 | for_each_zone(zone) { |
721 | if (is_highmem(zone)) | 705 | if (is_highmem(zone)) |
722 | continue; | 706 | continue; |
707 | |||
723 | mark_free_pages(zone); | 708 | mark_free_pages(zone); |
724 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; | 709 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; |
725 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | 710 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) |
726 | n += !!saveable_page(pfn); | 711 | if(saveable_page(pfn)) |
712 | n++; | ||
727 | } | 713 | } |
728 | return n; | 714 | return n; |
729 | } | 715 | } |
730 | 716 | ||
731 | static inline void copy_data_page(long *dst, long *src) | 717 | /* This is needed, because copy_page and memcpy are not usable for copying |
718 | * task structs. | ||
719 | */ | ||
720 | static inline void do_copy_page(long *dst, long *src) | ||
732 | { | 721 | { |
733 | int n; | 722 | int n; |
734 | 723 | ||
735 | /* copy_page and memcpy are not usable for copying task structs. */ | ||
736 | for (n = PAGE_SIZE / sizeof(long); n; n--) | 724 | for (n = PAGE_SIZE / sizeof(long); n; n--) |
737 | *dst++ = *src++; | 725 | *dst++ = *src++; |
738 | } | 726 | } |
739 | 727 | ||
728 | #ifdef CONFIG_HIGHMEM | ||
729 | static inline struct page * | ||
730 | page_is_saveable(struct zone *zone, unsigned long pfn) | ||
731 | { | ||
732 | return is_highmem(zone) ? | ||
733 | saveable_highmem_page(pfn) : saveable_page(pfn); | ||
734 | } | ||
735 | |||
736 | static inline void | ||
737 | copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) | ||
738 | { | ||
739 | struct page *s_page, *d_page; | ||
740 | void *src, *dst; | ||
741 | |||
742 | s_page = pfn_to_page(src_pfn); | ||
743 | d_page = pfn_to_page(dst_pfn); | ||
744 | if (PageHighMem(s_page)) { | ||
745 | src = kmap_atomic(s_page, KM_USER0); | ||
746 | dst = kmap_atomic(d_page, KM_USER1); | ||
747 | do_copy_page(dst, src); | ||
748 | kunmap_atomic(src, KM_USER0); | ||
749 | kunmap_atomic(dst, KM_USER1); | ||
750 | } else { | ||
751 | src = page_address(s_page); | ||
752 | if (PageHighMem(d_page)) { | ||
753 | /* Page pointed to by src may contain some kernel | ||
754 | * data modified by kmap_atomic() | ||
755 | */ | ||
756 | do_copy_page(buffer, src); | ||
757 | dst = kmap_atomic(pfn_to_page(dst_pfn), KM_USER0); | ||
758 | memcpy(dst, buffer, PAGE_SIZE); | ||
759 | kunmap_atomic(dst, KM_USER0); | ||
760 | } else { | ||
761 | dst = page_address(d_page); | ||
762 | do_copy_page(dst, src); | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | #else | ||
767 | #define page_is_saveable(zone, pfn) saveable_page(pfn) | ||
768 | |||
769 | static inline void | ||
770 | copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) | ||
771 | { | ||
772 | do_copy_page(page_address(pfn_to_page(dst_pfn)), | ||
773 | page_address(pfn_to_page(src_pfn))); | ||
774 | } | ||
775 | #endif /* CONFIG_HIGHMEM */ | ||
776 | |||
740 | static void | 777 | static void |
741 | copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm) | 778 | copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm) |
742 | { | 779 | { |
743 | struct zone *zone; | 780 | struct zone *zone; |
744 | unsigned long pfn; | 781 | unsigned long pfn; |
745 | 782 | ||
746 | for_each_zone (zone) { | 783 | for_each_zone(zone) { |
747 | unsigned long max_zone_pfn; | 784 | unsigned long max_zone_pfn; |
748 | 785 | ||
749 | if (is_highmem(zone)) | ||
750 | continue; | ||
751 | |||
752 | mark_free_pages(zone); | 786 | mark_free_pages(zone); |
753 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; | 787 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; |
754 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | 788 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) |
755 | if (saveable_page(pfn)) | 789 | if (page_is_saveable(zone, pfn)) |
756 | memory_bm_set_bit(orig_bm, pfn); | 790 | memory_bm_set_bit(orig_bm, pfn); |
757 | } | 791 | } |
758 | memory_bm_position_reset(orig_bm); | 792 | memory_bm_position_reset(orig_bm); |
759 | memory_bm_position_reset(copy_bm); | 793 | memory_bm_position_reset(copy_bm); |
760 | do { | 794 | do { |
761 | pfn = memory_bm_next_pfn(orig_bm); | 795 | pfn = memory_bm_next_pfn(orig_bm); |
762 | if (likely(pfn != BM_END_OF_MAP)) { | 796 | if (likely(pfn != BM_END_OF_MAP)) |
763 | struct page *page; | 797 | copy_data_page(memory_bm_next_pfn(copy_bm), pfn); |
764 | void *src; | ||
765 | |||
766 | page = pfn_to_page(pfn); | ||
767 | src = page_address(page); | ||
768 | page = pfn_to_page(memory_bm_next_pfn(copy_bm)); | ||
769 | copy_data_page(page_address(page), src); | ||
770 | } | ||
771 | } while (pfn != BM_END_OF_MAP); | 798 | } while (pfn != BM_END_OF_MAP); |
772 | } | 799 | } |
773 | 800 | ||
801 | /* Total number of image pages */ | ||
802 | static unsigned int nr_copy_pages; | ||
803 | /* Number of pages needed for saving the original pfns of the image pages */ | ||
804 | static unsigned int nr_meta_pages; | ||
805 | |||
774 | /** | 806 | /** |
775 | * swsusp_free - free pages allocated for the suspend. | 807 | * swsusp_free - free pages allocated for the suspend. |
776 | * | 808 | * |
@@ -792,7 +824,7 @@ void swsusp_free(void) | |||
792 | if (PageNosave(page) && PageNosaveFree(page)) { | 824 | if (PageNosave(page) && PageNosaveFree(page)) { |
793 | ClearPageNosave(page); | 825 | ClearPageNosave(page); |
794 | ClearPageNosaveFree(page); | 826 | ClearPageNosaveFree(page); |
795 | free_page((long) page_address(page)); | 827 | __free_page(page); |
796 | } | 828 | } |
797 | } | 829 | } |
798 | } | 830 | } |
@@ -802,34 +834,108 @@ void swsusp_free(void) | |||
802 | buffer = NULL; | 834 | buffer = NULL; |
803 | } | 835 | } |
804 | 836 | ||
837 | #ifdef CONFIG_HIGHMEM | ||
838 | /** | ||
839 | * count_pages_for_highmem - compute the number of non-highmem pages | ||
840 | * that will be necessary for creating copies of highmem pages. | ||
841 | */ | ||
842 | |||
843 | static unsigned int count_pages_for_highmem(unsigned int nr_highmem) | ||
844 | { | ||
845 | unsigned int free_highmem = count_free_highmem_pages(); | ||
846 | |||
847 | if (free_highmem >= nr_highmem) | ||
848 | nr_highmem = 0; | ||
849 | else | ||
850 | nr_highmem -= free_highmem; | ||
851 | |||
852 | return nr_highmem; | ||
853 | } | ||
854 | #else | ||
855 | static unsigned int | ||
856 | count_pages_for_highmem(unsigned int nr_highmem) { return 0; } | ||
857 | #endif /* CONFIG_HIGHMEM */ | ||
805 | 858 | ||
806 | /** | 859 | /** |
807 | * enough_free_mem - Make sure we enough free memory to snapshot. | 860 | * enough_free_mem - Make sure we have enough free memory for the |
808 | * | 861 | * snapshot image. |
809 | * Returns TRUE or FALSE after checking the number of available | ||
810 | * free pages. | ||
811 | */ | 862 | */ |
812 | 863 | ||
813 | static int enough_free_mem(unsigned int nr_pages) | 864 | static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem) |
814 | { | 865 | { |
815 | struct zone *zone; | 866 | struct zone *zone; |
816 | unsigned int free = 0, meta = 0; | 867 | unsigned int free = 0, meta = 0; |
817 | 868 | ||
818 | for_each_zone (zone) | 869 | for_each_zone(zone) { |
819 | if (!is_highmem(zone)) { | 870 | meta += snapshot_additional_pages(zone); |
871 | if (!is_highmem(zone)) | ||
820 | free += zone->free_pages; | 872 | free += zone->free_pages; |
821 | meta += snapshot_additional_pages(zone); | 873 | } |
822 | } | ||
823 | 874 | ||
824 | pr_debug("swsusp: pages needed: %u + %u + %u, available pages: %u\n", | 875 | nr_pages += count_pages_for_highmem(nr_highmem); |
876 | pr_debug("swsusp: Normal pages needed: %u + %u + %u, available pages: %u\n", | ||
825 | nr_pages, PAGES_FOR_IO, meta, free); | 877 | nr_pages, PAGES_FOR_IO, meta, free); |
826 | 878 | ||
827 | return free > nr_pages + PAGES_FOR_IO + meta; | 879 | return free > nr_pages + PAGES_FOR_IO + meta; |
828 | } | 880 | } |
829 | 881 | ||
882 | #ifdef CONFIG_HIGHMEM | ||
883 | /** | ||
884 | * get_highmem_buffer - if there are some highmem pages in the suspend | ||
885 | * image, we may need the buffer to copy them and/or load their data. | ||
886 | */ | ||
887 | |||
888 | static inline int get_highmem_buffer(int safe_needed) | ||
889 | { | ||
890 | buffer = get_image_page(GFP_ATOMIC | __GFP_COLD, safe_needed); | ||
891 | return buffer ? 0 : -ENOMEM; | ||
892 | } | ||
893 | |||
894 | /** | ||
895 | * alloc_highmem_image_pages - allocate some highmem pages for the image. | ||
896 | * Try to allocate as many pages as needed, but if the number of free | ||
897 | * highmem pages is lesser than that, allocate them all. | ||
898 | */ | ||
899 | |||
900 | static inline unsigned int | ||
901 | alloc_highmem_image_pages(struct memory_bitmap *bm, unsigned int nr_highmem) | ||
902 | { | ||
903 | unsigned int to_alloc = count_free_highmem_pages(); | ||
904 | |||
905 | if (to_alloc > nr_highmem) | ||
906 | to_alloc = nr_highmem; | ||
907 | |||
908 | nr_highmem -= to_alloc; | ||
909 | while (to_alloc-- > 0) { | ||
910 | struct page *page; | ||
911 | |||
912 | page = alloc_image_page(__GFP_HIGHMEM); | ||
913 | memory_bm_set_bit(bm, page_to_pfn(page)); | ||
914 | } | ||
915 | return nr_highmem; | ||
916 | } | ||
917 | #else | ||
918 | static inline int get_highmem_buffer(int safe_needed) { return 0; } | ||
919 | |||
920 | static inline unsigned int | ||
921 | alloc_highmem_image_pages(struct memory_bitmap *bm, unsigned int n) { return 0; } | ||
922 | #endif /* CONFIG_HIGHMEM */ | ||
923 | |||
924 | /** | ||
925 | * swsusp_alloc - allocate memory for the suspend image | ||
926 | * | ||
927 | * We first try to allocate as many highmem pages as there are | ||
928 | * saveable highmem pages in the system. If that fails, we allocate | ||
929 | * non-highmem pages for the copies of the remaining highmem ones. | ||
930 | * | ||
931 | * In this approach it is likely that the copies of highmem pages will | ||
932 | * also be located in the high memory, because of the way in which | ||
933 | * copy_data_pages() works. | ||
934 | */ | ||
935 | |||
830 | static int | 936 | static int |
831 | swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, | 937 | swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, |
832 | unsigned int nr_pages) | 938 | unsigned int nr_pages, unsigned int nr_highmem) |
833 | { | 939 | { |
834 | int error; | 940 | int error; |
835 | 941 | ||
@@ -841,46 +947,61 @@ swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, | |||
841 | if (error) | 947 | if (error) |
842 | goto Free; | 948 | goto Free; |
843 | 949 | ||
950 | if (nr_highmem > 0) { | ||
951 | error = get_highmem_buffer(PG_ANY); | ||
952 | if (error) | ||
953 | goto Free; | ||
954 | |||
955 | nr_pages += alloc_highmem_image_pages(copy_bm, nr_highmem); | ||
956 | } | ||
844 | while (nr_pages-- > 0) { | 957 | while (nr_pages-- > 0) { |
845 | struct page *page = alloc_page(GFP_ATOMIC | __GFP_COLD); | 958 | struct page *page = alloc_image_page(GFP_ATOMIC | __GFP_COLD); |
959 | |||
846 | if (!page) | 960 | if (!page) |
847 | goto Free; | 961 | goto Free; |
848 | 962 | ||
849 | SetPageNosave(page); | ||
850 | SetPageNosaveFree(page); | ||
851 | memory_bm_set_bit(copy_bm, page_to_pfn(page)); | 963 | memory_bm_set_bit(copy_bm, page_to_pfn(page)); |
852 | } | 964 | } |
853 | return 0; | 965 | return 0; |
854 | 966 | ||
855 | Free: | 967 | Free: |
856 | swsusp_free(); | 968 | swsusp_free(); |
857 | return -ENOMEM; | 969 | return -ENOMEM; |
858 | } | 970 | } |
859 | 971 | ||
860 | /* Memory bitmap used for marking saveable pages */ | 972 | /* Memory bitmap used for marking saveable pages (during suspend) or the |
973 | * suspend image pages (during resume) | ||
974 | */ | ||
861 | static struct memory_bitmap orig_bm; | 975 | static struct memory_bitmap orig_bm; |
862 | /* Memory bitmap used for marking allocated pages that will contain the copies | 976 | /* Memory bitmap used on suspend for marking allocated pages that will contain |
863 | * of saveable pages | 977 | * the copies of saveable pages. During resume it is initially used for |
978 | * marking the suspend image pages, but then its set bits are duplicated in | ||
979 | * @orig_bm and it is released. Next, on systems with high memory, it may be | ||
980 | * used for marking "safe" highmem pages, but it has to be reinitialized for | ||
981 | * this purpose. | ||
864 | */ | 982 | */ |
865 | static struct memory_bitmap copy_bm; | 983 | static struct memory_bitmap copy_bm; |
866 | 984 | ||
867 | asmlinkage int swsusp_save(void) | 985 | asmlinkage int swsusp_save(void) |
868 | { | 986 | { |
869 | unsigned int nr_pages; | 987 | unsigned int nr_pages, nr_highmem; |
870 | 988 | ||
871 | pr_debug("swsusp: critical section: \n"); | 989 | printk("swsusp: critical section: \n"); |
872 | 990 | ||
873 | drain_local_pages(); | 991 | drain_local_pages(); |
874 | nr_pages = count_data_pages(); | 992 | nr_pages = count_data_pages(); |
875 | printk("swsusp: Need to copy %u pages\n", nr_pages); | 993 | nr_highmem = count_highmem_pages(); |
994 | printk("swsusp: Need to copy %u pages\n", nr_pages + nr_highmem); | ||
876 | 995 | ||
877 | if (!enough_free_mem(nr_pages)) { | 996 | if (!enough_free_mem(nr_pages, nr_highmem)) { |
878 | printk(KERN_ERR "swsusp: Not enough free memory\n"); | 997 | printk(KERN_ERR "swsusp: Not enough free memory\n"); |
879 | return -ENOMEM; | 998 | return -ENOMEM; |
880 | } | 999 | } |
881 | 1000 | ||
882 | if (swsusp_alloc(&orig_bm, ©_bm, nr_pages)) | 1001 | if (swsusp_alloc(&orig_bm, ©_bm, nr_pages, nr_highmem)) { |
1002 | printk(KERN_ERR "swsusp: Memory allocation failed\n"); | ||
883 | return -ENOMEM; | 1003 | return -ENOMEM; |
1004 | } | ||
884 | 1005 | ||
885 | /* During allocating of suspend pagedir, new cold pages may appear. | 1006 | /* During allocating of suspend pagedir, new cold pages may appear. |
886 | * Kill them. | 1007 | * Kill them. |
@@ -894,10 +1015,12 @@ asmlinkage int swsusp_save(void) | |||
894 | * touch swap space! Except we must write out our image of course. | 1015 | * touch swap space! Except we must write out our image of course. |
895 | */ | 1016 | */ |
896 | 1017 | ||
1018 | nr_pages += nr_highmem; | ||
897 | nr_copy_pages = nr_pages; | 1019 | nr_copy_pages = nr_pages; |
898 | nr_meta_pages = (nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT; | 1020 | nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE); |
899 | 1021 | ||
900 | printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages); | 1022 | printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages); |
1023 | |||
901 | return 0; | 1024 | return 0; |
902 | } | 1025 | } |
903 | 1026 | ||
@@ -960,7 +1083,7 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count) | |||
960 | 1083 | ||
961 | if (!buffer) { | 1084 | if (!buffer) { |
962 | /* This makes the buffer be freed by swsusp_free() */ | 1085 | /* This makes the buffer be freed by swsusp_free() */ |
963 | buffer = alloc_image_page(GFP_ATOMIC, PG_ANY); | 1086 | buffer = get_image_page(GFP_ATOMIC, PG_ANY); |
964 | if (!buffer) | 1087 | if (!buffer) |
965 | return -ENOMEM; | 1088 | return -ENOMEM; |
966 | } | 1089 | } |
@@ -975,9 +1098,23 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count) | |||
975 | memset(buffer, 0, PAGE_SIZE); | 1098 | memset(buffer, 0, PAGE_SIZE); |
976 | pack_pfns(buffer, &orig_bm); | 1099 | pack_pfns(buffer, &orig_bm); |
977 | } else { | 1100 | } else { |
978 | unsigned long pfn = memory_bm_next_pfn(©_bm); | 1101 | struct page *page; |
979 | 1102 | ||
980 | handle->buffer = page_address(pfn_to_page(pfn)); | 1103 | page = pfn_to_page(memory_bm_next_pfn(©_bm)); |
1104 | if (PageHighMem(page)) { | ||
1105 | /* Highmem pages are copied to the buffer, | ||
1106 | * because we can't return with a kmapped | ||
1107 | * highmem page (we may not be called again). | ||
1108 | */ | ||
1109 | void *kaddr; | ||
1110 | |||
1111 | kaddr = kmap_atomic(page, KM_USER0); | ||
1112 | memcpy(buffer, kaddr, PAGE_SIZE); | ||
1113 | kunmap_atomic(kaddr, KM_USER0); | ||
1114 | handle->buffer = buffer; | ||
1115 | } else { | ||
1116 | handle->buffer = page_address(page); | ||
1117 | } | ||
981 | } | 1118 | } |
982 | handle->prev = handle->cur; | 1119 | handle->prev = handle->cur; |
983 | } | 1120 | } |
@@ -1005,7 +1142,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm) | |||
1005 | unsigned long pfn, max_zone_pfn; | 1142 | unsigned long pfn, max_zone_pfn; |
1006 | 1143 | ||
1007 | /* Clear page flags */ | 1144 | /* Clear page flags */ |
1008 | for_each_zone (zone) { | 1145 | for_each_zone(zone) { |
1009 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; | 1146 | max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages; |
1010 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | 1147 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) |
1011 | if (pfn_valid(pfn)) | 1148 | if (pfn_valid(pfn)) |
@@ -1101,6 +1238,218 @@ unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) | |||
1101 | } | 1238 | } |
1102 | } | 1239 | } |
1103 | 1240 | ||
1241 | /* List of "safe" pages that may be used to store data loaded from the suspend | ||
1242 | * image | ||
1243 | */ | ||
1244 | static struct linked_page *safe_pages_list; | ||
1245 | |||
1246 | #ifdef CONFIG_HIGHMEM | ||
1247 | /* struct highmem_pbe is used for creating the list of highmem pages that | ||
1248 | * should be restored atomically during the resume from disk, because the page | ||
1249 | * frames they have occupied before the suspend are in use. | ||
1250 | */ | ||
1251 | struct highmem_pbe { | ||
1252 | struct page *copy_page; /* data is here now */ | ||
1253 | struct page *orig_page; /* data was here before the suspend */ | ||
1254 | struct highmem_pbe *next; | ||
1255 | }; | ||
1256 | |||
1257 | /* List of highmem PBEs needed for restoring the highmem pages that were | ||
1258 | * allocated before the suspend and included in the suspend image, but have | ||
1259 | * also been allocated by the "resume" kernel, so their contents cannot be | ||
1260 | * written directly to their "original" page frames. | ||
1261 | */ | ||
1262 | static struct highmem_pbe *highmem_pblist; | ||
1263 | |||
1264 | /** | ||
1265 | * count_highmem_image_pages - compute the number of highmem pages in the | ||
1266 | * suspend image. The bits in the memory bitmap @bm that correspond to the | ||
1267 | * image pages are assumed to be set. | ||
1268 | */ | ||
1269 | |||
1270 | static unsigned int count_highmem_image_pages(struct memory_bitmap *bm) | ||
1271 | { | ||
1272 | unsigned long pfn; | ||
1273 | unsigned int cnt = 0; | ||
1274 | |||
1275 | memory_bm_position_reset(bm); | ||
1276 | pfn = memory_bm_next_pfn(bm); | ||
1277 | while (pfn != BM_END_OF_MAP) { | ||
1278 | if (PageHighMem(pfn_to_page(pfn))) | ||
1279 | cnt++; | ||
1280 | |||
1281 | pfn = memory_bm_next_pfn(bm); | ||
1282 | } | ||
1283 | return cnt; | ||
1284 | } | ||
1285 | |||
1286 | /** | ||
1287 | * prepare_highmem_image - try to allocate as many highmem pages as | ||
1288 | * there are highmem image pages (@nr_highmem_p points to the variable | ||
1289 | * containing the number of highmem image pages). The pages that are | ||
1290 | * "safe" (ie. will not be overwritten when the suspend image is | ||
1291 | * restored) have the corresponding bits set in @bm (it must be | ||
1292 | * unitialized). | ||
1293 | * | ||
1294 | * NOTE: This function should not be called if there are no highmem | ||
1295 | * image pages. | ||
1296 | */ | ||
1297 | |||
1298 | static unsigned int safe_highmem_pages; | ||
1299 | |||
1300 | static struct memory_bitmap *safe_highmem_bm; | ||
1301 | |||
1302 | static int | ||
1303 | prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p) | ||
1304 | { | ||
1305 | unsigned int to_alloc; | ||
1306 | |||
1307 | if (memory_bm_create(bm, GFP_ATOMIC, PG_SAFE)) | ||
1308 | return -ENOMEM; | ||
1309 | |||
1310 | if (get_highmem_buffer(PG_SAFE)) | ||
1311 | return -ENOMEM; | ||
1312 | |||
1313 | to_alloc = count_free_highmem_pages(); | ||
1314 | if (to_alloc > *nr_highmem_p) | ||
1315 | to_alloc = *nr_highmem_p; | ||
1316 | else | ||
1317 | *nr_highmem_p = to_alloc; | ||
1318 | |||
1319 | safe_highmem_pages = 0; | ||
1320 | while (to_alloc-- > 0) { | ||
1321 | struct page *page; | ||
1322 | |||
1323 | page = alloc_page(__GFP_HIGHMEM); | ||
1324 | if (!PageNosaveFree(page)) { | ||
1325 | /* The page is "safe", set its bit the bitmap */ | ||
1326 | memory_bm_set_bit(bm, page_to_pfn(page)); | ||
1327 | safe_highmem_pages++; | ||
1328 | } | ||
1329 | /* Mark the page as allocated */ | ||
1330 | SetPageNosave(page); | ||
1331 | SetPageNosaveFree(page); | ||
1332 | } | ||
1333 | memory_bm_position_reset(bm); | ||
1334 | safe_highmem_bm = bm; | ||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1338 | /** | ||
1339 | * get_highmem_page_buffer - for given highmem image page find the buffer | ||
1340 | * that suspend_write_next() should set for its caller to write to. | ||
1341 | * | ||
1342 | * If the page is to be saved to its "original" page frame or a copy of | ||
1343 | * the page is to be made in the highmem, @buffer is returned. Otherwise, | ||
1344 | * the copy of the page is to be made in normal memory, so the address of | ||
1345 | * the copy is returned. | ||
1346 | * | ||
1347 | * If @buffer is returned, the caller of suspend_write_next() will write | ||
1348 | * the page's contents to @buffer, so they will have to be copied to the | ||
1349 | * right location on the next call to suspend_write_next() and it is done | ||
1350 | * with the help of copy_last_highmem_page(). For this purpose, if | ||
1351 | * @buffer is returned, @last_highmem page is set to the page to which | ||
1352 | * the data will have to be copied from @buffer. | ||
1353 | */ | ||
1354 | |||
1355 | static struct page *last_highmem_page; | ||
1356 | |||
1357 | static void * | ||
1358 | get_highmem_page_buffer(struct page *page, struct chain_allocator *ca) | ||
1359 | { | ||
1360 | struct highmem_pbe *pbe; | ||
1361 | void *kaddr; | ||
1362 | |||
1363 | if (PageNosave(page) && PageNosaveFree(page)) { | ||
1364 | /* We have allocated the "original" page frame and we can | ||
1365 | * use it directly to store the loaded page. | ||
1366 | */ | ||
1367 | last_highmem_page = page; | ||
1368 | return buffer; | ||
1369 | } | ||
1370 | /* The "original" page frame has not been allocated and we have to | ||
1371 | * use a "safe" page frame to store the loaded page. | ||
1372 | */ | ||
1373 | pbe = chain_alloc(ca, sizeof(struct highmem_pbe)); | ||
1374 | if (!pbe) { | ||
1375 | swsusp_free(); | ||
1376 | return NULL; | ||
1377 | } | ||
1378 | pbe->orig_page = page; | ||
1379 | if (safe_highmem_pages > 0) { | ||
1380 | struct page *tmp; | ||
1381 | |||
1382 | /* Copy of the page will be stored in high memory */ | ||
1383 | kaddr = buffer; | ||
1384 | tmp = pfn_to_page(memory_bm_next_pfn(safe_highmem_bm)); | ||
1385 | safe_highmem_pages--; | ||
1386 | last_highmem_page = tmp; | ||
1387 | pbe->copy_page = tmp; | ||
1388 | } else { | ||
1389 | /* Copy of the page will be stored in normal memory */ | ||
1390 | kaddr = safe_pages_list; | ||
1391 | safe_pages_list = safe_pages_list->next; | ||
1392 | pbe->copy_page = virt_to_page(kaddr); | ||
1393 | } | ||
1394 | pbe->next = highmem_pblist; | ||
1395 | highmem_pblist = pbe; | ||
1396 | return kaddr; | ||
1397 | } | ||
1398 | |||
1399 | /** | ||
1400 | * copy_last_highmem_page - copy the contents of a highmem image from | ||
1401 | * @buffer, where the caller of snapshot_write_next() has place them, | ||
1402 | * to the right location represented by @last_highmem_page . | ||
1403 | */ | ||
1404 | |||
1405 | static void copy_last_highmem_page(void) | ||
1406 | { | ||
1407 | if (last_highmem_page) { | ||
1408 | void *dst; | ||
1409 | |||
1410 | dst = kmap_atomic(last_highmem_page, KM_USER0); | ||
1411 | memcpy(dst, buffer, PAGE_SIZE); | ||
1412 | kunmap_atomic(dst, KM_USER0); | ||
1413 | last_highmem_page = NULL; | ||
1414 | } | ||
1415 | } | ||
1416 | |||
1417 | static inline int last_highmem_page_copied(void) | ||
1418 | { | ||
1419 | return !last_highmem_page; | ||
1420 | } | ||
1421 | |||
1422 | static inline void free_highmem_data(void) | ||
1423 | { | ||
1424 | if (safe_highmem_bm) | ||
1425 | memory_bm_free(safe_highmem_bm, PG_UNSAFE_CLEAR); | ||
1426 | |||
1427 | if (buffer) | ||
1428 | free_image_page(buffer, PG_UNSAFE_CLEAR); | ||
1429 | } | ||
1430 | #else | ||
1431 | static inline int get_safe_write_buffer(void) { return 0; } | ||
1432 | |||
1433 | static unsigned int | ||
1434 | count_highmem_image_pages(struct memory_bitmap *bm) { return 0; } | ||
1435 | |||
1436 | static inline int | ||
1437 | prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p) | ||
1438 | { | ||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | static inline void * | ||
1443 | get_highmem_page_buffer(struct page *page, struct chain_allocator *ca) | ||
1444 | { | ||
1445 | return NULL; | ||
1446 | } | ||
1447 | |||
1448 | static inline void copy_last_highmem_page(void) {} | ||
1449 | static inline int last_highmem_page_copied(void) { return 1; } | ||
1450 | static inline void free_highmem_data(void) {} | ||
1451 | #endif /* CONFIG_HIGHMEM */ | ||
1452 | |||
1104 | /** | 1453 | /** |
1105 | * prepare_image - use the memory bitmap @bm to mark the pages that will | 1454 | * prepare_image - use the memory bitmap @bm to mark the pages that will |
1106 | * be overwritten in the process of restoring the system memory state | 1455 | * be overwritten in the process of restoring the system memory state |
@@ -1110,20 +1459,25 @@ unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) | |||
1110 | * The idea is to allocate a new memory bitmap first and then allocate | 1459 | * The idea is to allocate a new memory bitmap first and then allocate |
1111 | * as many pages as needed for the image data, but not to assign these | 1460 | * as many pages as needed for the image data, but not to assign these |
1112 | * pages to specific tasks initially. Instead, we just mark them as | 1461 | * pages to specific tasks initially. Instead, we just mark them as |
1113 | * allocated and create a list of "safe" pages that will be used later. | 1462 | * allocated and create a lists of "safe" pages that will be used |
1463 | * later. On systems with high memory a list of "safe" highmem pages is | ||
1464 | * also created. | ||
1114 | */ | 1465 | */ |
1115 | 1466 | ||
1116 | #define PBES_PER_LINKED_PAGE (LINKED_PAGE_DATA_SIZE / sizeof(struct pbe)) | 1467 | #define PBES_PER_LINKED_PAGE (LINKED_PAGE_DATA_SIZE / sizeof(struct pbe)) |
1117 | 1468 | ||
1118 | static struct linked_page *safe_pages_list; | ||
1119 | |||
1120 | static int | 1469 | static int |
1121 | prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) | 1470 | prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) |
1122 | { | 1471 | { |
1123 | unsigned int nr_pages; | 1472 | unsigned int nr_pages, nr_highmem; |
1124 | struct linked_page *sp_list, *lp; | 1473 | struct linked_page *sp_list, *lp; |
1125 | int error; | 1474 | int error; |
1126 | 1475 | ||
1476 | /* If there is no highmem, the buffer will not be necessary */ | ||
1477 | free_image_page(buffer, PG_UNSAFE_CLEAR); | ||
1478 | buffer = NULL; | ||
1479 | |||
1480 | nr_highmem = count_highmem_image_pages(bm); | ||
1127 | error = mark_unsafe_pages(bm); | 1481 | error = mark_unsafe_pages(bm); |
1128 | if (error) | 1482 | if (error) |
1129 | goto Free; | 1483 | goto Free; |
@@ -1134,6 +1488,11 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) | |||
1134 | 1488 | ||
1135 | duplicate_memory_bitmap(new_bm, bm); | 1489 | duplicate_memory_bitmap(new_bm, bm); |
1136 | memory_bm_free(bm, PG_UNSAFE_KEEP); | 1490 | memory_bm_free(bm, PG_UNSAFE_KEEP); |
1491 | if (nr_highmem > 0) { | ||
1492 | error = prepare_highmem_image(bm, &nr_highmem); | ||
1493 | if (error) | ||
1494 | goto Free; | ||
1495 | } | ||
1137 | /* Reserve some safe pages for potential later use. | 1496 | /* Reserve some safe pages for potential later use. |
1138 | * | 1497 | * |
1139 | * NOTE: This way we make sure there will be enough safe pages for the | 1498 | * NOTE: This way we make sure there will be enough safe pages for the |
@@ -1142,10 +1501,10 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) | |||
1142 | */ | 1501 | */ |
1143 | sp_list = NULL; | 1502 | sp_list = NULL; |
1144 | /* nr_copy_pages cannot be lesser than allocated_unsafe_pages */ | 1503 | /* nr_copy_pages cannot be lesser than allocated_unsafe_pages */ |
1145 | nr_pages = nr_copy_pages - allocated_unsafe_pages; | 1504 | nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages; |
1146 | nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE); | 1505 | nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE); |
1147 | while (nr_pages > 0) { | 1506 | while (nr_pages > 0) { |
1148 | lp = alloc_image_page(GFP_ATOMIC, PG_SAFE); | 1507 | lp = get_image_page(GFP_ATOMIC, PG_SAFE); |
1149 | if (!lp) { | 1508 | if (!lp) { |
1150 | error = -ENOMEM; | 1509 | error = -ENOMEM; |
1151 | goto Free; | 1510 | goto Free; |
@@ -1156,7 +1515,7 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) | |||
1156 | } | 1515 | } |
1157 | /* Preallocate memory for the image */ | 1516 | /* Preallocate memory for the image */ |
1158 | safe_pages_list = NULL; | 1517 | safe_pages_list = NULL; |
1159 | nr_pages = nr_copy_pages - allocated_unsafe_pages; | 1518 | nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages; |
1160 | while (nr_pages > 0) { | 1519 | while (nr_pages > 0) { |
1161 | lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC); | 1520 | lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC); |
1162 | if (!lp) { | 1521 | if (!lp) { |
@@ -1181,7 +1540,7 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) | |||
1181 | } | 1540 | } |
1182 | return 0; | 1541 | return 0; |
1183 | 1542 | ||
1184 | Free: | 1543 | Free: |
1185 | swsusp_free(); | 1544 | swsusp_free(); |
1186 | return error; | 1545 | return error; |
1187 | } | 1546 | } |
@@ -1196,6 +1555,9 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) | |||
1196 | struct pbe *pbe; | 1555 | struct pbe *pbe; |
1197 | struct page *page = pfn_to_page(memory_bm_next_pfn(bm)); | 1556 | struct page *page = pfn_to_page(memory_bm_next_pfn(bm)); |
1198 | 1557 | ||
1558 | if (PageHighMem(page)) | ||
1559 | return get_highmem_page_buffer(page, ca); | ||
1560 | |||
1199 | if (PageNosave(page) && PageNosaveFree(page)) | 1561 | if (PageNosave(page) && PageNosaveFree(page)) |
1200 | /* We have allocated the "original" page frame and we can | 1562 | /* We have allocated the "original" page frame and we can |
1201 | * use it directly to store the loaded page. | 1563 | * use it directly to store the loaded page. |
@@ -1210,12 +1572,12 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) | |||
1210 | swsusp_free(); | 1572 | swsusp_free(); |
1211 | return NULL; | 1573 | return NULL; |
1212 | } | 1574 | } |
1213 | pbe->orig_address = (unsigned long)page_address(page); | 1575 | pbe->orig_address = page_address(page); |
1214 | pbe->address = (unsigned long)safe_pages_list; | 1576 | pbe->address = safe_pages_list; |
1215 | safe_pages_list = safe_pages_list->next; | 1577 | safe_pages_list = safe_pages_list->next; |
1216 | pbe->next = restore_pblist; | 1578 | pbe->next = restore_pblist; |
1217 | restore_pblist = pbe; | 1579 | restore_pblist = pbe; |
1218 | return (void *)pbe->address; | 1580 | return pbe->address; |
1219 | } | 1581 | } |
1220 | 1582 | ||
1221 | /** | 1583 | /** |
@@ -1249,14 +1611,16 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count) | |||
1249 | if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) | 1611 | if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) |
1250 | return 0; | 1612 | return 0; |
1251 | 1613 | ||
1252 | if (!buffer) { | 1614 | if (handle->offset == 0) { |
1253 | /* This makes the buffer be freed by swsusp_free() */ | 1615 | if (!buffer) |
1254 | buffer = alloc_image_page(GFP_ATOMIC, PG_ANY); | 1616 | /* This makes the buffer be freed by swsusp_free() */ |
1617 | buffer = get_image_page(GFP_ATOMIC, PG_ANY); | ||
1618 | |||
1255 | if (!buffer) | 1619 | if (!buffer) |
1256 | return -ENOMEM; | 1620 | return -ENOMEM; |
1257 | } | 1621 | |
1258 | if (!handle->offset) | ||
1259 | handle->buffer = buffer; | 1622 | handle->buffer = buffer; |
1623 | } | ||
1260 | handle->sync_read = 1; | 1624 | handle->sync_read = 1; |
1261 | if (handle->prev < handle->cur) { | 1625 | if (handle->prev < handle->cur) { |
1262 | if (handle->prev == 0) { | 1626 | if (handle->prev == 0) { |
@@ -1284,8 +1648,10 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count) | |||
1284 | return -ENOMEM; | 1648 | return -ENOMEM; |
1285 | } | 1649 | } |
1286 | } else { | 1650 | } else { |
1651 | copy_last_highmem_page(); | ||
1287 | handle->buffer = get_buffer(&orig_bm, &ca); | 1652 | handle->buffer = get_buffer(&orig_bm, &ca); |
1288 | handle->sync_read = 0; | 1653 | if (handle->buffer != buffer) |
1654 | handle->sync_read = 0; | ||
1289 | } | 1655 | } |
1290 | handle->prev = handle->cur; | 1656 | handle->prev = handle->cur; |
1291 | } | 1657 | } |
@@ -1301,15 +1667,73 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count) | |||
1301 | return count; | 1667 | return count; |
1302 | } | 1668 | } |
1303 | 1669 | ||
1670 | /** | ||
1671 | * snapshot_write_finalize - must be called after the last call to | ||
1672 | * snapshot_write_next() in case the last page in the image happens | ||
1673 | * to be a highmem page and its contents should be stored in the | ||
1674 | * highmem. Additionally, it releases the memory that will not be | ||
1675 | * used any more. | ||
1676 | */ | ||
1677 | |||
1678 | void snapshot_write_finalize(struct snapshot_handle *handle) | ||
1679 | { | ||
1680 | copy_last_highmem_page(); | ||
1681 | /* Free only if we have loaded the image entirely */ | ||
1682 | if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) { | ||
1683 | memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR); | ||
1684 | free_highmem_data(); | ||
1685 | } | ||
1686 | } | ||
1687 | |||
1304 | int snapshot_image_loaded(struct snapshot_handle *handle) | 1688 | int snapshot_image_loaded(struct snapshot_handle *handle) |
1305 | { | 1689 | { |
1306 | return !(!nr_copy_pages || | 1690 | return !(!nr_copy_pages || !last_highmem_page_copied() || |
1307 | handle->cur <= nr_meta_pages + nr_copy_pages); | 1691 | handle->cur <= nr_meta_pages + nr_copy_pages); |
1308 | } | 1692 | } |
1309 | 1693 | ||
1310 | void snapshot_free_unused_memory(struct snapshot_handle *handle) | 1694 | #ifdef CONFIG_HIGHMEM |
1695 | /* Assumes that @buf is ready and points to a "safe" page */ | ||
1696 | static inline void | ||
1697 | swap_two_pages_data(struct page *p1, struct page *p2, void *buf) | ||
1311 | { | 1698 | { |
1312 | /* Free only if we have loaded the image entirely */ | 1699 | void *kaddr1, *kaddr2; |
1313 | if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) | 1700 | |
1314 | memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR); | 1701 | kaddr1 = kmap_atomic(p1, KM_USER0); |
1702 | kaddr2 = kmap_atomic(p2, KM_USER1); | ||
1703 | memcpy(buf, kaddr1, PAGE_SIZE); | ||
1704 | memcpy(kaddr1, kaddr2, PAGE_SIZE); | ||
1705 | memcpy(kaddr2, buf, PAGE_SIZE); | ||
1706 | kunmap_atomic(kaddr1, KM_USER0); | ||
1707 | kunmap_atomic(kaddr2, KM_USER1); | ||
1708 | } | ||
1709 | |||
1710 | /** | ||
1711 | * restore_highmem - for each highmem page that was allocated before | ||
1712 | * the suspend and included in the suspend image, and also has been | ||
1713 | * allocated by the "resume" kernel swap its current (ie. "before | ||
1714 | * resume") contents with the previous (ie. "before suspend") one. | ||
1715 | * | ||
1716 | * If the resume eventually fails, we can call this function once | ||
1717 | * again and restore the "before resume" highmem state. | ||
1718 | */ | ||
1719 | |||
1720 | int restore_highmem(void) | ||
1721 | { | ||
1722 | struct highmem_pbe *pbe = highmem_pblist; | ||
1723 | void *buf; | ||
1724 | |||
1725 | if (!pbe) | ||
1726 | return 0; | ||
1727 | |||
1728 | buf = get_image_page(GFP_ATOMIC, PG_SAFE); | ||
1729 | if (!buf) | ||
1730 | return -ENOMEM; | ||
1731 | |||
1732 | while (pbe) { | ||
1733 | swap_two_pages_data(pbe->copy_page, pbe->orig_page, buf); | ||
1734 | pbe = pbe->next; | ||
1735 | } | ||
1736 | free_image_page(buf, PG_UNSAFE_CLEAR); | ||
1737 | return 0; | ||
1315 | } | 1738 | } |
1739 | #endif /* CONFIG_HIGHMEM */ | ||
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 1a3b0dd2c3fc..f133d4a6d817 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -34,34 +34,123 @@ extern char resume_file[]; | |||
34 | #define SWSUSP_SIG "S1SUSPEND" | 34 | #define SWSUSP_SIG "S1SUSPEND" |
35 | 35 | ||
36 | static struct swsusp_header { | 36 | static struct swsusp_header { |
37 | char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; | 37 | char reserved[PAGE_SIZE - 20 - sizeof(sector_t)]; |
38 | swp_entry_t image; | 38 | sector_t image; |
39 | char orig_sig[10]; | 39 | char orig_sig[10]; |
40 | char sig[10]; | 40 | char sig[10]; |
41 | } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; | 41 | } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Saving part... | 44 | * General things |
45 | */ | 45 | */ |
46 | 46 | ||
47 | static unsigned short root_swap = 0xffff; | 47 | static unsigned short root_swap = 0xffff; |
48 | static struct block_device *resume_bdev; | ||
49 | |||
50 | /** | ||
51 | * submit - submit BIO request. | ||
52 | * @rw: READ or WRITE. | ||
53 | * @off physical offset of page. | ||
54 | * @page: page we're reading or writing. | ||
55 | * @bio_chain: list of pending biod (for async reading) | ||
56 | * | ||
57 | * Straight from the textbook - allocate and initialize the bio. | ||
58 | * If we're reading, make sure the page is marked as dirty. | ||
59 | * Then submit it and, if @bio_chain == NULL, wait. | ||
60 | */ | ||
61 | static int submit(int rw, pgoff_t page_off, struct page *page, | ||
62 | struct bio **bio_chain) | ||
63 | { | ||
64 | struct bio *bio; | ||
65 | |||
66 | bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); | ||
67 | if (!bio) | ||
68 | return -ENOMEM; | ||
69 | bio->bi_sector = page_off * (PAGE_SIZE >> 9); | ||
70 | bio->bi_bdev = resume_bdev; | ||
71 | bio->bi_end_io = end_swap_bio_read; | ||
72 | |||
73 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | ||
74 | printk("swsusp: ERROR: adding page to bio at %ld\n", page_off); | ||
75 | bio_put(bio); | ||
76 | return -EFAULT; | ||
77 | } | ||
78 | |||
79 | lock_page(page); | ||
80 | bio_get(bio); | ||
81 | |||
82 | if (bio_chain == NULL) { | ||
83 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
84 | wait_on_page_locked(page); | ||
85 | if (rw == READ) | ||
86 | bio_set_pages_dirty(bio); | ||
87 | bio_put(bio); | ||
88 | } else { | ||
89 | if (rw == READ) | ||
90 | get_page(page); /* These pages are freed later */ | ||
91 | bio->bi_private = *bio_chain; | ||
92 | *bio_chain = bio; | ||
93 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
94 | } | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
99 | { | ||
100 | return submit(READ, page_off, virt_to_page(addr), bio_chain); | ||
101 | } | ||
102 | |||
103 | static int bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
104 | { | ||
105 | return submit(WRITE, page_off, virt_to_page(addr), bio_chain); | ||
106 | } | ||
107 | |||
108 | static int wait_on_bio_chain(struct bio **bio_chain) | ||
109 | { | ||
110 | struct bio *bio; | ||
111 | struct bio *next_bio; | ||
112 | int ret = 0; | ||
113 | |||
114 | if (bio_chain == NULL) | ||
115 | return 0; | ||
116 | |||
117 | bio = *bio_chain; | ||
118 | if (bio == NULL) | ||
119 | return 0; | ||
120 | while (bio) { | ||
121 | struct page *page; | ||
122 | |||
123 | next_bio = bio->bi_private; | ||
124 | page = bio->bi_io_vec[0].bv_page; | ||
125 | wait_on_page_locked(page); | ||
126 | if (!PageUptodate(page) || PageError(page)) | ||
127 | ret = -EIO; | ||
128 | put_page(page); | ||
129 | bio_put(bio); | ||
130 | bio = next_bio; | ||
131 | } | ||
132 | *bio_chain = NULL; | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Saving part | ||
138 | */ | ||
48 | 139 | ||
49 | static int mark_swapfiles(swp_entry_t start) | 140 | static int mark_swapfiles(sector_t start) |
50 | { | 141 | { |
51 | int error; | 142 | int error; |
52 | 143 | ||
53 | rw_swap_page_sync(READ, swp_entry(root_swap, 0), | 144 | bio_read_page(swsusp_resume_block, &swsusp_header, NULL); |
54 | virt_to_page((unsigned long)&swsusp_header), NULL); | ||
55 | if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || | 145 | if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || |
56 | !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { | 146 | !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { |
57 | memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); | 147 | memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); |
58 | memcpy(swsusp_header.sig,SWSUSP_SIG, 10); | 148 | memcpy(swsusp_header.sig,SWSUSP_SIG, 10); |
59 | swsusp_header.image = start; | 149 | swsusp_header.image = start; |
60 | error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0), | 150 | error = bio_write_page(swsusp_resume_block, |
61 | virt_to_page((unsigned long)&swsusp_header), | 151 | &swsusp_header, NULL); |
62 | NULL); | ||
63 | } else { | 152 | } else { |
64 | pr_debug("swsusp: Partition is not swap space.\n"); | 153 | printk(KERN_ERR "swsusp: Swap header not found!\n"); |
65 | error = -ENODEV; | 154 | error = -ENODEV; |
66 | } | 155 | } |
67 | return error; | 156 | return error; |
@@ -74,12 +163,21 @@ static int mark_swapfiles(swp_entry_t start) | |||
74 | 163 | ||
75 | static int swsusp_swap_check(void) /* This is called before saving image */ | 164 | static int swsusp_swap_check(void) /* This is called before saving image */ |
76 | { | 165 | { |
77 | int res = swap_type_of(swsusp_resume_device); | 166 | int res; |
167 | |||
168 | res = swap_type_of(swsusp_resume_device, swsusp_resume_block); | ||
169 | if (res < 0) | ||
170 | return res; | ||
171 | |||
172 | root_swap = res; | ||
173 | resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_WRITE); | ||
174 | if (IS_ERR(resume_bdev)) | ||
175 | return PTR_ERR(resume_bdev); | ||
176 | |||
177 | res = set_blocksize(resume_bdev, PAGE_SIZE); | ||
178 | if (res < 0) | ||
179 | blkdev_put(resume_bdev); | ||
78 | 180 | ||
79 | if (res >= 0) { | ||
80 | root_swap = res; | ||
81 | return 0; | ||
82 | } | ||
83 | return res; | 181 | return res; |
84 | } | 182 | } |
85 | 183 | ||
@@ -90,36 +188,26 @@ static int swsusp_swap_check(void) /* This is called before saving image */ | |||
90 | * @bio_chain: Link the next write BIO here | 188 | * @bio_chain: Link the next write BIO here |
91 | */ | 189 | */ |
92 | 190 | ||
93 | static int write_page(void *buf, unsigned long offset, struct bio **bio_chain) | 191 | static int write_page(void *buf, sector_t offset, struct bio **bio_chain) |
94 | { | 192 | { |
95 | swp_entry_t entry; | 193 | void *src; |
96 | int error = -ENOSPC; | 194 | |
97 | 195 | if (!offset) | |
98 | if (offset) { | 196 | return -ENOSPC; |
99 | struct page *page = virt_to_page(buf); | 197 | |
100 | 198 | if (bio_chain) { | |
101 | if (bio_chain) { | 199 | src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); |
102 | /* | 200 | if (src) { |
103 | * Whether or not we successfully allocated a copy page, | 201 | memcpy(src, buf, PAGE_SIZE); |
104 | * we take a ref on the page here. It gets undone in | 202 | } else { |
105 | * wait_on_bio_chain(). | 203 | WARN_ON_ONCE(1); |
106 | */ | 204 | bio_chain = NULL; /* Go synchronous */ |
107 | struct page *page_copy; | 205 | src = buf; |
108 | page_copy = alloc_page(GFP_ATOMIC); | ||
109 | if (page_copy == NULL) { | ||
110 | WARN_ON_ONCE(1); | ||
111 | bio_chain = NULL; /* Go synchronous */ | ||
112 | get_page(page); | ||
113 | } else { | ||
114 | memcpy(page_address(page_copy), | ||
115 | page_address(page), PAGE_SIZE); | ||
116 | page = page_copy; | ||
117 | } | ||
118 | } | 206 | } |
119 | entry = swp_entry(root_swap, offset); | 207 | } else { |
120 | error = rw_swap_page_sync(WRITE, entry, page, bio_chain); | 208 | src = buf; |
121 | } | 209 | } |
122 | return error; | 210 | return bio_write_page(offset, src, bio_chain); |
123 | } | 211 | } |
124 | 212 | ||
125 | /* | 213 | /* |
@@ -137,11 +225,11 @@ static int write_page(void *buf, unsigned long offset, struct bio **bio_chain) | |||
137 | * at a time. | 225 | * at a time. |
138 | */ | 226 | */ |
139 | 227 | ||
140 | #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(long) - 1) | 228 | #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) |
141 | 229 | ||
142 | struct swap_map_page { | 230 | struct swap_map_page { |
143 | unsigned long entries[MAP_PAGE_ENTRIES]; | 231 | sector_t entries[MAP_PAGE_ENTRIES]; |
144 | unsigned long next_swap; | 232 | sector_t next_swap; |
145 | }; | 233 | }; |
146 | 234 | ||
147 | /** | 235 | /** |
@@ -151,7 +239,7 @@ struct swap_map_page { | |||
151 | 239 | ||
152 | struct swap_map_handle { | 240 | struct swap_map_handle { |
153 | struct swap_map_page *cur; | 241 | struct swap_map_page *cur; |
154 | unsigned long cur_swap; | 242 | sector_t cur_swap; |
155 | struct bitmap_page *bitmap; | 243 | struct bitmap_page *bitmap; |
156 | unsigned int k; | 244 | unsigned int k; |
157 | }; | 245 | }; |
@@ -166,26 +254,6 @@ static void release_swap_writer(struct swap_map_handle *handle) | |||
166 | handle->bitmap = NULL; | 254 | handle->bitmap = NULL; |
167 | } | 255 | } |
168 | 256 | ||
169 | static void show_speed(struct timeval *start, struct timeval *stop, | ||
170 | unsigned nr_pages, char *msg) | ||
171 | { | ||
172 | s64 elapsed_centisecs64; | ||
173 | int centisecs; | ||
174 | int k; | ||
175 | int kps; | ||
176 | |||
177 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); | ||
178 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); | ||
179 | centisecs = elapsed_centisecs64; | ||
180 | if (centisecs == 0) | ||
181 | centisecs = 1; /* avoid div-by-zero */ | ||
182 | k = nr_pages * (PAGE_SIZE / 1024); | ||
183 | kps = (k * 100) / centisecs; | ||
184 | printk("%s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", msg, k, | ||
185 | centisecs / 100, centisecs % 100, | ||
186 | kps / 1000, (kps % 1000) / 10); | ||
187 | } | ||
188 | |||
189 | static int get_swap_writer(struct swap_map_handle *handle) | 257 | static int get_swap_writer(struct swap_map_handle *handle) |
190 | { | 258 | { |
191 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); | 259 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); |
@@ -196,7 +264,7 @@ static int get_swap_writer(struct swap_map_handle *handle) | |||
196 | release_swap_writer(handle); | 264 | release_swap_writer(handle); |
197 | return -ENOMEM; | 265 | return -ENOMEM; |
198 | } | 266 | } |
199 | handle->cur_swap = alloc_swap_page(root_swap, handle->bitmap); | 267 | handle->cur_swap = alloc_swapdev_block(root_swap, handle->bitmap); |
200 | if (!handle->cur_swap) { | 268 | if (!handle->cur_swap) { |
201 | release_swap_writer(handle); | 269 | release_swap_writer(handle); |
202 | return -ENOSPC; | 270 | return -ENOSPC; |
@@ -205,43 +273,15 @@ static int get_swap_writer(struct swap_map_handle *handle) | |||
205 | return 0; | 273 | return 0; |
206 | } | 274 | } |
207 | 275 | ||
208 | static int wait_on_bio_chain(struct bio **bio_chain) | ||
209 | { | ||
210 | struct bio *bio; | ||
211 | struct bio *next_bio; | ||
212 | int ret = 0; | ||
213 | |||
214 | if (bio_chain == NULL) | ||
215 | return 0; | ||
216 | |||
217 | bio = *bio_chain; | ||
218 | if (bio == NULL) | ||
219 | return 0; | ||
220 | while (bio) { | ||
221 | struct page *page; | ||
222 | |||
223 | next_bio = bio->bi_private; | ||
224 | page = bio->bi_io_vec[0].bv_page; | ||
225 | wait_on_page_locked(page); | ||
226 | if (!PageUptodate(page) || PageError(page)) | ||
227 | ret = -EIO; | ||
228 | put_page(page); | ||
229 | bio_put(bio); | ||
230 | bio = next_bio; | ||
231 | } | ||
232 | *bio_chain = NULL; | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static int swap_write_page(struct swap_map_handle *handle, void *buf, | 276 | static int swap_write_page(struct swap_map_handle *handle, void *buf, |
237 | struct bio **bio_chain) | 277 | struct bio **bio_chain) |
238 | { | 278 | { |
239 | int error = 0; | 279 | int error = 0; |
240 | unsigned long offset; | 280 | sector_t offset; |
241 | 281 | ||
242 | if (!handle->cur) | 282 | if (!handle->cur) |
243 | return -EINVAL; | 283 | return -EINVAL; |
244 | offset = alloc_swap_page(root_swap, handle->bitmap); | 284 | offset = alloc_swapdev_block(root_swap, handle->bitmap); |
245 | error = write_page(buf, offset, bio_chain); | 285 | error = write_page(buf, offset, bio_chain); |
246 | if (error) | 286 | if (error) |
247 | return error; | 287 | return error; |
@@ -250,7 +290,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
250 | error = wait_on_bio_chain(bio_chain); | 290 | error = wait_on_bio_chain(bio_chain); |
251 | if (error) | 291 | if (error) |
252 | goto out; | 292 | goto out; |
253 | offset = alloc_swap_page(root_swap, handle->bitmap); | 293 | offset = alloc_swapdev_block(root_swap, handle->bitmap); |
254 | if (!offset) | 294 | if (!offset) |
255 | return -ENOSPC; | 295 | return -ENOSPC; |
256 | handle->cur->next_swap = offset; | 296 | handle->cur->next_swap = offset; |
@@ -261,7 +301,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
261 | handle->cur_swap = offset; | 301 | handle->cur_swap = offset; |
262 | handle->k = 0; | 302 | handle->k = 0; |
263 | } | 303 | } |
264 | out: | 304 | out: |
265 | return error; | 305 | return error; |
266 | } | 306 | } |
267 | 307 | ||
@@ -315,7 +355,7 @@ static int save_image(struct swap_map_handle *handle, | |||
315 | error = err2; | 355 | error = err2; |
316 | if (!error) | 356 | if (!error) |
317 | printk("\b\b\b\bdone\n"); | 357 | printk("\b\b\b\bdone\n"); |
318 | show_speed(&start, &stop, nr_to_write, "Wrote"); | 358 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); |
319 | return error; | 359 | return error; |
320 | } | 360 | } |
321 | 361 | ||
@@ -350,100 +390,50 @@ int swsusp_write(void) | |||
350 | struct swsusp_info *header; | 390 | struct swsusp_info *header; |
351 | int error; | 391 | int error; |
352 | 392 | ||
353 | if ((error = swsusp_swap_check())) { | 393 | error = swsusp_swap_check(); |
394 | if (error) { | ||
354 | printk(KERN_ERR "swsusp: Cannot find swap device, try " | 395 | printk(KERN_ERR "swsusp: Cannot find swap device, try " |
355 | "swapon -a.\n"); | 396 | "swapon -a.\n"); |
356 | return error; | 397 | return error; |
357 | } | 398 | } |
358 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); | 399 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); |
359 | error = snapshot_read_next(&snapshot, PAGE_SIZE); | 400 | error = snapshot_read_next(&snapshot, PAGE_SIZE); |
360 | if (error < PAGE_SIZE) | 401 | if (error < PAGE_SIZE) { |
361 | return error < 0 ? error : -EFAULT; | 402 | if (error >= 0) |
403 | error = -EFAULT; | ||
404 | |||
405 | goto out; | ||
406 | } | ||
362 | header = (struct swsusp_info *)data_of(snapshot); | 407 | header = (struct swsusp_info *)data_of(snapshot); |
363 | if (!enough_swap(header->pages)) { | 408 | if (!enough_swap(header->pages)) { |
364 | printk(KERN_ERR "swsusp: Not enough free swap\n"); | 409 | printk(KERN_ERR "swsusp: Not enough free swap\n"); |
365 | return -ENOSPC; | 410 | error = -ENOSPC; |
411 | goto out; | ||
366 | } | 412 | } |
367 | error = get_swap_writer(&handle); | 413 | error = get_swap_writer(&handle); |
368 | if (!error) { | 414 | if (!error) { |
369 | unsigned long start = handle.cur_swap; | 415 | sector_t start = handle.cur_swap; |
416 | |||
370 | error = swap_write_page(&handle, header, NULL); | 417 | error = swap_write_page(&handle, header, NULL); |
371 | if (!error) | 418 | if (!error) |
372 | error = save_image(&handle, &snapshot, | 419 | error = save_image(&handle, &snapshot, |
373 | header->pages - 1); | 420 | header->pages - 1); |
421 | |||
374 | if (!error) { | 422 | if (!error) { |
375 | flush_swap_writer(&handle); | 423 | flush_swap_writer(&handle); |
376 | printk("S"); | 424 | printk("S"); |
377 | error = mark_swapfiles(swp_entry(root_swap, start)); | 425 | error = mark_swapfiles(start); |
378 | printk("|\n"); | 426 | printk("|\n"); |
379 | } | 427 | } |
380 | } | 428 | } |
381 | if (error) | 429 | if (error) |
382 | free_all_swap_pages(root_swap, handle.bitmap); | 430 | free_all_swap_pages(root_swap, handle.bitmap); |
383 | release_swap_writer(&handle); | 431 | release_swap_writer(&handle); |
432 | out: | ||
433 | swsusp_close(); | ||
384 | return error; | 434 | return error; |
385 | } | 435 | } |
386 | 436 | ||
387 | static struct block_device *resume_bdev; | ||
388 | |||
389 | /** | ||
390 | * submit - submit BIO request. | ||
391 | * @rw: READ or WRITE. | ||
392 | * @off physical offset of page. | ||
393 | * @page: page we're reading or writing. | ||
394 | * @bio_chain: list of pending biod (for async reading) | ||
395 | * | ||
396 | * Straight from the textbook - allocate and initialize the bio. | ||
397 | * If we're reading, make sure the page is marked as dirty. | ||
398 | * Then submit it and, if @bio_chain == NULL, wait. | ||
399 | */ | ||
400 | static int submit(int rw, pgoff_t page_off, struct page *page, | ||
401 | struct bio **bio_chain) | ||
402 | { | ||
403 | struct bio *bio; | ||
404 | |||
405 | bio = bio_alloc(GFP_ATOMIC, 1); | ||
406 | if (!bio) | ||
407 | return -ENOMEM; | ||
408 | bio->bi_sector = page_off * (PAGE_SIZE >> 9); | ||
409 | bio->bi_bdev = resume_bdev; | ||
410 | bio->bi_end_io = end_swap_bio_read; | ||
411 | |||
412 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | ||
413 | printk("swsusp: ERROR: adding page to bio at %ld\n", page_off); | ||
414 | bio_put(bio); | ||
415 | return -EFAULT; | ||
416 | } | ||
417 | |||
418 | lock_page(page); | ||
419 | bio_get(bio); | ||
420 | |||
421 | if (bio_chain == NULL) { | ||
422 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
423 | wait_on_page_locked(page); | ||
424 | if (rw == READ) | ||
425 | bio_set_pages_dirty(bio); | ||
426 | bio_put(bio); | ||
427 | } else { | ||
428 | if (rw == READ) | ||
429 | get_page(page); /* These pages are freed later */ | ||
430 | bio->bi_private = *bio_chain; | ||
431 | *bio_chain = bio; | ||
432 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
433 | } | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
438 | { | ||
439 | return submit(READ, page_off, virt_to_page(addr), bio_chain); | ||
440 | } | ||
441 | |||
442 | static int bio_write_page(pgoff_t page_off, void *addr) | ||
443 | { | ||
444 | return submit(WRITE, page_off, virt_to_page(addr), NULL); | ||
445 | } | ||
446 | |||
447 | /** | 437 | /** |
448 | * The following functions allow us to read data using a swap map | 438 | * The following functions allow us to read data using a swap map |
449 | * in a file-alike way | 439 | * in a file-alike way |
@@ -456,17 +446,18 @@ static void release_swap_reader(struct swap_map_handle *handle) | |||
456 | handle->cur = NULL; | 446 | handle->cur = NULL; |
457 | } | 447 | } |
458 | 448 | ||
459 | static int get_swap_reader(struct swap_map_handle *handle, | 449 | static int get_swap_reader(struct swap_map_handle *handle, sector_t start) |
460 | swp_entry_t start) | ||
461 | { | 450 | { |
462 | int error; | 451 | int error; |
463 | 452 | ||
464 | if (!swp_offset(start)) | 453 | if (!start) |
465 | return -EINVAL; | 454 | return -EINVAL; |
466 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); | 455 | |
456 | handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH); | ||
467 | if (!handle->cur) | 457 | if (!handle->cur) |
468 | return -ENOMEM; | 458 | return -ENOMEM; |
469 | error = bio_read_page(swp_offset(start), handle->cur, NULL); | 459 | |
460 | error = bio_read_page(start, handle->cur, NULL); | ||
470 | if (error) { | 461 | if (error) { |
471 | release_swap_reader(handle); | 462 | release_swap_reader(handle); |
472 | return error; | 463 | return error; |
@@ -478,7 +469,7 @@ static int get_swap_reader(struct swap_map_handle *handle, | |||
478 | static int swap_read_page(struct swap_map_handle *handle, void *buf, | 469 | static int swap_read_page(struct swap_map_handle *handle, void *buf, |
479 | struct bio **bio_chain) | 470 | struct bio **bio_chain) |
480 | { | 471 | { |
481 | unsigned long offset; | 472 | sector_t offset; |
482 | int error; | 473 | int error; |
483 | 474 | ||
484 | if (!handle->cur) | 475 | if (!handle->cur) |
@@ -547,11 +538,11 @@ static int load_image(struct swap_map_handle *handle, | |||
547 | error = err2; | 538 | error = err2; |
548 | if (!error) { | 539 | if (!error) { |
549 | printk("\b\b\b\bdone\n"); | 540 | printk("\b\b\b\bdone\n"); |
550 | snapshot_free_unused_memory(snapshot); | 541 | snapshot_write_finalize(snapshot); |
551 | if (!snapshot_image_loaded(snapshot)) | 542 | if (!snapshot_image_loaded(snapshot)) |
552 | error = -ENODATA; | 543 | error = -ENODATA; |
553 | } | 544 | } |
554 | show_speed(&start, &stop, nr_to_read, "Read"); | 545 | swsusp_show_speed(&start, &stop, nr_to_read, "Read"); |
555 | return error; | 546 | return error; |
556 | } | 547 | } |
557 | 548 | ||
@@ -600,12 +591,16 @@ int swsusp_check(void) | |||
600 | if (!IS_ERR(resume_bdev)) { | 591 | if (!IS_ERR(resume_bdev)) { |
601 | set_blocksize(resume_bdev, PAGE_SIZE); | 592 | set_blocksize(resume_bdev, PAGE_SIZE); |
602 | memset(&swsusp_header, 0, sizeof(swsusp_header)); | 593 | memset(&swsusp_header, 0, sizeof(swsusp_header)); |
603 | if ((error = bio_read_page(0, &swsusp_header, NULL))) | 594 | error = bio_read_page(swsusp_resume_block, |
595 | &swsusp_header, NULL); | ||
596 | if (error) | ||
604 | return error; | 597 | return error; |
598 | |||
605 | if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { | 599 | if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { |
606 | memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); | 600 | memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); |
607 | /* Reset swap signature now */ | 601 | /* Reset swap signature now */ |
608 | error = bio_write_page(0, &swsusp_header); | 602 | error = bio_write_page(swsusp_resume_block, |
603 | &swsusp_header, NULL); | ||
609 | } else { | 604 | } else { |
610 | return -EINVAL; | 605 | return -EINVAL; |
611 | } | 606 | } |
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 0b66659dc516..31aa0390c777 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/bootmem.h> | 49 | #include <linux/bootmem.h> |
50 | #include <linux/syscalls.h> | 50 | #include <linux/syscalls.h> |
51 | #include <linux/highmem.h> | 51 | #include <linux/highmem.h> |
52 | #include <linux/time.h> | ||
52 | 53 | ||
53 | #include "power.h" | 54 | #include "power.h" |
54 | 55 | ||
@@ -64,10 +65,8 @@ int in_suspend __nosavedata = 0; | |||
64 | 65 | ||
65 | #ifdef CONFIG_HIGHMEM | 66 | #ifdef CONFIG_HIGHMEM |
66 | unsigned int count_highmem_pages(void); | 67 | unsigned int count_highmem_pages(void); |
67 | int save_highmem(void); | ||
68 | int restore_highmem(void); | 68 | int restore_highmem(void); |
69 | #else | 69 | #else |
70 | static inline int save_highmem(void) { return 0; } | ||
71 | static inline int restore_highmem(void) { return 0; } | 70 | static inline int restore_highmem(void) { return 0; } |
72 | static inline unsigned int count_highmem_pages(void) { return 0; } | 71 | static inline unsigned int count_highmem_pages(void) { return 0; } |
73 | #endif | 72 | #endif |
@@ -134,18 +133,18 @@ static int bitmap_set(struct bitmap_page *bitmap, unsigned long bit) | |||
134 | return 0; | 133 | return 0; |
135 | } | 134 | } |
136 | 135 | ||
137 | unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap) | 136 | sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap) |
138 | { | 137 | { |
139 | unsigned long offset; | 138 | unsigned long offset; |
140 | 139 | ||
141 | offset = swp_offset(get_swap_page_of_type(swap)); | 140 | offset = swp_offset(get_swap_page_of_type(swap)); |
142 | if (offset) { | 141 | if (offset) { |
143 | if (bitmap_set(bitmap, offset)) { | 142 | if (bitmap_set(bitmap, offset)) |
144 | swap_free(swp_entry(swap, offset)); | 143 | swap_free(swp_entry(swap, offset)); |
145 | offset = 0; | 144 | else |
146 | } | 145 | return swapdev_block(swap, offset); |
147 | } | 146 | } |
148 | return offset; | 147 | return 0; |
149 | } | 148 | } |
150 | 149 | ||
151 | void free_all_swap_pages(int swap, struct bitmap_page *bitmap) | 150 | void free_all_swap_pages(int swap, struct bitmap_page *bitmap) |
@@ -166,6 +165,34 @@ void free_all_swap_pages(int swap, struct bitmap_page *bitmap) | |||
166 | } | 165 | } |
167 | 166 | ||
168 | /** | 167 | /** |
168 | * swsusp_show_speed - print the time elapsed between two events represented by | ||
169 | * @start and @stop | ||
170 | * | ||
171 | * @nr_pages - number of pages processed between @start and @stop | ||
172 | * @msg - introductory message to print | ||
173 | */ | ||
174 | |||
175 | void swsusp_show_speed(struct timeval *start, struct timeval *stop, | ||
176 | unsigned nr_pages, char *msg) | ||
177 | { | ||
178 | s64 elapsed_centisecs64; | ||
179 | int centisecs; | ||
180 | int k; | ||
181 | int kps; | ||
182 | |||
183 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); | ||
184 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); | ||
185 | centisecs = elapsed_centisecs64; | ||
186 | if (centisecs == 0) | ||
187 | centisecs = 1; /* avoid div-by-zero */ | ||
188 | k = nr_pages * (PAGE_SIZE / 1024); | ||
189 | kps = (k * 100) / centisecs; | ||
190 | printk("%s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", msg, k, | ||
191 | centisecs / 100, centisecs % 100, | ||
192 | kps / 1000, (kps % 1000) / 10); | ||
193 | } | ||
194 | |||
195 | /** | ||
169 | * swsusp_shrink_memory - Try to free as much memory as needed | 196 | * swsusp_shrink_memory - Try to free as much memory as needed |
170 | * | 197 | * |
171 | * ... but do not OOM-kill anyone | 198 | * ... but do not OOM-kill anyone |
@@ -184,23 +211,37 @@ static inline unsigned long __shrink_memory(long tmp) | |||
184 | 211 | ||
185 | int swsusp_shrink_memory(void) | 212 | int swsusp_shrink_memory(void) |
186 | { | 213 | { |
187 | long size, tmp; | 214 | long tmp; |
188 | struct zone *zone; | 215 | struct zone *zone; |
189 | unsigned long pages = 0; | 216 | unsigned long pages = 0; |
190 | unsigned int i = 0; | 217 | unsigned int i = 0; |
191 | char *p = "-\\|/"; | 218 | char *p = "-\\|/"; |
219 | struct timeval start, stop; | ||
192 | 220 | ||
193 | printk("Shrinking memory... "); | 221 | printk("Shrinking memory... "); |
222 | do_gettimeofday(&start); | ||
194 | do { | 223 | do { |
195 | size = 2 * count_highmem_pages(); | 224 | long size, highmem_size; |
196 | size += size / 50 + count_data_pages() + PAGES_FOR_IO; | 225 | |
226 | highmem_size = count_highmem_pages(); | ||
227 | size = count_data_pages() + PAGES_FOR_IO; | ||
197 | tmp = size; | 228 | tmp = size; |
229 | size += highmem_size; | ||
198 | for_each_zone (zone) | 230 | for_each_zone (zone) |
199 | if (!is_highmem(zone) && populated_zone(zone)) { | 231 | if (populated_zone(zone)) { |
200 | tmp -= zone->free_pages; | 232 | if (is_highmem(zone)) { |
201 | tmp += zone->lowmem_reserve[ZONE_NORMAL]; | 233 | highmem_size -= zone->free_pages; |
202 | tmp += snapshot_additional_pages(zone); | 234 | } else { |
235 | tmp -= zone->free_pages; | ||
236 | tmp += zone->lowmem_reserve[ZONE_NORMAL]; | ||
237 | tmp += snapshot_additional_pages(zone); | ||
238 | } | ||
203 | } | 239 | } |
240 | |||
241 | if (highmem_size < 0) | ||
242 | highmem_size = 0; | ||
243 | |||
244 | tmp += highmem_size; | ||
204 | if (tmp > 0) { | 245 | if (tmp > 0) { |
205 | tmp = __shrink_memory(tmp); | 246 | tmp = __shrink_memory(tmp); |
206 | if (!tmp) | 247 | if (!tmp) |
@@ -212,7 +253,9 @@ int swsusp_shrink_memory(void) | |||
212 | } | 253 | } |
213 | printk("\b%c", p[i++%4]); | 254 | printk("\b%c", p[i++%4]); |
214 | } while (tmp > 0); | 255 | } while (tmp > 0); |
256 | do_gettimeofday(&stop); | ||
215 | printk("\bdone (%lu pages freed)\n", pages); | 257 | printk("\bdone (%lu pages freed)\n", pages); |
258 | swsusp_show_speed(&start, &stop, pages, "Freed"); | ||
216 | 259 | ||
217 | return 0; | 260 | return 0; |
218 | } | 261 | } |
@@ -223,6 +266,7 @@ int swsusp_suspend(void) | |||
223 | 266 | ||
224 | if ((error = arch_prepare_suspend())) | 267 | if ((error = arch_prepare_suspend())) |
225 | return error; | 268 | return error; |
269 | |||
226 | local_irq_disable(); | 270 | local_irq_disable(); |
227 | /* At this point, device_suspend() has been called, but *not* | 271 | /* At this point, device_suspend() has been called, but *not* |
228 | * device_power_down(). We *must* device_power_down() now. | 272 | * device_power_down(). We *must* device_power_down() now. |
@@ -235,23 +279,16 @@ int swsusp_suspend(void) | |||
235 | goto Enable_irqs; | 279 | goto Enable_irqs; |
236 | } | 280 | } |
237 | 281 | ||
238 | if ((error = save_highmem())) { | ||
239 | printk(KERN_ERR "swsusp: Not enough free pages for highmem\n"); | ||
240 | goto Restore_highmem; | ||
241 | } | ||
242 | |||
243 | save_processor_state(); | 282 | save_processor_state(); |
244 | if ((error = swsusp_arch_suspend())) | 283 | if ((error = swsusp_arch_suspend())) |
245 | printk(KERN_ERR "Error %d suspending\n", error); | 284 | printk(KERN_ERR "Error %d suspending\n", error); |
246 | /* Restore control flow magically appears here */ | 285 | /* Restore control flow magically appears here */ |
247 | restore_processor_state(); | 286 | restore_processor_state(); |
248 | Restore_highmem: | ||
249 | restore_highmem(); | ||
250 | /* NOTE: device_power_up() is just a resume() for devices | 287 | /* NOTE: device_power_up() is just a resume() for devices |
251 | * that suspended with irqs off ... no overall powerup. | 288 | * that suspended with irqs off ... no overall powerup. |
252 | */ | 289 | */ |
253 | device_power_up(); | 290 | device_power_up(); |
254 | Enable_irqs: | 291 | Enable_irqs: |
255 | local_irq_enable(); | 292 | local_irq_enable(); |
256 | return error; | 293 | return error; |
257 | } | 294 | } |
@@ -268,18 +305,23 @@ int swsusp_resume(void) | |||
268 | printk(KERN_ERR "Some devices failed to power down, very bad\n"); | 305 | printk(KERN_ERR "Some devices failed to power down, very bad\n"); |
269 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | 306 | /* We'll ignore saved state, but this gets preempt count (etc) right */ |
270 | save_processor_state(); | 307 | save_processor_state(); |
271 | error = swsusp_arch_resume(); | 308 | error = restore_highmem(); |
272 | /* Code below is only ever reached in case of failure. Otherwise | 309 | if (!error) { |
273 | * execution continues at place where swsusp_arch_suspend was called | 310 | error = swsusp_arch_resume(); |
274 | */ | 311 | /* The code below is only ever reached in case of a failure. |
275 | BUG_ON(!error); | 312 | * Otherwise execution continues at place where |
313 | * swsusp_arch_suspend() was called | ||
314 | */ | ||
315 | BUG_ON(!error); | ||
316 | /* This call to restore_highmem() undos the previous one */ | ||
317 | restore_highmem(); | ||
318 | } | ||
276 | /* The only reason why swsusp_arch_resume() can fail is memory being | 319 | /* The only reason why swsusp_arch_resume() can fail is memory being |
277 | * very tight, so we have to free it as soon as we can to avoid | 320 | * very tight, so we have to free it as soon as we can to avoid |
278 | * subsequent failures | 321 | * subsequent failures |
279 | */ | 322 | */ |
280 | swsusp_free(); | 323 | swsusp_free(); |
281 | restore_processor_state(); | 324 | restore_processor_state(); |
282 | restore_highmem(); | ||
283 | touch_softlockup_watchdog(); | 325 | touch_softlockup_watchdog(); |
284 | device_power_up(); | 326 | device_power_up(); |
285 | local_irq_enable(); | 327 | local_irq_enable(); |
diff --git a/kernel/power/user.c b/kernel/power/user.c index d991d3b0e5a4..89443b85163b 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/suspend.h> | 12 | #include <linux/suspend.h> |
13 | #include <linux/syscalls.h> | 13 | #include <linux/syscalls.h> |
14 | #include <linux/reboot.h> | ||
14 | #include <linux/string.h> | 15 | #include <linux/string.h> |
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
16 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
@@ -21,6 +22,7 @@ | |||
21 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
22 | #include <linux/console.h> | 23 | #include <linux/console.h> |
23 | #include <linux/cpu.h> | 24 | #include <linux/cpu.h> |
25 | #include <linux/freezer.h> | ||
24 | 26 | ||
25 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
26 | 28 | ||
@@ -54,7 +56,8 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
54 | filp->private_data = data; | 56 | filp->private_data = data; |
55 | memset(&data->handle, 0, sizeof(struct snapshot_handle)); | 57 | memset(&data->handle, 0, sizeof(struct snapshot_handle)); |
56 | if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { | 58 | if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { |
57 | data->swap = swsusp_resume_device ? swap_type_of(swsusp_resume_device) : -1; | 59 | data->swap = swsusp_resume_device ? |
60 | swap_type_of(swsusp_resume_device, 0) : -1; | ||
58 | data->mode = O_RDONLY; | 61 | data->mode = O_RDONLY; |
59 | } else { | 62 | } else { |
60 | data->swap = -1; | 63 | data->swap = -1; |
@@ -76,10 +79,10 @@ static int snapshot_release(struct inode *inode, struct file *filp) | |||
76 | free_all_swap_pages(data->swap, data->bitmap); | 79 | free_all_swap_pages(data->swap, data->bitmap); |
77 | free_bitmap(data->bitmap); | 80 | free_bitmap(data->bitmap); |
78 | if (data->frozen) { | 81 | if (data->frozen) { |
79 | down(&pm_sem); | 82 | mutex_lock(&pm_mutex); |
80 | thaw_processes(); | 83 | thaw_processes(); |
81 | enable_nonboot_cpus(); | 84 | enable_nonboot_cpus(); |
82 | up(&pm_sem); | 85 | mutex_unlock(&pm_mutex); |
83 | } | 86 | } |
84 | atomic_inc(&device_available); | 87 | atomic_inc(&device_available); |
85 | return 0; | 88 | return 0; |
@@ -124,7 +127,8 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
124 | { | 127 | { |
125 | int error = 0; | 128 | int error = 0; |
126 | struct snapshot_data *data; | 129 | struct snapshot_data *data; |
127 | loff_t offset, avail; | 130 | loff_t avail; |
131 | sector_t offset; | ||
128 | 132 | ||
129 | if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) | 133 | if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) |
130 | return -ENOTTY; | 134 | return -ENOTTY; |
@@ -140,7 +144,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
140 | case SNAPSHOT_FREEZE: | 144 | case SNAPSHOT_FREEZE: |
141 | if (data->frozen) | 145 | if (data->frozen) |
142 | break; | 146 | break; |
143 | down(&pm_sem); | 147 | mutex_lock(&pm_mutex); |
144 | error = disable_nonboot_cpus(); | 148 | error = disable_nonboot_cpus(); |
145 | if (!error) { | 149 | if (!error) { |
146 | error = freeze_processes(); | 150 | error = freeze_processes(); |
@@ -150,7 +154,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
150 | error = -EBUSY; | 154 | error = -EBUSY; |
151 | } | 155 | } |
152 | } | 156 | } |
153 | up(&pm_sem); | 157 | mutex_unlock(&pm_mutex); |
154 | if (!error) | 158 | if (!error) |
155 | data->frozen = 1; | 159 | data->frozen = 1; |
156 | break; | 160 | break; |
@@ -158,10 +162,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
158 | case SNAPSHOT_UNFREEZE: | 162 | case SNAPSHOT_UNFREEZE: |
159 | if (!data->frozen) | 163 | if (!data->frozen) |
160 | break; | 164 | break; |
161 | down(&pm_sem); | 165 | mutex_lock(&pm_mutex); |
162 | thaw_processes(); | 166 | thaw_processes(); |
163 | enable_nonboot_cpus(); | 167 | enable_nonboot_cpus(); |
164 | up(&pm_sem); | 168 | mutex_unlock(&pm_mutex); |
165 | data->frozen = 0; | 169 | data->frozen = 0; |
166 | break; | 170 | break; |
167 | 171 | ||
@@ -170,7 +174,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
170 | error = -EPERM; | 174 | error = -EPERM; |
171 | break; | 175 | break; |
172 | } | 176 | } |
173 | down(&pm_sem); | 177 | mutex_lock(&pm_mutex); |
174 | /* Free memory before shutting down devices. */ | 178 | /* Free memory before shutting down devices. */ |
175 | error = swsusp_shrink_memory(); | 179 | error = swsusp_shrink_memory(); |
176 | if (!error) { | 180 | if (!error) { |
@@ -183,7 +187,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
183 | } | 187 | } |
184 | resume_console(); | 188 | resume_console(); |
185 | } | 189 | } |
186 | up(&pm_sem); | 190 | mutex_unlock(&pm_mutex); |
187 | if (!error) | 191 | if (!error) |
188 | error = put_user(in_suspend, (unsigned int __user *)arg); | 192 | error = put_user(in_suspend, (unsigned int __user *)arg); |
189 | if (!error) | 193 | if (!error) |
@@ -191,13 +195,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
191 | break; | 195 | break; |
192 | 196 | ||
193 | case SNAPSHOT_ATOMIC_RESTORE: | 197 | case SNAPSHOT_ATOMIC_RESTORE: |
198 | snapshot_write_finalize(&data->handle); | ||
194 | if (data->mode != O_WRONLY || !data->frozen || | 199 | if (data->mode != O_WRONLY || !data->frozen || |
195 | !snapshot_image_loaded(&data->handle)) { | 200 | !snapshot_image_loaded(&data->handle)) { |
196 | error = -EPERM; | 201 | error = -EPERM; |
197 | break; | 202 | break; |
198 | } | 203 | } |
199 | snapshot_free_unused_memory(&data->handle); | 204 | mutex_lock(&pm_mutex); |
200 | down(&pm_sem); | ||
201 | pm_prepare_console(); | 205 | pm_prepare_console(); |
202 | suspend_console(); | 206 | suspend_console(); |
203 | error = device_suspend(PMSG_PRETHAW); | 207 | error = device_suspend(PMSG_PRETHAW); |
@@ -207,7 +211,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
207 | } | 211 | } |
208 | resume_console(); | 212 | resume_console(); |
209 | pm_restore_console(); | 213 | pm_restore_console(); |
210 | up(&pm_sem); | 214 | mutex_unlock(&pm_mutex); |
211 | break; | 215 | break; |
212 | 216 | ||
213 | case SNAPSHOT_FREE: | 217 | case SNAPSHOT_FREE: |
@@ -238,10 +242,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
238 | break; | 242 | break; |
239 | } | 243 | } |
240 | } | 244 | } |
241 | offset = alloc_swap_page(data->swap, data->bitmap); | 245 | offset = alloc_swapdev_block(data->swap, data->bitmap); |
242 | if (offset) { | 246 | if (offset) { |
243 | offset <<= PAGE_SHIFT; | 247 | offset <<= PAGE_SHIFT; |
244 | error = put_user(offset, (loff_t __user *)arg); | 248 | error = put_user(offset, (sector_t __user *)arg); |
245 | } else { | 249 | } else { |
246 | error = -ENOSPC; | 250 | error = -ENOSPC; |
247 | } | 251 | } |
@@ -264,7 +268,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
264 | * so we need to recode them | 268 | * so we need to recode them |
265 | */ | 269 | */ |
266 | if (old_decode_dev(arg)) { | 270 | if (old_decode_dev(arg)) { |
267 | data->swap = swap_type_of(old_decode_dev(arg)); | 271 | data->swap = swap_type_of(old_decode_dev(arg), 0); |
268 | if (data->swap < 0) | 272 | if (data->swap < 0) |
269 | error = -ENODEV; | 273 | error = -ENODEV; |
270 | } else { | 274 | } else { |
@@ -282,7 +286,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
282 | break; | 286 | break; |
283 | } | 287 | } |
284 | 288 | ||
285 | if (down_trylock(&pm_sem)) { | 289 | if (!mutex_trylock(&pm_mutex)) { |
286 | error = -EBUSY; | 290 | error = -EBUSY; |
287 | break; | 291 | break; |
288 | } | 292 | } |
@@ -309,8 +313,66 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
309 | if (pm_ops->finish) | 313 | if (pm_ops->finish) |
310 | pm_ops->finish(PM_SUSPEND_MEM); | 314 | pm_ops->finish(PM_SUSPEND_MEM); |
311 | 315 | ||
312 | OutS3: | 316 | OutS3: |
313 | up(&pm_sem); | 317 | mutex_unlock(&pm_mutex); |
318 | break; | ||
319 | |||
320 | case SNAPSHOT_PMOPS: | ||
321 | switch (arg) { | ||
322 | |||
323 | case PMOPS_PREPARE: | ||
324 | if (pm_ops->prepare) { | ||
325 | error = pm_ops->prepare(PM_SUSPEND_DISK); | ||
326 | } | ||
327 | break; | ||
328 | |||
329 | case PMOPS_ENTER: | ||
330 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); | ||
331 | error = pm_ops->enter(PM_SUSPEND_DISK); | ||
332 | break; | ||
333 | |||
334 | case PMOPS_FINISH: | ||
335 | if (pm_ops && pm_ops->finish) { | ||
336 | pm_ops->finish(PM_SUSPEND_DISK); | ||
337 | } | ||
338 | break; | ||
339 | |||
340 | default: | ||
341 | printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg); | ||
342 | error = -EINVAL; | ||
343 | |||
344 | } | ||
345 | break; | ||
346 | |||
347 | case SNAPSHOT_SET_SWAP_AREA: | ||
348 | if (data->bitmap) { | ||
349 | error = -EPERM; | ||
350 | } else { | ||
351 | struct resume_swap_area swap_area; | ||
352 | dev_t swdev; | ||
353 | |||
354 | error = copy_from_user(&swap_area, (void __user *)arg, | ||
355 | sizeof(struct resume_swap_area)); | ||
356 | if (error) { | ||
357 | error = -EFAULT; | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * User space encodes device types as two-byte values, | ||
363 | * so we need to recode them | ||
364 | */ | ||
365 | swdev = old_decode_dev(swap_area.dev); | ||
366 | if (swdev) { | ||
367 | offset = swap_area.offset; | ||
368 | data->swap = swap_type_of(swdev, offset); | ||
369 | if (data->swap < 0) | ||
370 | error = -ENODEV; | ||
371 | } else { | ||
372 | data->swap = -1; | ||
373 | error = -EINVAL; | ||
374 | } | ||
375 | } | ||
314 | break; | 376 | break; |
315 | 377 | ||
316 | default: | 378 | default: |
@@ -321,7 +383,7 @@ OutS3: | |||
321 | return error; | 383 | return error; |
322 | } | 384 | } |
323 | 385 | ||
324 | static struct file_operations snapshot_fops = { | 386 | static const struct file_operations snapshot_fops = { |
325 | .open = snapshot_open, | 387 | .open = snapshot_open, |
326 | .release = snapshot_release, | 388 | .release = snapshot_release, |
327 | .read = snapshot_read, | 389 | .read = snapshot_read, |