]> git.pld-linux.org Git - packages/kernel.git/blame - suspend2-2.2.9-for-2.6.19-rc6.patch
- try to fix ppc builds for external modules (untested yet)
[packages/kernel.git] / suspend2-2.2.9-for-2.6.19-rc6.patch
CommitLineData
ce6c723b 1diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
2index 6747384..0be48f2 100644
3--- a/Documentation/kernel-parameters.txt
4+++ b/Documentation/kernel-parameters.txt
5@@ -80,6 +80,7 @@ parameter is applicable:
6 SERIAL Serial support is enabled.
7 SMP The kernel is an SMP kernel.
8 SPARC Sparc architecture is enabled.
9+ SUSPEND2 Suspend2 is enabled.
10 SWSUSP Software suspend is enabled.
11 TS Appropriate touchscreen support is enabled.
12 USB USB support is enabled.
13@@ -1079,6 +1080,8 @@ and is between 256 and 4096 characters.
14 noresume [SWSUSP] Disables resume and restores original swap
15 space.
16
17+ noresume2 [SUSPEND2] Disables resuming and restores original swap signature.
18+
19 no-scroll [VGA] Disables scrollback.
20 This is required for the Braillex ib80-piezo Braille
21 reader made by F.H. Papenmeier (Germany).
22@@ -1369,6 +1372,11 @@ and is between 256 and 4096 characters.
23 resume= [SWSUSP]
24 Specify the partition device for software suspend
25
26+ resume2= [SUSPEND2] Specify the storage device for Suspend2.
27+ Format: <writer>:<writer-parameters>.
28+ See Documentation/power/suspend2.txt for details of the
29+ formats for available image writers.
30+
31 rhash_entries= [KNL,NET]
32 Set number of hash buckets for route cache
33
34diff --git a/Documentation/power/Suspend2-Changelog.txt b/Documentation/power/Suspend2-Changelog.txt
35new file mode 100644
36index 0000000..99f8199
37--- /dev/null
38+++ b/Documentation/power/Suspend2-Changelog.txt
39@@ -0,0 +1,870 @@
40+Suspend2 changelog.
41+
42+2.2.9 - 24 November 2006
43+
44+- Remove bdev freezing - XFS users, proceed with caution!
45+ I'm told this shouldn't be needed any more as XFS threads are now behaving
46+ properly. Let's see.
47+- Remove dependancy on CONFIG_PM_DEBUG (All debugging code available always).
48+- Don't wait for a keypress if aborting because pageset1 waits too much.
49+ We're in the midst of an atomic copy, so can't interact with the user.
50+- Related to the previous one, add a new bit in the result code to say that
51+ the extra pages allowance was too small.
52+- Restore freezing of processes prior to atomic copy at resume time. When did
53+ it go missing? (Haven't looked).
54+- Add support for aborting if pages need resaving.
55+- Don't clear the encryption key and iv when loading plugin configs if they
56+ weren't saved in the image.
57+- Mark only readonly process pages as pageset2 by default. The old behaviour
58+ of marking all process pages as pageset2 (thereby letting you save a large
59+ image) can be reenabled by:
60+ procsetting full_pageset2 1
61+ or
62+ echo 1 > /sys/power/suspend2/full_pageset2
63+ I think that most people might want this to be the default, but I'll see.
64+ Not doing it is theoretically safer, at least until I identify the cause
65+ of the few cases that have appeared so far where pageset2 pages do change.
66+
67+2.2.8.5 - 14 November 2006
68+
69+- Rework LRU page un/relinking code.
70+- Add cryptoapi based hashing for verification that Pageset2 doesn't
71+ change while being written. Off by default. To enable:
72+ echo 1 > /sys/power/suspend2/checksum/enabled
73+ This calculates MD5 checksums for all pageset2 pages prior to starting
74+ to save the image and again prior to the atomic copy. If any pages have
75+ changed, they will be resaved in the atomic copy, and the original version
76+ discarded when the image is reloaded. If checksumming is enabled, the
77+ debug info will contain:
78+ - Checksum method is 'md5'.
79+ 0 pages resaved in atomic copy.
80+ If the number is non-zero, please contact me - I will be interested to
81+ see if we can track down which pages change and why.
82+
83+2.2.8.4 - 8 November 2006
84+
85+- Update documentation some more.
86+- Completion of renaming 'writers' to 'allocators'.
87+
88+2.2.8.3 - 7 November 2006
89+
90+- Freezer.h instead of suspend.h/sched.h used for freezing functions.
91+- Select CRYPTO_ALGAPI when LZF chosen.
92+- Modifications to freezer.
93+- Rename swap and file 'writers' to 'allocators'.
94+- Add Redhat copyrights.
95+- Cleanup some unused declarations in compression.c.
96+- Call read_header_cleanup functions in __read_pageset1 error pages.
97+- Fix accounting for number of highmem pages needed.
98+- Use swsusp saveable() function.
99+- Use drop_pagecache() function for image_size_limit=-2.
100+- Make 'Initiating a software suspend cycle' KERN_INFO level.
101+- Remove buffer_alloc|free paranoia code.
102+- If open_bdev (swap allocator), don't treat device as a string and
103+ only display error when we're not going to in the caller.
104+- Use DIV_ROUND_UP in dyn_pageflags code.
105+- Use kzalloc instead of kmalloc in dyn_pageflags code.
106+- printk error if allocating memory for dynamic pageflags fails.
107+
108+2.2.8.2 - 12 October 2006
109+
110+- Update internals document and rename to suspend2-internals.txt.
111+- Remove device and suspend2 beeping code.
112+- Fix compilation issues with !CONFIG_NET.
113+- Lots of whitespace cleanups & removal of spurious comments.
114+- Remove some now unused members in extent struct and unused variables.
115+- Rename struct pagedir pageset_size member to size.
116+- Make unsigned longs used in image preparation into ints.
117+- Cleanups in unused/unnecessary return values and procedures with just one
118+ caller.
119+- Rework [de]registering modules.
120+- Use DIV_ROUND_UP macro.
121+- Revert power_off changes.
122+
123+2.2.8.1 - 5 October 2006
124+
125+- Try to make freezing more reliable under load by doing
126+ sys_sync after signalling userspace threads the first time,
127+ and start the timeout from the completion of the sys_sync.
128+- Handle the return value from sysfs_create_file.
129+- Reset compression stats on any action so they don't cause
130+ confusion in debugging.
131+- Poweroff improvements, I hope!
132+- Block i/o cleanups - 200 lines less, no problems seen so far!
133+- Fix a compilation warning when swsusp and suspend2 are both disabled.
134+- Work toward completion of Documentation/power/internals.
135+- Correct complain when an initrd lacks echo > do_resume (s/proc/sysfs)
136+
137+2.2.8 - 20 September 2006
138+
139+- Add Changelog as Documentation/power/Suspend2-Changelog.txt
140+- Don't replace swsusp completely when the do-it-by-default option is on.
141+
142+2.2.7.6 - 15 September 2006
143+
144+- Let swsusp work. The readding of BUG_ON(non suspend2 io) test
145+ wasn't targetted enough.
146+- Fix the swsusp replacement code to work with initramfses.
147+- Explicitly case the sizeof(struct suspend_header) as int. One case
148+ reported where the lack of a cast seems to have caused huge header
149+ size values.
150+- Make the suspend_file routine parse_signature static.
151+- Fix handling of swapwriter code so that the filewriter can still work
152+ with the new swsusp replacement functionality.
153+
154+2.2.7.5 - 5 September 2006
155+
156+- Documentation updates
157+- Add support for beeping at signficant lowlevel suspending points,
158+ to help in diagnosing resume failures.
159+ suspend_beep=1 on commandline to activate.
160+- Add support for beeping while invoking driver suspend and resume
161+ routines, to help in diagnosing resume failures.
162+ Boot with device_beep=1 to activate.
163+- Add a timer_resume fix that I'm hoping to see John Stultz submit
164+ upstream.
165+- Readd BUG_ON(non suspend2 io during suspend) in response to a
166+ recent corruption report.
167+- Remove deflate fix. We were the only ones needing it, and I don't
168+ recommend the use of glacially slow compression anyway.
169+- Remove PPC SOFTWARE_REPLACE_SLEEP configuration option.
170+- Better typing of pageflags variables.
171+- Use max_pfn rather than -1 to indicate the start/end of a scan.
172+- Remove LRU paranoia. No reports of it being hit.
173+- Consolidate Suspend2 specific kernel/power/*.h.
174+- Unlink LRU pages instead of avoiding vmscanning during suspend.
175+- Make Suspend2 a drop-in replacement for swsusp (compile time
176+ option). This doesn't stop swsusp from working. Instead it lets you
177+ * use resume= instead of resume2= (resume= takes precedence if set)
178+ * use noresume instead of noresume2
179+ * use echo disk > /sys/power/state to activate suspend2.
180+ By default suspend2 is configured to use lzf compression, if available,
181+ and no encryption.
182+ Overriding swsusp can by disabled via /sys/power/suspend2.
183+- Add further printks to help diagnose resume issues.
184+- Replace zone->spanned_pages with populated_zone() test.
185+- Some initial work on code to prove/ensure LRU pages aren't modified
186+ while being written. Relies on DEBUG_PAGEALLOC, so shouldn't interfere
187+ with normal use of this release, but it isn't working yet. x86 only.
188+- Some further cleanups from sysfs conversion.
189+
190+2.2.7.4 - 19 July 2006
191+
192+- Update Documentation to refer to /sys/power/suspend2.
193+- Make invocation of pm_console_suspend/resume optional
194+ and disabled by default.
195+- Add some printks for -EBUSY error messages.
196+- Rename proc.c to sysfs.c.
197+- Apply Rafael's suggestion of using the zone table info.
198+- Change .disabled to .enabled in the module structure.
199+- Change all references to proc to be sysfs.
200+- Add one second delay between powering down devices and
201+ doing the acpi state enter/machine_power_off/machine_halt.
202+- Add result code flag for drivers failing to suspend.
203+
204+2.2.7.3 - 11 July 2006
205+
206+- Add subdirectories for modules.
207+- Fix do_suspend and do_resume.
208+
209+2.2.7.2 - 11 July 2006
210+
211+- Console suspend and resume fix.
212+- Initial sysfs support. /proc support retained for the interim. Note that the
213+ sysfs layout is subject to change. I may make subdirectories for the modules
214+ (compressor etc) and put their entries in there.
215+- Modifed debugging info for compressor and encryptor so it's clearer when the
216+ name of the algorithm to be used hasn't been set.
217+- Try kernel_halt() if kernel_power_off() fails.
218+
219+2.2.7.1 - 6 July 2006
220+
221+- Remove Linus patches.
222+- Remove some debugging code from atomic_copy.c
223+- Change quotes and remove leading spaces in Kconfig
224+- Shift resetting accounting of module header storage usage.
225+- Add a missing reset of suspend2_running.
226+- Remove some extra whitespace that was used when splitting the patches.
227+- Enable some code in dyn_pageflags.c that was disabled and correct a typo
228+ in it.
229+
230+2.2.7 - 2 July 2006
231+
232+- Fix test debugging patch to run on powering down devices instead of
233+ when suspending them, and re-disable interrupts when we find something
234+ to complain about.
235+
236+2.2.6.3 - 2 July 2006
237+
238+- Add Bernard's 2.2.6.2 fix patch (thanks, Bernard!)
239+- Add test debugging patch to capture drivers that reenable irqs when they
240+ ought not.
241+
242+2.2.6.2 - 1 July 2006
243+
244+- Fix date on last release :)
245+- Fix freeze when eating memory that I forgot about before doing 2.2.6.1
246+- Small commenting fix.
247+- Quieten pdflush when thawed.
248+
249+2.2.6.1 - 1 July 2006
250+
251+- Cleanups: Whitespace/line wrapping, removal of asm-ppc/cpu_context.h,
252+ old/unnecessary declarations in dyn_pageflags.h, freezer.h. Atomic_copy
253+ prepare_pbe_list.
254+- Commenting: dyn_pageflags.h
255+- Rename: pageflags_space_needed -> suspend_*
256+- Add zones_in_use variable, to save recalculating how many zones are in use
257+ all the time (ta Rafael).
258+- !(CONFIG_VT && VT_CONSOLE) compile fix from LKML.
259+- Fix SYSTEM_BOOTING->RUNNING, from old version of Linus' console patch.
260+- Quoting of KConfig options. Addresses warnings that have appeared in
261+ post 2.6.17 git.
262+- Reverse early pm_ops->prepare and late ->finish invocations.
263+- Handle errors if bdev freezing kmalloc fails or suspend2_suspend fails.
264+- Correct error handling in suspend_main().
265+- Remove block_dump debugging in file_writer.
266+- Re-enable populate_block_list printk condition.
267+- Disable pm_prepare_console and pm_restore_console calls for now. Still
268+ seem to be problematic.
269+- Add MAINTAINERS file entry.
270+
271+2.2.6 - 23 June 2006
272+
273+- No problems reported so far with 2.2.5.3, so I'm
274+ renaming it to 2.2.6.
275+
276+2.2.5.3 - 22 June 2006
277+
278+- Update to 2.6.17
279+- Bring figuring out which pages to save closer to the
280+ algorithm used by swsusp.
281+- Move allocation of image header storage last in updating
282+ the image contents.
283+- Reset the header bytes used by each module when getting
284+ the request so S3 powerdown doesn't only work once.
285+- Tidy header allocation code.
286+- Tidy process refreezing when updating the image metadata.
287+- Add debugging code to check that LRU pages are not modified
288+ while the freezer is on.
289+- Do pm_state->prepare and finish right at the start and
290+ end of a cycle.
291+- Add Ben Collin's patch for a trace data section for ppc
292+ (needed for Linus' debugging patch, added in 2.2.5.2).
293+- Rework extra pageset1 pages allowance so that we have a
294+ hardcoded minimum and default (now 500) that is more
295+ easily modified (prepare_image.h).
296+- Take pm_sem when suspending and add PM_SEM failure bit
297+ to the result code.
298+- Use console suspend/resume code.
299+
300+2.2.5.2 - 16 June 2006
301+
302+- Remove x86_64 e820 code.
303+- Add #include to Linus' tracing code to fix compilation in
304+ Ubuntu backport.
305+- Add display of number of extra pageset 1 pages used.
306+- Modify the code which tracks our position in storage so that
307+ it sits at the start of a page and not the end. Simplifies
308+ finding where to start when resuming.
309+- Add pdflush post-resume fix from LKML.
310+
311+2.2.5.1 - 15 June 2006
312+
313+- Updated to 2.6.17-rc6.
314+- Fixed filewriter issue when header is not at the lowest block
315+ number in the file.
316+- Moved refrigerator closer to the vanilla implementation.
317+- Removed per-workqueue freezing.
318+- Carefully audited header space usage and added debugging
319+ support.
320+- Fixed compilation issues with sharing code with swsusp.
321+- Removed SUSPEND_TEST_BIO flag.
322+- Added paragraph to suspend2.txt. Pavel forked, not us :)
323+- Removed arm code. No recent updates.
324+- Added (temporary) e820 amd64 code.
325+- Fix BITMAP_FOR_EACH_SET to check for -1 instead of max_pfn.
326+- Add ifdefs around some highmem code.
327+- Fix some line length issues.
328+- Rename attempt_to_parse_resume_device to suspend_...
329+- Remove DEBUG_PAGEALLOC support.
330+- Prepare to power off with POWER_OFF, not SUSPEND_DISK.
331+- Max extra pages allowance should be INT_MAX, not 32768.
332+
333+2.2.5 - 21 April 2006
334+
335+- Cleanups from ongoing preparation of the git tree.
336+- Correction to x86_64 page_is_ram function.
337+- New FREEZING_COMPLETE status variable, used in debugging the
338+ new shrink_all_memory implementation.
339+- Improvements to calculations of header space required. More
340+ work to be done.
341+- Fix compilation with !CONFIG_NET
342+- Some new image calculation paranoia. Shouldn't be needed, but
343+ you can't always know everything that changes from one kernel
344+ version to the next.
345+- Use Con Kolivas and Rafael Wysocki's shrink_all_memory rework,
346+ with a couple of bug fixes of my own. In combination with this,
347+ simplify the memory freeing in suspend2 to use a single pass.
348+- Fix suspend_running not being set at resume time, which caused
349+ spontaneous reboots when the temporary pagedir allocator then
350+ got unsafe pages.
351+- Remove setting swap info struct data during resume.
352+- Update hooks in the pagealloc routines that prevented memory
353+ freeing while we're writing the image.
354+
355+2.2.4.1 - 13 April 2006
356+
357+- Removed use of max_pfn to make life simpler on ARM.
358+- Fix line length in atomic_copy.c.
359+- Rename suspend_recalculate_stats to suspend_recalculate_image_contents
360+- Remove checksumming code.
361+- Apply Jens Gustedt's checks for which filesystems are mounted
362+ on resume.
363+- Fix encryption where PAGE_SIZE % key length != 0.
364+- Move swsusp Makefile entries below Suspend2 again - it doesn't play
365+ nicely with Suspend2, and so needs to have it's boot time routines
366+ run later. noresume2 will also not work with noresume being compiled
367+ in first.
368+- Rework the allocation of extra pages to use PageNosave instead of
369+ PageAllocd and don't completely clear Pageset1Copy on every iteration
370+ through count_data_pages.
371+- Remove the ConflictingPages bitmap.
372+- Remove a bogus comment that said we remember conflicting pages and
373+ free them.
374+- Remove DEBUG_PAGEALLOC support.
375+- Add extra message for when powering off.
376+- Rework and cleanup code which determines which pages to save.
377+- Correction to ram_to_suspend function - it should halve the
378+ amount calculated and take account of extra pagedir pages that have
379+ been allocated.
380+- Correct handling of proc entries that use longs. This is particularly
381+ relevant to the image_size_limit. It wasn't previously correctly set
382+ to -1 or -2. (This would have broken the nocaches functionality).
383+- Move suspend_default_console_level to ui.c.
384+- Remove unused suspend_bio_task in block_io.c.
385+- Use progress granularity that was saved in the image header, even
386+ if the userui helper program stored in the image header won't be
387+ used because it was overridden by the initrd/ramfs script.
388+- Don't update the load average while the freezer is on. This fixes
389+ an unintended sideeffect wherein mail services will refuse to
390+ operate post-resume because the load average had been pushed up
391+ by Suspend's intensive CPU use.
392+
393+2.2.4 - 2 April 2006
394+
395+- Fixed what are hopefully the last outstanding issues with
396+ the switchover to using the swsusp lowlevel code:
397+ * Corrected compilation issues with the difference
398+ combinations of swsusp and Suspend2.
399+ * Make x86_64 work correctly - get_safe_page() was using
400+ the swsusp code instead of Suspend2 code.
401+
402+2.2.3 - 1 April 2006
403+
404+- Add better powerdown_methods documentation (thanks
405+ Jens Gustedt).
406+- Further work addressing issues with using the swsusp
407+ lowlevel code.
408+- Abort on resume if we fail to initialise the compression
409+ transform used when suspending.
410+- Switch filewriter to use add_to_extent_chain instead of
411+ append_extent_to_extent_chain and remove now the now
412+ unused function.
413+- Fix compilation errors if swsusp and Suspend2 are both
414+ disabled.
415+- Fix PPC compilation error with !rtas.
416+
417+2.2.2.1 - 28 March 2006
418+
419+- Missed a part of the backport, inadvertently making
420+ a requirement that you also select
421+ CONFIG_SOFTWARE_SUSPEND. Fix that by making Suspend2
422+ select SOFTWARE_SUSPEND automatically.
423+
424+2.2.2 - 28 March 2006
425+
426+- Backported to 2.6.16.
427+- Added a couple of printks for when we fail to write a
428+ block of the image. Saw this in unusual circumstances
429+ while testing, and need to seek to reproduce and fix.
430+
431+2.2.1.3 - 27 March 2006
432+Prepared against current git as at 7.30pm AEST
433+- Further cleanups as I begin to prepare the git tree
434+ in earnest.
435+- Highmem fixes I almost forgot for this release!
436+
437+2.2.1.2 - 23 March 2006
438+Prepared against current git as at 11pm AEST.
439+
440+- Further cleanups from the switch to swsusp lowlevel
441+ code. Should not longer require swsusp to be selected.
442+
443+2.2.1.1 - 23 March 2006
444+Prepared against current git as at 4:20pm AEST.
445+
446+- Switch suspend2 to use the swsusp lowlevel code.
447+- Rework freeing of extra pages allocated for the
448+ atomic copy.
449+- Misc cleanups.
450+
451+2.2.1 - 17 March 2006
452+
453+- Remove debug_pagealloc support
454+- Documentation update
455+- Move device_suspend at resume time prior to setting
456+ up temporary page tables (Lamarque Souza).
457+
458+2.2.0.8 - 15 March 2006
459+
460+- Convert pageset sizes to longs.
461+- Convert [read|write]_header_chunk to
462+ rw_header_chunk([READ|WRITE]...) and do similar
463+ cleanups with other i/o routines.
464+- Remove some unused module structure members.
465+- Flatten the module ops.
466+- Fix a couple of harmless compile warnings.
467+
468+2.2.0.7 - 15 March 2006
469+
470+- Further fixes from 2.2.0.6. Now tested with modifying
471+ resume2= in an initrd and checking image_exists prior
472+ to do the echo > do_resume.
473+
474+2.2.0.6 - 13 March 2006
475+
476+- Split logic for determining whether we can suspend from
477+ that for figuring out whether we can resume. This is
478+ useful for the filewriter, where resume2= can be valid
479+ (allowing us to resume) while filewriter_target isn't
480+ set (prohibiting suspending).
481+- Update file headers.
482+
483+2.2.0.5 - 13 March 2006
484+
485+- Oh dear. I somehow reversed the 2.2.0.3 fix in 2.2.0.4.
486+ Let's try and get them both in the same patch, shall we?
487+
488+2.2.0.4 - 13 March 2006
489+
490+- Fix missing incrementation of # extents freed in new
491+ swap storage code.
492+
493+2.2.0.3 - 11 March 2006
494+
495+- Add x86 compilation error fix I missed.
496+
497+2.2.0.2 - 11 March 2006
498+
499+- Fix minimum free ram at 2000 pages rather than nr pages >> 7.
500+- Remove command line suspend_act, suspend_lvl and suspend_dbg
501+ options.
502+- Fix issues with swap allocation that made suspend not work
503+ properly with multiple swap storage at the same priority or
504+ highly fragmented storage.
505+- Add Randy Dunlap's libata patches (sata).
506+- Removed time patches.
507+- Documentation updates
508+- Remove un-needed x86_64 fix processor context patch.
509+- Remove x86_64 mcheck_init invocation.
510+- Separate workqueue freezer, dynamic pageflags and
511+ lzf patches.
512+- Remove obsolete configuration flags from the enums in suspend2.h.
513+- Correct various typos in headers.
514+- Various cleanups.
515+- Remove command line parameters suspend_act, suspend_dbg and
516+ suspend_lvl.
517+- Remove HALT_ON debugging macro from pagedir.c.
518+- Add tags for my new patch splitting utility.
519+
520+2.2.0.1 - 15 February 2006
521+
522+- Update to 2.6.16-rc3.
523+- Further cleanups, removing fragments that are no longer needed
524+ and applying suggestions from code review.
525+- Remove Christoph's todo list code. Not because I don't like it,
526+ but because it was originally designed to help SMP cleanness,
527+ and cpu hotplug has taken over that need.
528+
529+2.2 - 24 January 2006 (Happy Birthday, Dad!)
530+
531+- Fix amd64 page_is_ram typo.
532+- Fix unintentional dependence on swsusp (amd64).
533+- Make swapwriter select swap support instead of depending
534+ on it already being selected.
535+- Make a new common function for writing the last (partial)
536+ page of a header.
537+- Remove temporary enabling of block dump when reading pageset1.
538+- Extend have_image to also display some of the details from
539+ the header.
540+- Cleanup count_data_pages changes.
541+- Save and restore the block_dump setting when starting/finishing
542+ a cycle.
543+- Add support for debugging the image header reading & writing.
544+- A few fixes to the filewriter.
545+- Cleanups in swapwriter and arch specific code.
546+
547+2.2-rc16 - 8 January 2006
548+
549+- Small updates to documentation.
550+- Fix amd64 support.
551+- Remove no-unneeded modifications to fs/super.c & mtrr code.
552+- Cleanup dyn pageflags include files.
553+- Clean freezer header.
554+- Move swsusp to bottom of Makefile to make interoperability work better.
555+- Move pm_ops prepare/finish calls back -moving the calls to pre/post
556+ hotplugging doesn't seem to be the right thing to do at the moment.
557+- Save zone info that's used during atomic restore in memory that can
558+ be safely accessed during that period.
559+- Modify swsusp so it can be used with the new freezer without causing
560+ a deadlock.
561+- Reinstate the ability to cancel a suspend part way through writing a
562+ pageset.
563+- Fix some duplicated allowance for extra pd1 pages.
564+- Further work on new PageNoSave code.
565+- Increase max outstanding I/O to 2048.
566+- Remove some unnecessary forced inlining.
567+
568+2.2-rc15 - 26 December 2005
569+
570+- Call the correct writer init routine (read/write were transposed!)
571+- Freeze filesystems in reverse order so loopback doesn't result in
572+ a hang.
573+- Select HOTPLUG_CPU instead of depending on it (SMP).
574+- Further switchovers from assuming pfns start at 0 to using per zone
575+ ranges.
576+- Lots of architecture specific fixes for PPC, x86_64 and ARM.
577+- Work on removing PageNosave dependency and changes outside kernel/power.
578+- Support new read-only section patches.
579+- Remove b44 patch.
580+- Cleanups (as always!). This time, we remove driver_model.[ch], and
581+ remove some now unused MTRR modifications and lowlevel x86 code.
582+- Small modifications to lowlevel code routine.
583+- Reintroduce /proc/suspend2/no_pageset2 for testing.
584+- Compile fix for !SUSPEND2.
585+- Fixups to powerdown code (yes, again!).
586+- Bug fix to rw_init_plugins.
587+- Small rework of sanity checking.
588+- Make num_pcp_pages() numa compatible.
589+- Cleanup filesystem freezing code.
590+- More consolidation of swapwriter and filewriter code into bio.c.
591+- Attempt to parse resume device when checking if can suspend and
592+ suspend is currently disabled.
593+- Rename noresume_setup to noresume2_setup so it works with swsusp
594+ compiled in.
595+- Fix filewriter so it again tries to stat the file if name_to_dev_t
596+ fails.
597+
598+2.2-rc14 - 2 December 2005
599+
600+- Correct header_locations in documentation to headerlocations.
601+- Remove BUG_ON() in ll_rw_blk.c.
602+- Correction to nvidia agp suspend/resume support.
603+- Complete removal of syncthread code.
604+- Consolidate all of the page i/o code from swapwriter and
605+ filewriter into one version, moved to block_io.c.
606+- Combine the io.c read & write pageset routines and make
607+ separate routines of plugin setup/cleanup and the main loop.
608+- Fix for AMD64 reading wrong block for header at resume time
609+ (and thus reporting 0.0.0 kernel version in the image).
610+
611+2.2-rc13 - 25 November 2005
612+
613+- Add ARM support, thanks to Hiroki Kaminaga at Sony.
614+- Replace remounting with freezing and thawing filesystems.
615+- Remove now unneeded syncthread code (more to be done).
616+- Don't sys_sync after freezing filesystems. That way lies deadlocks.
617+- Beginnings of cleanups for writers.
618+- Make number of extra pagedir 1 pages allowed for tunable via a
619+ new proc entry. Set it to 0 for autotuning.
620+- Fix an oops in the filewriter.
621+- Fix for typo in power off code (thanks, _damjan_).
622+
623+2.2-rc12 - 22 November 2005
624+
625+- New test_bio proc debugging entry; don't actually write anything,
626+ just say where the data would be put.
627+- Further filewriter fixes. It should be perfectly usable now,
628+ but I would still recommend care and backups!
629+- Don't use smp_processor_id in lowlevel code. With cpuhotplug, we
630+ know we're on processor zero.
631+- Fix some indentation in the lowlevel code.
632+- Touch softlockup watchdog when resuming. Shouldn't be needed and
633+ doesn't seem to make any difference, but I'll seek consistency
634+ with Pavel at this point.
635+- Show what processes enter and leave the fridge and when iff
636+ PM Debug is enabled (wRAR).
637+- Modify remounting logic introduced in rc11 so that syslog etc
638+ continue to work postresume.
639+- Remove some extra debugging code in the freezer.
640+- Prune the number of calls to attempt_to_parse so that we can
641+ properly figure out whether suspending should be enabled.
642+- Don't unblank the console from the kernel code. Doesn't play
643+ nicely with vesafb-tng.
644+
645+2.2-rc11 - 15 November 2005
646+
647+- Remount filesystems readonly while suspending so as to ensure
648+ xfs flushes all pending writes. This also means things should
649+ be nice and clean if you fail to resume (for whatever reason).
650+- Fix highmem support that I broke with rc10.
651+- Fix typo in 2nd+ attempt at resuming message.
652+
653+2.2-rc10 - 14 November 2005
654+
655+- Increased allowance for extra pagedir1 pages. This is primarily
656+ for the new flgrx driver. If you don't use it, you'll see a
657+ bigger drop in the total image size after the atomic copy. This
658+ is nothing to be concerned about.
659+- Some debugging code has been temporarily modified to always
660+ print, to help address some particular users' issues.
661+- More helpful debugging for AMD64 preemption problems.
662+- Rework of powerdown code. Powerdown method can now also be 0,
663+ meaning Suspend won't try to use ACPI to powerdown. 1 & 2 are
664+ also accepted values. You might find Standby (1) useful, but 2
665+ will probably only make the computer resume again immediately.
666+- Big rework of blocksize handling. Suspend2 is now tested with the
667+ swap files and ordinary files on ext3, xfs and reiser with each
668+ blocksize allowed by the filesystem type. Other filesystems should
669+ work without a problem because the algorithm is basically the same
670+ as that used for swapfiles.
671+- Initial version of discontiguous memory support.
672+- Replace /proc/software_suspend with /proc/suspend2.
673+- Make Suspend2 explicitly depend upon cpu hotplug for SMP.
674+- Leave interrupts enabled when powering down.
675+- Make storage manager testing proc entry depend on PM_DEBUG.
676+- Remove unnecessary check at the start of save image.
677+- Small cleanups in the swapwriter (swapfile management).
678+
679+2.2-rc9 - 5 November 2005
680+
681+- Filewriter cleanups and bug fixes.
682+- Display stats when unable to allocate enough storage, to help diagnosing
683+ this issue.
684+- Some cleanups to e820 table support.
685+- Various small fixes to PPC support.
686+- Modifed BIO submission check to be smarter (use new Suspend2 flag in BIO
687+ flags).
688+- Add userspace storage manager (usm) support. Requires userspace program.
689+ None are available yet. This change included a separation of the netlink
690+ code from the userui code into a new file.
691+- Replace type * name with type *name everywhere.
692+- Made debugging code for driver suspend/resume calls more gentle
693+ (delay/print instead of BUG_ON().
694+- Don't mark image as resumed before when in KEEP_IMAGE made.
695+- Seek to address BUG_ONs being hit in marking a task as pageset1.
696+- Address some arch/config specific compilation warnings.
697+- Use kernel_power_off_prepare instead of device_shutdown when not entering
698+ suspend to ram.
699+- Thaw kernel processes before beginning to eat memory.
700+- Make freezer quiet by default.
701+- Export freezer state for when ext3 (eg) built as a module.
702+- Add news_storage_manager to proc entry info so that entries that needs
703+ access to storage for reading and/or writing can enable it as required.
704+ There is also a new activate_storage entry that can be used in a script to
705+ avoid having it repetitively enabled and disabled by a number of instructions.
706+ echo 1 > /proc/suspend2/activate_storage
707+ at the start of the sequence and
708+ echo 0 > /proc/suspend2/activate_storage
709+ and the end.
710+- Correct bits in result code so hibernate script gives the correct
711+ interpretation again.
712+- Cleanup and simplify file management in the file writer. (Debugging printks
713+ left in for this release).
714+- Poke blanked console when resuming.
715+
716+2.2-rc8 - October 3, 2005.
717+
718+REQUIRES hibernate script 1.12 or newer.
719+
720+- Changed name of proc directory to suspend2.
721+- Removed suspend_drivers_init/cleanup
722+- Cleaned up debug_info entry
723+- Remove atomic_restore conflict check
724+- Stop tracking max extents used.
725+- put_extent. Just BUG_ON(!extent). Or don't handle.
726+- put_extent_chain remove if (!this) return
727+- Removed references to chain optimisation info
728+- Remove error messages in <load|serialise>_extent_chain (should
729+ come from real cause of err)
730+- attempt_to_parse_resume_device should return whether successful
731+- Merge plugin read/write inits/cleanups into one loop.
732+- Merge read & write routines into one generic I/O loop?
733+- Sanity check kernel version - macros for digits?
734+- Rename free_pagedir_data to free_extra_pagedir_memory. Don't reset pageset
735+ sizes there.
736+- Removed SetPageConflicting
737+- release_conflicting_pages: Delete. Not used.
738+- remove version info in proc.c
739+- Remove #ifdef CONFIG_SUSPEND2_DEFAULT_RESUME2 in suspend2
740+- compress <allocate|free>_bitmaps functions
741+- Remove #ifdef DEBUG_PAGE_ALLOC in suspend2.c
742+- can_suspend: if(DISABLED && !attempt_to_parse())
743+- Remove keep_metadata proc entry
744+- Use (DISABLED && !attempt_to_parse() in suspend2_resume, too.
745+- Removed unused fields used in io_info struct
746+- flush_dcache_page needed?
747+- Use put_page to free pages.
748+- Some extraneous comments removed.
749+- Removed header_data comment
750+- /*^N *^N *^N* ^N* ^N */
751+- Remove PRINTK in swapwriter
752+- Remove swapwriter file management?
753+- Cleaned up get_blocks_per_page in swapwriter
754+- Integrated get_path_for_swapfile to caller
755+- Parse signature - remove old pmdisk version support
756+- Removed unneeded extern int signature_check? (swapwriter:478)
757+- Cleaned up swapwriter_storage_allocated
758+- Remove space_requests = ((long) space_really_requested) << PAGE_SHIFT
759+- Remove allocate_header_space comment "was going to be in bytes"
760+- Simplified header space allocated calculation.
761+- Remove extra escape action in request_abort_suspend (not used and would
762+ be a problem anyway).
763+- Fix compile error for AMD64 SMP.
764+- Fix error in the filewriter.
765+
766+2.2-rc7 - September 16 2005
767+
768+- Further fixing of powerdown code. If !pm_ops, just use
769+ kernel_power_off.
770+- Use return code when freezing failure occurs.
771+- Make userui disabling effective.
772+
773+2.2-rc6 - September 6 2005 (The Hamilton Release)
774+
775+- Fix for corruption caused when failing to power down.
776+- Fix for failing to power down.
777+- Separated refrigerator changes from Suspend2 for separate
778+ merge.
779+- Misc other cleanups.
780+
781+2.2-rc5 - September 2 2005
782+- Add more detailed debugging information regarding which
783+ driver re-enables interrupts and recover.
784+- Handle wrong userui interface version by resetting userui
785+ and continuing without it.
786+- Fix for powerdown issues.
787+- Ensure resumed before flag isn't unintentionally set when
788+ writing header.
789+- Seek to address trace given in refrigerator code.
790+- Complain if can't find the userui process number given
791+ for setting nofreeze.
792+- Fixed a bug in the swap allocation routine that would
793+ result in swap being allocated but not freed.
794+
795+2.2-rc4 - August 30 2005
796+
797+- Fixed bounding error in swapwriter device closing. This
798+ had 'interesting' side effects.
799+- Moved storing the console log level used to before asking
800+ the userui to cleanup, so that after suspending.
801+ default_console_loglevel contains the last one used, and
802+ not the original value.
803+- Fixed a mistake in include/asm-i386/suspend2.h that broke
804+ compilation for gcc 4 users.
805+- Made the refrigerator ignore Stopped processes again. Mea
806+ culpa. As always :|
807+
808+2.2-rc3 - August 29 2005
809+
810+- Modified error message for setting the blocksize to give
811+ some useful information.
812+- Fixed typo in todo_list_active calls in jfs_txnmgr.c
813+- Fixed size of blocksize storage in header. Thanks Ola!
814+- Merged in initramfs changes to filewriter. Added new state
815+ flag for resuming from initramfs and call from do_mounts_rd.c.
816+ Yet to test.
817+- Implemented communication of the netlink socket number to use
818+ to the userui program when invoking it. (Changes to commit to
819+ userui tree)
820+- Give more information and invalidate the image when we fail to
821+ initialise a filter at resume.
822+- Clean up console when failing to resume.
823+- Make escape and toggling pause and single step take effect
824+ immediately.
825+- Fixed log everything so that it does again.
826+- Expand userui message buffer from 80 to 255 characters.
827+- Fixed a silly bug when the header is not stored on the resume
828+ block device.
829+- Modify freezer implementation to signal all processes once,
830+ separate to waiting for them to enter the refrigerator. This
831+ will be more robust and quicker if/when the todo list gets used
832+ for other things.
833+- Modify userui version to 6.
834+- Move freeing of freezer notifier entry to post spinlock release.
835+- Fix compilation error when !SUSPEND2 & CRYPTO
836+- Fix missing ; in macro for !SUSPEND2
837+
838+2.2-rc2 - August 24 2005
839+- Apply LZF 64 bit from Anders Fugmann.
840+- Complete transition to todo list and fix up jffs2.
841+- Temporary fix for gcc 4, telling it lies that we're
842+ not clobbering ebp. Something similar needed for other
843+ archs?
844+
845+2.2-rc1 - August 23 2005
846+- Fixed problem with swapwriter buffer offset not being reset
847+ when beginning to write the image header.
848+- PPC fixes from Johannes Berg.
849+- Give a better message when can't initialise a compressor.
850+- Remove an unused variable from the pageset_sizes_result struct.
851+- Make Suspend still compile ok when networking is disabled.
852+ Userui won't work (it uses netlink), but suspending will.
853+ This will also be handy for embedded support.
854+- Say why we can't do userui when we can't open /dev/console
855+ (entirely possible when resuming from an initrd).
856+
857+2.1.9.14 - August 22 2005
858+- Fixes for previous patch - base tree was slightly corrupted.
859+- Also fixed agp driver cleanups - humble apologies to ATI and
860+ Nvidia users.
861+- Small fixes for new bdev management code in swapwriter.
862+
863+2.1.9.13 - August 20 2005
864+- Added support for Christoph Lameter's todo list changes.
865+- Reworked device setup at resume time.
866+- Began splitting up patches into many more changesets for
867+ the (to be made) git tree. I'll now ship the patch as one
868+ big patch.
869+- Miscellaneous other bug fixes and cleanups.
870+
871+2.1.9.12 - August 4 2005
872+- Bug fixes for the refrigerator code
873+- Fixed bug in dyn_pageflags code that would cause an oops if
874+ allocating pageflags ever failed.
875+- Changed block io code to use kblockd_flush.
876+- Reworking of semantics for workqueue calls (merge work).
877+
878+2.1.9.11 - July 30 2005
879+- More cleanups.
880+
881+2.1.9.10 - July 23 2005
882+- Lots more cleanups and little fixes.
883+- Changed workqueue freezer implementation from using an extra parameter
884+ to using new routines with nofreeze in the name. Greatly reduces the
885+ number of files we touch.
886+- Remove SYNCTHREAD flag from kernel threads. It really means nothing.
887+ (They are frozen anyway, after real syncthreads).
888+- In the process of re-adding checksumming as a standalone patch. Not
889+ to be submitted.
890+- Cleaned up LZF. Removed macros and ifdefs.
891+- Started pushing patches.
892+- Renamed arch specific functions to include _arch_.
893+- Removed all_settings after asking how many people use it.
894+- Fixed up copyback thread spawning so as to ensure that the stack used
895+ is not in a conflicting page. We spwan new threads until one is ok.
896+ Each thread spawned will keep spawning other threads (with a delay)
897+ until one has a non conflicting page. This means you can end up with
898+ a large number of threads quickly. We guarantee that only one will
899+ continue on to the copyback. All others enter the freezer.
900+
901+2.1.9.9 - July 8 2005
902+- Move suspend2_core directory contents up to kernel/power.
903+- Further work on x86_64 (more to be done before it can be tested).
904+- Lots of cleanups in response to premerge (I hope) comments. As part
905+ of this, converted a number of lists of #defined bit indices to
906+ enums. This will break saved all_settings files, so I bumped the
907+ version.
908+- Added debugging info to swapwriter to try and diagnose set block size
909+ oops some people are seeing.
910diff --git a/Documentation/power/suspend2-internals.txt b/Documentation/power/suspend2-internals.txt
911new file mode 100644
912index 0000000..ba4e1e5
913--- /dev/null
914+++ b/Documentation/power/suspend2-internals.txt
915@@ -0,0 +1,473 @@
916+ Software Suspend 2.2 Internal Documentation.
917+ Version 1
918+
919+1. Introduction.
920+
921+ Software Suspend 2.2 is an addition to the Linux Kernel, designed to
922+ allow the user to quickly shutdown and quickly boot a computer, without
923+ needing to close documents or programs. It is equivalent to the
924+ hibernate facility in some laptops. This implementation, however,
925+ requires no special BIOS or hardware support.
926+
927+ The code in these files is based upon the original implementation
928+ prepared by Gabor Kuti and additional work by Pavel Machek and a
929+ host of others. This code has been substantially reworked by Nigel
930+ Cunningham, again with the help and testing of many others, not the
931+ least of whom is Michael Frank. At its heart, however, the operation is
932+ essentially the same as Gabor's version.
933+
934+2. Overview of operation.
935+
936+ The basic sequence of operations is as follows:
937+
938+ a. Quiesce all other activity.
939+ b. Ensure enough memory and storage space are available, and attempt
940+ to free memory/storage if necessary.
941+ c. Allocate the required memory and storage space.
942+ d. Write the image.
943+ e. Power down.
944+
945+ There are a number of complicating factors which mean that things are
946+ not as simple as the above would imply, however...
947+
948+ o The activity of each process must be stopped at a point where it will
949+ not be holding locks necessary for saving the image, or unexpectedly
950+ restart operations due to something like a timeout and thereby make
951+ our image inconsistent.
952+
953+ o It is desirous that we sync outstanding I/O to disk before calculating
954+ image statistics. This reduces corruption if one should suspend but
955+ then not resume, and also makes later parts of the operation safer (see
956+ below).
957+
958+ o We need to get as close as we can to an atomic copy of the data.
959+ Inconsistencies in the image will result in inconsistent memory contents at
960+ resume time, and thus in instability of the system and/or file system
961+ corruption. This would appear to imply a maximum image size of one half of
962+ the amount of RAM, but we have a solution... (again, below).
963+
964+ o In 2.6, we choose to play nicely with the other suspend-to-disk
965+ implementations.
966+
967+3. Detailed description of internals.
968+
969+ a. Quiescing activity.
970+
971+ Safely quiescing the system is achieved using two methods.
972+
973+ First, we note that the vast majority of processes don't need to run during
974+ suspend. They can be 'frozen'. We therefore implement a refrigerator
975+ routine, which processes enter and in which they remain until the cycle is
976+ complete. Processes enter the refrigerator via try_to_freeze() invocations
977+ at appropriate places. A process cannot be frozen in any old place. It
978+ must not be holding locks that will be needed for writing the image or
979+ freezing other processes. For this reason, userspace processes generally
980+ enter the refrigerator via the signal handling code, and kernel threads at
981+ the place in their event loops where they drop locks and yield to other
982+ processes or sleep.
983+
984+ The second part of our method for quisescing the system involves freezing
985+ the filesystems. We use the standard freeze_bdev and thaw_bdev functions to
986+ ensure that all of the user's data is synced to disk before we begin to
987+ write the image. This is particularly important with XFS, where without
988+ bdev freezing, activity may still occur after we begin to write the image
989+ (potentially causing in-memory and on-disk corruption later).
990+
991+ Quiescing the system works most quickly and reliably when we add one more
992+ element to the algorithm: separating the freezing of userspace processes
993+ from the freezing of kernel space processes, and doing the filesystem freeze
994+ in between. The filesystem freeze needs to be done while kernel threads such
995+ as kjournald can still run. At the same time, though, everything will be
996+ less racy and run more quickly if we stop userspace submitting more I/O work
997+ while we're trying to quiesce.
998+
999+ Quiescing the system is therefore done in three steps:
1000+ - Freeze userspace
1001+ - Freeze filesystems
1002+ - Freeze kernel threads
1003+
1004+ If we need to free memory, we thaw kernel threads and filesystems, but not
1005+ userspace. We can then free caches without worrying about deadlocks due to
1006+ swap files being on frozen filesystems or such like.
1007+
1008+ One limitation of this is that FUSE filesystems are incompatible with
1009+ suspending to disk. They need to be unmounted prior to suspending, to avoid
1010+ potential deadlocks.
1011+
1012+ b. Ensure enough memory & storage are available.
1013+
1014+ We have a number of constraints to meet in order to be able to successfully
1015+ suspend and resume.
1016+
1017+ First, the image will be written in two parts, described below. One of these
1018+ parts needs to have an atomic copy made, which of course implies a maximum
1019+ size of one half of the amount of system memory. The other part ('pageset')
1020+ is not atomically copied, and can therefore be as large or small as desired.
1021+
1022+ Second, we have constraints on the amount of storage available. In these
1023+ calculations, we may also consider any compression that will be done. The
1024+ cryptoapi module allows the user to configure an expected compression ratio.
1025+
1026+ Third, the user can specify an arbitrary limit on the image size, in
1027+ megabytes. This limit is treated as a soft limit, so that we don't fail the
1028+ attempt to suspend if we cannot meet this constraint.
1029+
1030+ c. Allocate the required memory and storage space.
1031+
1032+ Having done the initial freeze, we determine whether the above constraints
1033+ are met, and seek to allocate the metadata for the image. If the constraints
1034+ are not met, or we fail to allocate the required space for the metadata, we
1035+ seek to free the amount of memory that we calculate is needed and try again.
1036+ We allow up to four iterations of this loop before aborting the cycle. If we
1037+ do fail, it should only be because of a bug in Suspend's calculations.
1038+
1039+ These steps are merged together in the prepare_image function, found in
1040+ prepare_image.c. The functions are merged because of the cyclical nature
1041+ of the problem of calculating how much memory and storage is needed. Since
1042+ the data structures containing the information about the image must
1043+ themselves take memory and use storage, the amount of memory and storage
1044+ required changes as we prepare the image. Since the changes are not large,
1045+ only one or two iterations will be required to achieve a solution.
1046+
1047+ The recursive nature of the algorithm is miminised by keeping user space
1048+ frozen while preparing the image, and by the fact that our records of which
1049+ pages are to be saved and which pageset they are saved in use bitmaps (so
1050+ that changes in number or fragmentation of the pages to be saved don't
1051+ feedback via changes in the amount of memory needed for metadata). The
1052+ recursiveness is thus limited to any extra slab pages allocated to store the
1053+ extents that record storage used, and he effects of seeking to free memory.
1054+
1055+ d. Write the image.
1056+
1057+ We previously mentioned the need to create an atomic copy of the data, and
1058+ the half-of-memory limitation that is implied in this. This limitation is
1059+ circumvented by dividing the memory to be saved into two parts, called
1060+ pagesets.
1061+
1062+ Pageset2 contains the page cache - the pages on the active and inactive
1063+ lists. These pages aren't needed or modifed while Suspend2 is running, so
1064+ they can be safely written without an atomic copy. They are therefore
1065+ saved first and reloaded last. While saving these pages, Suspend2 carefully
1066+ ensures that the work of writing the pages doesn't make the image
1067+ inconsistent.
1068+
1069+ Once pageset2 has been saved, we prepare to do the atomic copy of remaining
1070+ memory. As part of the preparation, we power down drivers, thereby providing
1071+ them with the opportunity to have their state recorded in the image. The
1072+ amount of memory allocated by drivers for this is usually negligible, but if
1073+ DRI is in use, video drivers may require significants amounts. Ideally we
1074+ would be able to query drivers while preparing the image as to the amount of
1075+ memory they will need. Unfortunately no such mechanism exists at the time of
1076+ writing. For this reason, Suspend2 allows the user to set an
1077+ 'extra_pages_allowance', which is used to seek to ensure sufficient memory
1078+ is available for drivers at this point. Suspend2 also lets the user set this
1079+ value to 0. In this case, a test driver suspend is done while preparing the
1080+ image, and the difference (plus a margin) used instead.
1081+
1082+ Having suspended the drivers, we save the CPU context before making an
1083+ atomic copy of pageset1, resuming the drivers and saving the atomic copy.
1084+ After saving the two pagesets, we just need to save our metadata before
1085+ powering down.
1086+
1087+ As we mentioned earlier, the contents of pageset2 pages aren't needed once
1088+ they've been saved. We therefore use them as the destination of our atomic
1089+ copy. In the unlikely event that pageset1 is larger, extra pages are
1090+ allocated while the image is being prepared. This is normally only a real
1091+ possibility when the system has just been booted and the page cache is
1092+ small.
1093+
1094+ This is where we need to be careful about syncing, however. Pageset2 will
1095+ probably contain filesystem meta data. If this is overwritten with pageset1
1096+ and then a sync occurs, the filesystem will be corrupted - at least until
1097+ resume time and another sync of the restored data. Since there is a
1098+ possibility that the user might not resume or (may it never be!) that
1099+ suspend might oops, we do our utmost to avoid syncing filesystems after
1100+ copying pageset1.
1101+
1102+ e. Power down.
1103+
1104+ Powering down uses standard kernel routines. Suspend2 supports powering down
1105+ using the ACPI S3, S4 and S5 methods or the kernel's non-ACPI power-off.
1106+ Supporting suspend to ram (S3) as a power off option might sound strange,
1107+ but it allows the user to quickly get their system up and running again if
1108+ the battery doesn't run out (we just need to re-read the overwritten pages)
1109+ and if the battery does run out (or the user removes power), they can still
1110+ resume.
1111+
1112+4. Data Structures.
1113+
1114+ Suspend2 uses three main structures to store its metadata and configuration
1115+ information:
1116+
1117+ a) Pageflags bitmaps.
1118+
1119+ Suspend records which pages will be in pageset1, pageset2, the destination
1120+ of the atomic copy and the source of the atomically restored image using
1121+ bitmaps. These bitmaps are created from order zero allocations to maximise
1122+ reliability. The individual pages are combined together with pointers to
1123+ form per-zone bitmaps, which are in turn combined with another layer of
1124+ pointers to construct the overall bitmap.
1125+
1126+ The pageset1 bitmap is thus easily stored in the image header for use at
1127+ resume time.
1128+
1129+ As mentioned above, using bitmaps also means that the amount of memory and
1130+ storage required for recording the above information is constant. This
1131+ greatly simplifies the work of preparing the image. In earlier versions of
1132+ Suspend2, extents were used to record which pages would be stored. In that
1133+ case, however, eating memory could result in greater fragmentation of the
1134+ lists of pages, which in turn required more memory to store the extents and
1135+ more storage in the image header. These could in turn require further
1136+ freeing of memory, and another iteration. All of this complexity is removed
1137+ by having bitmaps.
1138+
1139+ Bitmaps also make a lot of sense because Suspend2 only ever iterates
1140+ through the lists. There is therefore no cost to not being able to find the
1141+ nth page in order 0 time. We only need to worry about the cost of finding
1142+ the n+1th page, given the location of the nth page. Bitwise optimisations
1143+ help here.
1144+
1145+ The data structure is: unsigned long ***.
1146+
1147+ b) Extents for block data.
1148+
1149+ Suspend2 supports writing the image to multiple block devices. In the case
1150+ of swap, multiple partitions and/or files may be in use, and we happily use
1151+ them all. This is accomplished as follows:
1152+
1153+ Whatever the actual source of the allocated storage, the destination of the
1154+ image can be viewed in terms of one or more block devices, and on each
1155+ device, a list of sectors. To simplify matters, we only use contiguous,
1156+ PAGE_SIZE aligned sectors, like the swap code does.
1157+
1158+ Since sector numbers on each bdev may well not start at 0, it makes much
1159+ more sense to use extents here. Contiguous ranges of pages can thus be
1160+ represented in the extents by contiguous values.
1161+
1162+ Variations in block size are taken account of in transforming this data
1163+ into the parameters for bio submission.
1164+
1165+ We can thus implement a layer of abstraction wherein the core of Suspend2
1166+ doesn't have to worry about which device we're currently writing to or
1167+ where in the device we are. It simply requests that the next page in the
1168+ pageset or header be written, leaving the details to this lower layer.
1169+ The lower layer remembers where in the sequence of devices and blocks each
1170+ pageset starts. The header always starts at the beginning of the allocated
1171+ storage.
1172+
1173+ So extents are:
1174+
1175+ struct extent {
1176+ unsigned long minimum, maximum;
1177+ struct extent *next;
1178+ }
1179+
1180+ These are combined into chains of extents for a device:
1181+
1182+ struct extent_chain {
1183+ int size; /* size of the extent ie sum (max-min+1) */
1184+ int allocs, frees;
1185+ char *name;
1186+ struct extent *first, *last_touched;
1187+ };
1188+
1189+ For each bdev, we need to store a little more info:
1190+
1191+ struct suspend_bdev_info {
1192+ struct block_device *bdev;
1193+ dev_t dev_t;
1194+ int bmap_shift;
1195+ int blocks_per_page;
1196+ };
1197+
1198+ The dev_t is used to identify the device in the stored image. As a result,
1199+ we expect devices at resume time to have the same major and minor numbers
1200+ as they had while suspending. This is primarily a concern where the user
1201+ utilises LVM for storage, as they will need to dmsetup their partitions in
1202+ such a way as to maintain this consistency at resume time.
1203+
1204+ bmap_shift and blocks_per_page record apply the effects of variations in
1205+ blocks per page settings for the filesystem and underlying bdev. For most
1206+ filesystems, these are the same, but for xfs, they can have independant
1207+ values.
1208+
1209+ Combining these two structures together, we have everything we need to
1210+ record what devices and what blocks on each device are being used to
1211+ store the image, and to submit i/o using bio_submit.
1212+
1213+ The last elements in the picture are a means of recording how the storage
1214+ is being used.
1215+
1216+ We do this first and foremost by implementing a layer of abstraction on
1217+ top of the devices and extent chains which allows us to view however many
1218+ devices there might be as one long storage tape, with a single 'head' that
1219+ tracks a 'current position' on the tape:
1220+
1221+ struct extent_iterate_state {
1222+ struct extent_chain *chains;
1223+ int num_chains;
1224+ int current_chain;
1225+ struct extent *current_extent;
1226+ unsigned long current_offset;
1227+ };
1228+
1229+ That is, *chains points to an array of size num_chains of extent chains.
1230+ For the filewriter, this is always a single chain. For the swapwriter, the
1231+ array is of size MAX_SWAPFILES.
1232+
1233+ current_chain, current_extent and current_offset thus point to the current
1234+ index in the chains array (and into a matching array of struct
1235+ suspend_bdev_info), the current extent in that chain (to optimise access),
1236+ and the current value in the offset.
1237+
1238+ The image is divided into three parts:
1239+ - The header
1240+ - Pageset 1
1241+ - Pageset 2
1242+
1243+ The header always starts at the first device and first block. We know its
1244+ size before we begin to save the image because we carefully account for
1245+ everything that will be stored in it.
1246+
1247+ The second pageset (LRU) is stored first. It begins on the next page after
1248+ the end of the header.
1249+
1250+ The first pageset is stored second. It's start location is only known once
1251+ pageset2 has been saved, since pageset2 may be compressed as it is written.
1252+ This location is thus recorded at the end of saving pageset2. It is page
1253+ aligned also.
1254+
1255+ Since this information is needed at resume time, and the location of extents
1256+ in memory will differ at resume time, this needs to be stored in a portable
1257+ way:
1258+
1259+ struct extent_iterate_saved_state {
1260+ int chain_num;
1261+ int extent_num;
1262+ unsigned long offset;
1263+ };
1264+
1265+ We can thus implement a layer of abstraction wherein the core of Suspend2
1266+ doesn't have to worry about which device we're currently writing to or
1267+ where in the device we are. It simply requests that the next page in the
1268+ pageset or header be written, leaving the details to this layer, and
1269+ invokes the routines to remember and restore the position, without having
1270+ to worry about the details of how the data is arranged on disk or such like.
1271+
1272+ c) Modules
1273+
1274+ One aim in designing Suspend2 was to make it flexible. We wanted to allow
1275+ for the implementation of different methods of transforming a page to be
1276+ written to disk and different methods of getting the pages stored.
1277+
1278+ In early versions (the betas and perhaps Suspend1), compression support was
1279+ inlined in the image writing code, and the data structures and code for
1280+ managing swap were intertwined with the rest of the code. A number of people
1281+ had expressed interest in implementing image encryption, and alternative
1282+ methods of storing the image.
1283+
1284+ In order to achieve this, Suspend2 was given a modular design.
1285+
1286+ A module is a single file which encapsulates the functionality needed
1287+ to transform a pageset of data (encryption or compression, for example),
1288+ or to write the pageset to a device. The former type of module is called
1289+ a 'page-transformer', the later a 'writer'.
1290+
1291+ Modules are linked together in pipeline fashion. There may be zero or more
1292+ page transformers in a pipeline, and there is always exactly one writer.
1293+ The pipeline follows this pattern:
1294+
1295+ ---------------------------------
1296+ | Suspend2 Core |
1297+ ---------------------------------
1298+ |
1299+ |
1300+ ---------------------------------
1301+ | Page transformer 1 |
1302+ ---------------------------------
1303+ |
1304+ |
1305+ ---------------------------------
1306+ | Page transformer 2 |
1307+ ---------------------------------
1308+ |
1309+ |
1310+ ---------------------------------
1311+ | Writer |
1312+ ---------------------------------
1313+
1314+ During the writing of an image, the core code feeds pages one at a time
1315+ to the first module. This module performs whatever transformations it
1316+ implements on the incoming data, completely consuming the incoming data and
1317+ feeding output in a similar manner to the next module. A module may buffer
1318+ its output.
1319+
1320+ During reading, the pipeline works in the reverse direction. The core code
1321+ calls the first module with the address of a buffer which should be filled.
1322+ (Note that the buffer size is always PAGE_SIZE at this time). This module
1323+ will in turn request data from the next module and so on down until the
1324+ writer is made to read from the stored image.
1325+
1326+ Part of definition of the structure of a module thus looks like this:
1327+
1328+ int (*rw_init) (int rw, int stream_number);
1329+ int (*rw_cleanup) (int rw);
1330+ int (*write_chunk) (struct page *buffer_page);
1331+ int (*read_chunk) (struct page *buffer_page, int sync);
1332+
1333+ It should be noted that the _cleanup routine may be called before the
1334+ full stream of data has been read or written. While writing the image,
1335+ the user may (depending upon settings) choose to abort suspending, and
1336+ if we are in the midst of writing the last portion of the image, a portion
1337+ of the second pageset may be reread. This may also happen if an error
1338+ occurs and we seek to abort the process of writing the image.
1339+
1340+ The modular design is also useful in a number of other ways. It provides
1341+ a means where by we can add support for:
1342+
1343+ - providing overall initialisation and cleanup routines;
1344+ - serialising configuration information in the image header;
1345+ - providing debugging information to the user;
1346+ - determining memory and image storage requirements;
1347+ - dis/enabling components at run-time;
1348+ - configuring the module (see below);
1349+
1350+ ...and routines for writers specific to their work:
1351+ - Parsing a resume2= location;
1352+ - Determining whether an image exists;
1353+ - Marking a resume as having been attempted;
1354+ - Invalidating an image;
1355+
1356+ Since some parts of the core - the user interface and storage manager
1357+ support - have use for some of these functions, they are registered as
1358+ 'miscellaneous' modules as well.
1359+
1360+ d) Sysfs data structures.
1361+
1362+ This brings us naturally to support for configuring Suspend2. We desired to
1363+ provide a way to make Suspend2 as flexible and configurable as possible.
1364+ The user shouldn't have to reboot just because they want to now suspend to
1365+ a file instead of a partition, for example.
1366+
1367+ To accomplish this, Suspend2 implements a very generic means whereby the
1368+ core and modules can register new sysfs entries. All Suspend2 entries use
1369+ a single _store and _show routine, both of which are found in sysfs.c in
1370+ the kernel/power directory. These routines handle the most common operations
1371+ - getting and setting the values of bits, integers, longs, unsigned longs
1372+ and strings in one place, and allow overrides for customised get and set
1373+ options as well as side-effect routines for all reads and writes.
1374+
1375+ When combined with some simple macros, a new sysfs entry can then be defined
1376+ in just a couple of lines:
1377+
1378+ { SUSPEND2_ATTR("progress_granularity", SYSFS_RW),
1379+ SYSFS_INT(&progress_granularity, 1, 2048)
1380+ },
1381+
1382+ This defines a sysfs entry named "progress_granularity" which is rw and
1383+ allows the user to access an integer stored at &progress_granularity, giving
1384+ it a value between 1 and 2048 inclusive.
1385+
1386+ Sysfs entries are registered under /sys/power/suspend2, and entries for
1387+ modules are located in a subdirectory named after the module.
1388+
1389diff --git a/Documentation/power/suspend2.txt b/Documentation/power/suspend2.txt
1390new file mode 100644
1391index 0000000..b5a8edb
1392--- /dev/null
1393+++ b/Documentation/power/suspend2.txt
1394@@ -0,0 +1,713 @@
1395+ --- Suspend2, version 2.2 ---
1396+
1397+1. What is it?
1398+2. Why would you want it?
1399+3. What do you need to use it?
1400+4. Why not just use the version already in the kernel?
1401+5. How do you use it?
1402+6. What do all those entries in /sys/power/suspend2 do?
1403+7. How do you get support?
1404+8. I think I've found a bug. What should I do?
1405+9. When will XXX be supported?
1406+10 How does it work?
1407+11. Who wrote Suspend2?
1408+
1409+1. What is it?
1410+
1411+ Imagine you're sitting at your computer, working away. For some reason, you
1412+ need to turn off your computer for a while - perhaps it's time to go home
1413+ for the day. When you come back to your computer next, you're going to want
1414+ to carry on where you left off. Now imagine that you could push a button and
1415+ have your computer store the contents of its memory to disk and power down.
1416+ Then, when you next start up your computer, it loads that image back into
1417+ memory and you can carry on from where you were, just as if you'd never
1418+ turned the computer off. Far less time to start up, no reopening
1419+ applications and finding what directory you put that file in yesterday.
1420+ That's what Suspend2 does.
1421+
1422+ Suspend2 has a long heritage. It began life as work by Gabor Kuti, who,
1423+ with some help from Pavel Machek, got an early version going in 1999. The
1424+ project was then taken over by Florent Chabaud while still in alpha version
1425+ numbers. Nigel Cunningham came on the scene when Florent was unable to
1426+ continue, moving the project into betas, then 1.0, 2.0 and so on up to
1427+ the present 2.2 series. Pavel Machek's swsusp code, which was merged around
1428+ 2.5.17 retains the original name, and was essentially a fork of the beta
1429+ code until Rafael Wysocki came on the scene in 2005 and began to improve it
1430+ further.
1431+
1432+2. Why would you want it?
1433+
1434+ Why wouldn't you want it?
1435+
1436+ Being able to save the state of your system and quickly restore it improves
1437+ your productivity - you get a useful system in far less time than through
1438+ the normal boot process.
1439+
1440+3. What do you need to use it?
1441+
1442+ a. Kernel Support.
1443+
1444+ i) The Suspend2 patch.
1445+
1446+ Suspend2 is part of the Linux Kernel. This version is not part of Linus's
1447+ 2.6 tree at the moment, so you will need to download the kernel source and
1448+ apply the latest patch. Having done that, enable the appropriate options in
1449+ make [menu|x]config (under Power Management Options), compile and install your
1450+ kernel. Suspend2 works with SMP, Highmem, preemption, x86-32, PPC and x86_64.
1451+
1452+ Suspend2 patches are available from http://suspend2.net.
1453+
1454+ ii) Compression and encryption support.
1455+
1456+ Compression and encryption support are implemented via the
1457+ cryptoapi. You will therefore want to select any Cryptoapi transforms that
1458+ you want to use on your image from the Cryptoapi menu while configuring
1459+ your kernel.
1460+
1461+ You can also tell Suspend to write it's image to an encrypted and/or
1462+ compressed filesystem/swap partition. In that case, you don't need to do
1463+ anything special for Suspend2 when it comes to kernel configuration.
1464+
1465+ iii) Configuring other options.
1466+
1467+ While you're configuring your kernel, try to configure as much as possible
1468+ to build as modules. We recommend this because there are a number of drivers
1469+ that are still in the process of implementing proper power management
1470+ support. In those cases, the best way to work around their current lack is
1471+ to build them as modules and remove the modules while suspending. You might
1472+ also bug the driver authors to get their support up to speed, or even help!
1473+
1474+ b. Storage.
1475+
1476+ i) Swap.
1477+
1478+ Suspend2 can store the suspend image in your swap partition, a swap file or
1479+ a combination thereof. Whichever combination you choose, you will probably
1480+ want to create enough swap space to store the largest image you could have,
1481+ plus the space you'd normally use for swap. A good rule of thumb would be
1482+ to calculate the amount of swap you'd want without using Suspend2, and then
1483+ add the amount of memory you have. This swapspace can be arranged in any way
1484+ you'd like. It can be in one partition or file, or spread over a number. The
1485+ only requirement is that they be active when you start a suspend cycle.
1486+
1487+ There is one exception to this requirement. Suspend2 has the ability to turn
1488+ on one swap file or partition at the start of suspending and turn it back off
1489+ at the end. If you want to ensure you have enough memory to store a image
1490+ when your memory is fully used, you might want to make one swap partition or
1491+ file for 'normal' use, and another for Suspend2 to activate & deactivate
1492+ automatically. (Further details below).
1493+
1494+ ii) Normal files.
1495+
1496+ Suspend2 includes a 'filewriter'. The filewriter can store your image in a
1497+ simple file. Since Linux has the idea of everything being a file, this is
1498+ more powerful than it initially sounds. If, for example, you were to set up
1499+ a network block device file, you could suspend to a network server. This has
1500+ been tested and works to a point, but nbd itself isn't stateless enough for
1501+ our purposes.
1502+
1503+ Take extra care when setting up the filewriter. If you just type commands
1504+ without thinking and then try to suspend, you could cause irreversible
1505+ corruption on your filesystems! Make sure you have backups.
1506+
1507+ Most people will only want to suspend to a local file. To achieve that, do
1508+ something along the lines of:
1509+
1510+ echo "Suspend2" > /suspend-file
1511+ dd if=/dev/zero bs=1M count=512 >> suspend-file
1512+
1513+ This will create a 512MB file called /suspend-file. To get Suspend2 to use
1514+ it:
1515+
1516+ echo /suspend-file > /sys/power/suspend2/filewriter/filewriter_target
1517+
1518+ Then
1519+
1520+ cat /sys/power/suspend2/resume2
1521+
1522+ Put the results of this into your bootloader's configuration (see also step
1523+ C, below:
1524+
1525+ ---EXAMPLE-ONLY-DON'T-COPY-AND-PASTE---
1526+ # cat /sys/power/suspend2/resume2
1527+ file:/dev/hda2:0x1e001
1528+
1529+ In this example, we would edit the append= line of our lilo.conf|menu.lst
1530+ so that it included:
1531+
1532+ resume2=file:/dev/hda2:0x1e001
1533+ ---EXAMPLE-ONLY-DON'T-COPY-AND-PASTE---
1534+
1535+ For those who are thinking 'Could I make the file sparse?', the answer is
1536+ 'No!'. At the moment, there is no way for Suspend2 to fill in the holes in
1537+ a sparse file while suspending. In the longer term (post merge!), I'd like
1538+ to change things so that the file could be dynamically resized as needed.
1539+ Right now, however, that's not possible and not a priority.
1540+
1541+ c. Bootloader configuration.
1542+
1543+ Using Suspend2 also requires that you add an extra parameter to
1544+ your lilo.conf or equivalent. Here's an example for a swap partition:
1545+
1546+ append="resume2=swap:/dev/hda1"
1547+
1548+ This would tell Suspend2 that /dev/hda1 is a swap partition you
1549+ have. Suspend2 will use the swap signature of this partition as a
1550+ pointer to your data when you suspend. This means that (in this example)
1551+ /dev/hda1 doesn't need to be _the_ swap partition where all of your data
1552+ is actually stored. It just needs to be a swap partition that has a
1553+ valid signature.
1554+
1555+ You don't need to have a swap partition for this purpose. Suspend2
1556+ can also use a swap file, but usage is a little more complex. Having made
1557+ your swap file, turn it on and do
1558+
1559+ cat /sys/power/suspend2/swapwriter/headerlocations
1560+
1561+ (this assumes you've already compiled your kernel with Suspend2
1562+ support and booted it). The results of the cat command will tell you
1563+ what you need to put in lilo.conf:
1564+
1565+ For swap partitions like /dev/hda1, simply use resume2=/dev/hda1.
1566+ For swapfile `swapfile`, use resume2=swap:/dev/hda2:0x242d.
1567+
1568+ If the swapfile changes for any reason (it is moved to a different
1569+ location, it is deleted and recreated, or the filesystem is
1570+ defragmented) then you will have to check
1571+ /sys/power/suspend2/swapwriter/headerlocations for a new resume_block value.
1572+
1573+ Once you've compiled and installed the kernel and adjusted your bootloader
1574+ configuration, you should only need to reboot for the most basic part
1575+ of Suspend2 to be ready.
1576+
1577+ If you only compile in the swapwriter, or only compile in the filewriter,
1578+ you don't need to add the "swap:" part of the resume2= parameters above.
1579+ resume2=/dev/hda2:0x242d will work just as well.
1580+
1581+ d. The hibernate script.
1582+
1583+ Since the driver model in 2.6 kernels is still being developed, you may need
1584+ to do more, however. Users of Suspend2 usually start the process via a script
1585+ which prepares for the suspend, tells the kernel to do its stuff and then
1586+ restore things afterwards. This script might involve:
1587+
1588+ - Switching to a text console and back if X doesn't like the video card
1589+ status on resume.
1590+ - Un/reloading PCMCIA support since it doesn't play well with suspend.
1591+
1592+ Note that you might not be able to unload some drivers if there are
1593+ processes using them. You might have to kill off processes that hold
1594+ devices open. Hint: if your X server accesses an USB mouse, doing a
1595+ 'chvt' to a text console releases the device and you can unload the
1596+ module.
1597+
1598+ Check out the latest script (available on suspend2.net).
1599+
1600+4. Why not just use the version already in the kernel?
1601+
1602+ The version in the vanilla kernel has a number of drawbacks. Among these:
1603+ - it has a maximum image size of 1/2 total memory.
1604+ - it doesn't allocate storage until after it has snapshotted memory.
1605+ This means that you can't be sure suspending will work until you
1606+ see it start to write the image.
1607+ - it performs all of it's I/O synchronously.
1608+ - it does not allow you to press escape to cancel a cycle
1609+ - it does not allow you to automatically swapon a file when
1610+ starting a cycle.
1611+ - it does not allow you to use multiple swap partitions.
1612+ - it does not allow you to use swapfiles.
1613+ - it does not allow you to use ordinary files.
1614+ - it just invalidates an image and continues to boot if you
1615+ accidentally boot the wrong kernel after suspending.
1616+ - it doesn't support any sort of nice display while suspending
1617+ - it is moving toward requiring that you have an initrd/initramfs
1618+ to ever have a hope of resuming (uswsusp). While uswsusp will
1619+ address some of the concerns above, it won't address all, and
1620+ will be more complicated to get set up.
1621+
1622+5. How do you use it?
1623+
1624+ A suspend cycle can be started directly by doing:
1625+
1626+ echo > /sys/power/suspend2/do_resume
1627+
1628+ In practice, though, you'll probably want to use the hibernate script
1629+ to unload modules, configure the kernel the way you like it and so on.
1630+ In that case, you'd do (as root):
1631+
1632+ hibernate
1633+
1634+ See the hibernate script's man page for more details on the options it
1635+ takes.
1636+
1637+ If you're using the text or splash user interface modules, one neat feature
1638+ of Suspend2 that you might find useful is that you can press Escape at any
1639+ time during suspending, and the process will be aborted.
1640+
1641+ Due to the way suspend works, this means you'll have your system back and
1642+ perfectly usable almost instantly. The only exception is when it's at the
1643+ very end of writing the image. Then it will need to reload a small (
1644+ usually 4-50MBs, depending upon the image characteristics) portion first.
1645+
1646+ If you run into problems with resuming, adding the "noresume2" option to
1647+ the kernel command line will let you skip the resume step and recover your
1648+ system.
1649+
1650+6. What do all those entries in /sys/power/suspend2 do?
1651+
1652+ /sys/power/suspend2 is the directory which contains files you can use to
1653+ tune and configure Suspend2 to your liking. The exact contents of
1654+ the directory will depend upon the version of Suspend2 you're
1655+ running and the options you selected at compile time. In the following
1656+ descriptions, names in brackets refer to compile time options.
1657+ (Note that they're all dependant upon you having selected CONFIG_SUSPEND2
1658+ in the first place!).
1659+
1660+ Since the values of these settings can open potential security risks, they
1661+ are usually accessible only to the root user. You can, however, enable a
1662+ compile time option which makes all of these files world-accessible. This
1663+ should only be done if you trust everyone with shell access to this
1664+ computer!
1665+
1666+ - checksum/enabled
1667+
1668+ Use cryptoapi hashing routines to verify that Pageset2 pages don't change
1669+ while we're saving the first part of the image, and to get any pages that
1670+ do change resaved in the atomic copy. This should normally not be needed,
1671+ but if you're seeing issues, please enable this. If your issues stop you
1672+ being able to resume, enable this option, suspend and cancel the cycle
1673+ after the atomic copy is done. If the debugging info shows a non-zero
1674+ number of pages resaved, please report this to Nigel.
1675+
1676+ - compression/algorithm
1677+
1678+ Set the cryptoapi algorithm used for compressing the image.
1679+
1680+ - compression/expected_compression
1681+
1682+ These values allow you to set an expected compression ratio, which Software
1683+ Suspend will use in calculating whether it meets constraints on the image
1684+ size. If this expected compression ratio is not attained, the suspend will
1685+ abort, so it is wise to allow some spare. You can see what compression
1686+ ratio is achieved in the logs after suspending.
1687+
1688+ - debug_info:
1689+
1690+ This file returns information about your configuration that may be helpful
1691+ in diagnosing problems with suspending.
1692+
1693+ - do_resume:
1694+
1695+ When anything is written to this file suspend will attempt to read and
1696+ restore an image. If there is no image, it will return almost immediately.
1697+ If an image exists, the echo > will never return. Instead, the original
1698+ kernel context will be restored and the original echo > do_suspend will
1699+ return.
1700+
1701+ - do_suspend:
1702+
1703+ When anything is written to this file, the kernel side of Suspend2 will
1704+ begin to attempt to write an image to disk and power down. You'll normally
1705+ want to run the hibernate script instead, to get modules unloaded first.
1706+
1707+ - driver_model_beeping
1708+
1709+ Enable beeping when suspending and resuming the drivers. Might help with
1710+ determining where a problem in resuming occurs.
1711+
1712+ - */enabled
1713+
1714+ These option can be used to temporarily disable various parts of suspend.
1715+
1716+ - encryption/*
1717+
1718+ The iv, key, save_key_and_iv, mode and algorithm values allow you to
1719+ select a cryptoapi encryption algoritm, set the iv and key and whether
1720+ they are saved in the image header. Saving the iv and key in the image
1721+ header is of course less secure than having them on some external device,
1722+ such as a USB key. If you want to use a USB key, you'll need to write
1723+ some scripting in your initrd/ramfs to retrieve the key & iv from your
1724+ USB key and put them into the entries again prior to doing the echo to
1725+ do_resume.
1726+
1727+ - extra_pages_allowance
1728+
1729+ When Suspend2 does its atomic copy, it calls the driver model suspend
1730+ and resume methods. If you have DRI enabled with a driver such as fglrx,
1731+ this can result in the driver allocating a substantial amount of memory
1732+ for storing its state. Extra_pages_allowance tells suspend2 how much
1733+ extra memory it should ensure is available for those allocations. If
1734+ your attempts at suspending end with a message in dmesg indicating that
1735+ insufficient extra pages were allowed, you need to increase this value.
1736+
1737+ - filewriter/target:
1738+
1739+ Read this value to get the current setting. Write to it to point Suspend
1740+ at a new storage location for the filewriter. See above for details of how
1741+ to set up the filewriter.
1742+
1743+ - freezer_test
1744+
1745+ This entry can be used to get Suspend2 to just test the freezer without
1746+ actually doing a suspend cycle. It is useful for diagnosing freezing
1747+ issues.
1748+
1749+ - image_exists:
1750+
1751+ Can be used in a script to determine whether a valid image exists at the
1752+ location currently pointed to by resume2=. Returns up to three lines.
1753+ The first is whether an image exists (-1 for unsure, otherwise 0 or 1).
1754+ If an image eixsts, additional lines will return the machine and version.
1755+ Echoing anything to this entry removes any current image.
1756+
1757+ - image_size_limit:
1758+
1759+ The maximum size of suspend image written to disk, measured in megabytes
1760+ (1024*1024).
1761+
1762+ - interface_version:
1763+
1764+ The value returned by this file can be used by scripts and configuration
1765+ tools to determine what entries should be looked for. The value is
1766+ incremented whenever an entry in /sys/power/suspend2 is obsoleted or
1767+ added.
1768+
1769+ - last_result:
1770+
1771+ The result of the last suspend, as defined in
1772+ include/linux/suspend-debug.h with the values SUSPEND_ABORTED to
1773+ SUSPEND_KEPT_IMAGE. This is a bitmask.
1774+
1775+ - log_everything (CONFIG_PM_DEBUG):
1776+
1777+ Setting this option results in all messages printed being logged. Normally,
1778+ only a subset are logged, so as to not slow the process and not clutter the
1779+ logs. Useful for debugging. It can be toggled during a cycle by pressing
1780+ 'L'.
1781+
1782+ - pause_between_steps (CONFIG_PM_DEBUG):
1783+
1784+ This option is used during debugging, to make Suspend2 pause between
1785+ each step of the process. It is ignored when the nice display is on.
1786+
1787+ - powerdown_method:
1788+
1789+ Used to select a method by which Suspend2 should powerdown after writing the
1790+ image. Currently:
1791+
1792+ 0: Don't use ACPI to power off.
1793+ 3: Attempt to enter Suspend-to-ram.
1794+ 4: Attempt to enter ACPI S4 mode.
1795+ 5: Attempt to power down via ACPI S5 mode.
1796+
1797+ Note that these options are highly dependant upon your hardware & software:
1798+
1799+ 3: When succesful, your machine suspends-to-ram instead of powering off.
1800+ The advantage of using this mode is that it doesn't matter whether your
1801+ battery has enough charge to make it through to your next resume. If it
1802+ lasts, you will simply resume from suspend to ram (and the image on disk
1803+ will be discarded). If the battery runs out, you will resume from disk
1804+ instead. The disadvantage is that it takes longer than a normal
1805+ suspend-to-ram to enter the state, since the suspend-to-disk image needs
1806+ to be written first.
1807+ 4/5: When successful, your machine will be off and comsume (almost) no power.
1808+ But it might still react to some external events like opening the lid or
1809+ trafic on a network or usb device. For the bios, resume is then the same
1810+ as warm boot, similar to a situation where you used the command `reboot'
1811+ to reboot your machine. If your machine has problems on warm boot or if
1812+ you want to protect your machine with the bios password, this is probably
1813+ not the right choice. Mode 4 may be necessary on some machines where ACPI
1814+ wake up methods need to be run to properly reinitialise hardware after a
1815+ suspend-to-disk cycle.
1816+ 0: Switch the machine completely off. The only possible wakeup is the power
1817+ button. For the bios, resume is then the same as a cold boot, in
1818+ particular you would have to provide your bios boot password if your
1819+ machine uses that feature for booting.
1820+
1821+ - progressbar_granularity_limit:
1822+
1823+ This option can be used to limit the granularity of the progress bar
1824+ displayed with a bootsplash screen. The value is the maximum number of
1825+ steps. That is, 10 will make the progress bar jump in 10% increments.
1826+
1827+ - reboot:
1828+
1829+ This option causes Suspend2 to reboot rather than powering down
1830+ at the end of saving an image. It can be toggled during a cycle by pressing
1831+ 'R'.
1832+
1833+ - resume_commandline:
1834+
1835+ This entry can be read after resuming to see the commandline that was used
1836+ when resuming began. You might use this to set up two bootloader entries
1837+ that are the same apart from the fact that one includes a extra append=
1838+ argument "at_work=1". You could then grep resume_commandline in your
1839+ post-resume scripts and configure networking (for example) differently
1840+ depending upon whether you're at home or work. resume_commandline can be
1841+ set to arbitrary text if you wish to remove sensitive contents.
1842+
1843+ - swapwriter/swapfilename:
1844+
1845+ This entry is used to specify the swapfile or partition that
1846+ Suspend2 will attempt to swapon/swapoff automatically. Thus, if
1847+ I normally use /dev/hda1 for swap, and want to use /dev/hda2 for specifically
1848+ for my suspend image, I would
1849+
1850+ echo /dev/hda2 > /sys/power/suspend2/swapwriter/swapfile
1851+
1852+ /dev/hda2 would then be automatically swapon'd and swapoff'd. Note that the
1853+ swapon and swapoff occur while other processes are frozen (including kswapd)
1854+ so this swap file will not be used up when attempting to free memory. The
1855+ parition/file is also given the highest priority, so other swapfiles/partitions
1856+ will only be used to save the image when this one is filled.
1857+
1858+ The value of this file is used by headerlocations along with any currently
1859+ activated swapfiles/partitions.
1860+
1861+ - swapwriter/headerlocations:
1862+
1863+ This option tells you the resume2= options to use for swap devices you
1864+ currently have activated. It is particularly useful when you only want to
1865+ use a swap file to store your image. See above for further details.
1866+
1867+ - toggle_process_nofreeze
1868+
1869+ This entry can be used to toggle the NOFREEZE flag on a process, to allow it
1870+ to run during Suspending. It should be used with extreme caution. There are
1871+ strict limitations on what a process running during suspend can do. This is
1872+ really only intended for use by Suspend's helpers (userui in particular).
1873+
1874+ - userui_program
1875+
1876+ This entry is used to tell Suspend what userspace program to use for
1877+ providing a user interface while suspending. The program uses a netlink
1878+ socket to pass messages back and forward to the kernel, allowing all of the
1879+ functions formerly implemented in the kernel user interface components.
1880+
1881+ - user_interface/debug_sections (CONFIG_PM_DEBUG):
1882+
1883+ This value, together with the console log level, controls what debugging
1884+ information is displayed. The console log level determines the level of
1885+ detail, and this value determines what detail is displayed. This value is
1886+ a bit vector, and the meaning of the bits can be found in the kernel tree
1887+ in include/linux/suspend2.h. It can be overridden using the kernel's
1888+ command line option suspend_dbg.
1889+
1890+ - user_interface/default_console_level (CONFIG_PM_DEBUG):
1891+
1892+ This determines the value of the console log level at the start of a
1893+ suspend cycle. If debugging is compiled in, the console log level can be
1894+ changed during a cycle by pressing the digit keys. Meanings are:
1895+
1896+ 0: Nice display.
1897+ 1: Nice display plus numerical progress.
1898+ 2: Errors only.
1899+ 3: Low level debugging info.
1900+ 4: Medium level debugging info.
1901+ 5: High level debugging info.
1902+ 6: Verbose debugging info.
1903+
1904+ - user_interface/enable_escape:
1905+
1906+ Setting this to "1" will enable you abort a suspend by
1907+ pressing escape, "0" (default) disables this feature. Note that enabling
1908+ this option means that you cannot initiate a suspend and then walk away
1909+ from your computer, expecting it to be secure. With feature disabled,
1910+ you can validly have this expectation once Suspend begins to write the
1911+ image to disk. (Prior to this point, it is possible that Suspend might
1912+ about because of failure to freeze all processes or because constraints
1913+ on its ability to save the image are not met).
1914+
1915+ - version:
1916+
1917+ The version of suspend you have compiled into the currently running kernel.
1918+
1919+7. How do you get support?
1920+
1921+ Glad you asked. Suspend2 is being actively maintained and supported
1922+ by Nigel (the guy doing most of the kernel coding at the moment), Bernard
1923+ (who maintains the hibernate script and userspace user interface components)
1924+ and its users.
1925+
1926+ Resources availble include HowTos, FAQs and a Wiki, all available via
1927+ suspend2.net. You can find the mailing lists there.
1928+
1929+8. I think I've found a bug. What should I do?
1930+
1931+ By far and a way, the most common problems people have with suspend2
1932+ related to drivers not having adequate power management support. In this
1933+ case, it is not a bug with suspend2, but we can still help you. As we
1934+ mentioned above, such issues can usually be worked around by building the
1935+ functionality as modules and unloading them while suspending. Please visit
1936+ the Wiki for up-to-date lists of known issues and work arounds.
1937+
1938+ If this information doesn't help, try running:
1939+
1940+ hibernate --bug-report
1941+
1942+ ..and sending the output to the users mailing list.
1943+
1944+ Good information on how to provide us with useful information from an
1945+ oops is found in the file REPORTING-BUGS, in the top level directory
1946+ of the kernel tree. If you get an oops, please especially note the
1947+ information about running what is printed on the screen through ksymoops.
1948+ The raw information is useless.
1949+
1950+9. When will XXX be supported?
1951+
1952+ If there's a feature missing from Suspend2 that you'd like, feel free to
1953+ ask. We try to be obliging, within reason.
1954+
1955+ Patches are welcome. Please send to the list.
1956+
1957+10. How does it work?
1958+
1959+ Suspend2 does its work in a number of steps.
1960+
1961+ a. Freezing system activity.
1962+
1963+ The first main stage in suspending is to stop all other activity. This is
1964+ achieved in stages. Processes are considered in fours groups, which we will
1965+ describe in reverse order for clarity's sake: Threads with the PF_NOFREEZE
1966+ flag, kernel threads without this flag, userspace processes with the
1967+ PF_SYNCTHREAD flag and all other processes. The first set (PF_NOFREEZE) are
1968+ untouched by the refrigerator code. They are allowed to run during suspending
1969+ and resuming, and are used to support user interaction, storage access or the
1970+ like. Other kernel threads (those unneeded while suspending) are frozen last.
1971+ This leaves us with userspace processes that need to be frozen. When a
1972+ process enters one of the *_sync system calls, we set a PF_SYNCTHREAD flag on
1973+ that process for the duration of that call. Processes that have this flag are
1974+ frozen after processes without it, so that we can seek to ensure that dirty
1975+ data is synced to disk as quickly as possible in a situation where other
1976+ processes may be submitting writes at the same time. Freezing the processes
1977+ that are submitting data stops new I/O from being submitted. Syncthreads can
1978+ then cleanly finish their work. So the order is:
1979+
1980+ - Userspace processes without PF_SYNCTHREAD or PF_NOFREEZE;
1981+ - Userspace processes with PF_SYNCTHREAD (they won't have NOFREEZE);
1982+ - Kernel processes without PF_NOFREEZE.
1983+
1984+ b. Eating memory.
1985+
1986+ For a successful suspend, you need to have enough disk space to store the
1987+ image and enough memory for the various limitations of Suspend2's
1988+ algorithm. You can also specify a maximum image size. In order to attain
1989+ to those constraints, Suspend2 may 'eat' memory. If, after freezing
1990+ processes, the constraints aren't met, Suspend2 will thaw all the
1991+ other processes and begin to eat memory until its calculations indicate
1992+ the constraints are met. It will then freeze processes again and recheck
1993+ its calculations.
1994+
1995+ c. Allocation of storage.
1996+
1997+ Next, Suspend2 allocates the storage that will be used to save
1998+ the image.
1999+
2000+ The core of Suspend2 knows nothing about how or where pages are stored. We
2001+ therefore request the active writer (remember you might have compiled in
2002+ more than one!) to allocate enough storage for our expect image size. If
2003+ this request cannot be fulfilled, we eat more memory and try again. If it
2004+ is fulfiled, we seek to allocate additional storage, just in case our
2005+ expected compression ratio (if any) isn't achieved. This time, however, we
2006+ just continue if we can't allocate enough storage.
2007+
2008+ If these calls to our writer change the characteristics of the image such
2009+ that we haven't allocated enough memory, we also loop. (The writer may well
2010+ need to allocate space for its storage information).
2011+
2012+ d. Write the first part of the image.
2013+
2014+ Suspend2 stores the image in two sets of pages called 'pagesets'.
2015+ Pageset 2 contains pages on the active and inactive lists; essentially
2016+ the page cache. Pageset 1 contains all other pages, including the kernel.
2017+ We use two pagesets for one important reason: We need to make an atomic copy
2018+ of the kernel to ensure consistency of the image. Without a second pageset,
2019+ that would limit us to an image that was at most half the amount of memory
2020+ available. Using two pagesets allows us to store a full image. Since pageset
2021+ 2 pages won't be needed in saving pageset 1, we first save pageset 2 pages.
2022+ We can then make our atomic copy of the remaining pages using both pageset 2
2023+ pages and any other pages that are free. While saving both pagesets, we are
2024+ careful not to corrupt the image. Among other things, we use lowlevel block
2025+ I/O routines that don't change the pagecache contents.
2026+
2027+ The next step, then, is writing pageset 2.
2028+
2029+ e. Suspending drivers and storing processor context.
2030+
2031+ Having written pageset2, Suspend2 calls the power management functions to
2032+ notify drivers of the suspend, and saves the processor state in preparation
2033+ for the atomic copy of memory we are about to make.
2034+
2035+ f. Atomic copy.
2036+
2037+ At this stage, everything else but the Suspend2 code is halted. Processes
2038+ are frozen or idling, drivers are quiesced and have stored (ideally and where
2039+ necessary) their configuration in memory we are about to atomically copy.
2040+ In our lowlevel architecture specific code, we have saved the CPU state.
2041+ We can therefore now do our atomic copy before resuming drivers etc.
2042+
2043+ g. Save the atomic copy (pageset 1).
2044+
2045+ Suspend can then write the atomic copy of the remaining pages. Since we
2046+ have copied the pages into other locations, we can continue to use the
2047+ normal block I/O routines without fear of corruption our image.
2048+
2049+ f. Save the suspend header.
2050+
2051+ Nearly there! We save our settings and other parameters needed for
2052+ reloading pageset 1 in a 'suspend header'. We also tell our writer to
2053+ serialise its data at this stage, so that it can reread the image at resume
2054+ time. Note that the writer can write this data in any format - in the case
2055+ of the swapwriter, for example, it splits header pages in 4092 byte blocks,
2056+ using the last four bytes to link pages of data together. This is completely
2057+ transparent to the core.
2058+
2059+ g. Set the image header.
2060+
2061+ Finally, we edit the header at our resume2= location. The signature is
2062+ changed by the writer to reflect the fact that an image exists, and to point
2063+ to the start of that data if necessary (swapwriter).
2064+
2065+ h. Power down.
2066+
2067+ Or reboot if we're debugging and the appropriate option is selected.
2068+
2069+ Whew!
2070+
2071+ Reloading the image.
2072+ --------------------
2073+
2074+ Reloading the image is essentially the reverse of all the above. We load
2075+ our copy of pageset 1, being careful to choose locations that aren't going
2076+ to be overwritten as we copy it back (We start very early in the boot
2077+ process, so there are no other processes to quiesce here). We then copy
2078+ pageset 1 back to its original location in memory and restore the process
2079+ context. We are now running with the original kernel. Next, we reload the
2080+ pageset 2 pages, free the memory and swap used by Suspend2, restore
2081+ the pageset header and restart processes. Sounds easy in comparison to
2082+ suspending, doesn't it!
2083+
2084+ There is of course more to Suspend2 than this, but this explanation
2085+ should be a good start. If there's interest, I'll write further
2086+ documentation on range pages and the low level I/O.
2087+
2088+11. Who wrote Suspend2?
2089+
2090+ (Answer based on the writings of Florent Chabaud, credits in files and
2091+ Nigel's limited knowledge; apologies to anyone missed out!)
2092+
2093+ The main developers of Suspend2 have been...
2094+
2095+ Gabor Kuti
2096+ Pavel Machek
2097+ Florent Chabaud
2098+ Bernard Blackham
2099+ Nigel Cunningham
2100+
2101+ They have been aided in their efforts by a host of hundreds, if not thousands
2102+ of testers and people who have submitted bug fixes & suggestions. Of special
2103+ note are the efforts of Michael Frank, who had his computers repetitively
2104+ suspend and resume for literally tens of thousands of cycles and developed
2105+ scripts to stress the system and test Suspend2 far beyond the point
2106+ most of us (Nigel included!) would consider testing. His efforts have
2107+ contributed as much to Suspend2 as any of the names above.
2108diff --git a/MAINTAINERS b/MAINTAINERS
2109index a5508f9..9f58d1e 100644
2110--- a/MAINTAINERS
2111+++ b/MAINTAINERS
2112@@ -2895,6 +2895,13 @@ L: sun3-list@redhat.com
2113 W: http://sammy.net/sun3/
2114 S: Maintained
2115
2116+SUSPEND2
2117+P: Nigel Cunningham
2118+M: nigel@suspend2.net
2119+L: suspend2-devel@suspend2.net
2120+W: http://suspend2.net
2121+S: Maintained
2122+
2123 SVGA HANDLING
2124 P: Martin Mares
2125 M: mj@ucw.cz
2126diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
2127index 48cf7ff..f38a60a 100644
2128--- a/arch/arm/kernel/signal.c
2129+++ b/arch/arm/kernel/signal.c
2130@@ -11,6 +11,7 @@ #include <linux/errno.h>
2131 #include <linux/signal.h>
2132 #include <linux/ptrace.h>
2133 #include <linux/personality.h>
2134+#include <linux/freezer.h>
2135
2136 #include <asm/cacheflush.h>
2137 #include <asm/ucontext.h>
2138diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
2139index 3309665..0ec1485 100644
2140--- a/arch/avr32/kernel/signal.c
2141+++ b/arch/avr32/kernel/signal.c
2142@@ -15,7 +15,7 @@ #include <linux/mm.h>
2143 #include <linux/errno.h>
2144 #include <linux/ptrace.h>
2145 #include <linux/unistd.h>
2146-#include <linux/suspend.h>
2147+#include <linux/freezer.h>
2148
2149 #include <asm/uaccess.h>
2150 #include <asm/ucontext.h>
2151diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
2152index b8a5882..85baeae 100644
2153--- a/arch/frv/kernel/signal.c
2154+++ b/arch/frv/kernel/signal.c
2155@@ -21,7 +21,7 @@ #include <linux/wait.h>
2156 #include <linux/ptrace.h>
2157 #include <linux/unistd.h>
2158 #include <linux/personality.h>
2159-#include <linux/suspend.h>
2160+#include <linux/freezer.h>
2161 #include <asm/ucontext.h>
2162 #include <asm/uaccess.h>
2163 #include <asm/cacheflush.h>
2164diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
2165index 7787f70..0295560 100644
2166--- a/arch/h8300/kernel/signal.c
2167+++ b/arch/h8300/kernel/signal.c
2168@@ -38,7 +38,7 @@ #include <linux/highuid.h>
2169 #include <linux/personality.h>
2170 #include <linux/tty.h>
2171 #include <linux/binfmts.h>
2172-#include <linux/suspend.h>
2173+#include <linux/freezer.h>
2174
2175 #include <asm/setup.h>
2176 #include <asm/uaccess.h>
2177diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
2178index 3b7a63e..44c5a32 100644
2179--- a/arch/i386/kernel/io_apic.c
2180+++ b/arch/i386/kernel/io_apic.c
2181@@ -34,6 +34,7 @@ #include <linux/sysdev.h>
2182 #include <linux/pci.h>
2183 #include <linux/msi.h>
2184 #include <linux/htirq.h>
2185+#include <linux/freezer.h>
2186
2187 #include <asm/io.h>
2188 #include <asm/smp.h>
2189diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
2190index 1674161..42fa731 100644
2191--- a/arch/i386/mm/init.c
2192+++ b/arch/i386/mm/init.c
2193@@ -385,7 +385,7 @@ #ifdef CONFIG_X86_PAE
2194 #endif
2195 }
2196
2197-#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
2198+#if defined(CONFIG_SUSPEND_SHARED) || defined(CONFIG_ACPI_SLEEP)
2199 /*
2200 * Swap suspend & friends need this for resume because things like the intel-agp
2201 * driver might have split up a kernel 4MB mapping.
2202diff --git a/arch/i386/power/Makefile b/arch/i386/power/Makefile
2203index 8cfa4e8..7f4efb1 100644
2204--- a/arch/i386/power/Makefile
2205+++ b/arch/i386/power/Makefile
2206@@ -1,2 +1,2 @@
2207 obj-$(CONFIG_PM) += cpu.o
2208-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
2209+obj-$(CONFIG_SUSPEND_SHARED) += swsusp.o
2210diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
2211index b60cea4..092ea86 100644
2212--- a/arch/m32r/kernel/signal.c
2213+++ b/arch/m32r/kernel/signal.c
2214@@ -21,7 +21,7 @@ #include <linux/wait.h>
2215 #include <linux/unistd.h>
2216 #include <linux/stddef.h>
2217 #include <linux/personality.h>
2218-#include <linux/suspend.h>
2219+#include <linux/freezer.h>
2220 #include <asm/cacheflush.h>
2221 #include <asm/ucontext.h>
2222 #include <asm/uaccess.h>
2223diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
2224index 7af23c4..4d53d0f 100644
2225--- a/arch/powerpc/kernel/Makefile
2226+++ b/arch/powerpc/kernel/Makefile
2227@@ -36,7 +36,7 @@ obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvr
2228 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
2229 obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
2230 obj-$(CONFIG_TAU) += tau_6xx.o
2231-obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
2232+obj32-$(CONFIG_SUSPEND_SHARED) += swsusp_32.o
2233 obj32-$(CONFIG_MODULES) += module_32.o
2234
2235 ifeq ($(CONFIG_PPC_MERGE),y)
2236diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
2237index 320353f..e4ebe1a 100644
2238--- a/arch/powerpc/kernel/signal_32.c
2239+++ b/arch/powerpc/kernel/signal_32.c
2240@@ -36,7 +36,7 @@ #include <linux/unistd.h>
2241 #include <linux/stddef.h>
2242 #include <linux/tty.h>
2243 #include <linux/binfmts.h>
2244-#include <linux/suspend.h>
2245+#include <linux/freezer.h>
2246 #endif
2247
2248 #include <asm/uaccess.h>
2249diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
2250index 5213f5b..380249a 100644
2251--- a/arch/sh/kernel/signal.c
2252+++ b/arch/sh/kernel/signal.c
2253@@ -23,6 +23,7 @@ #include <linux/tty.h>
2254 #include <linux/elf.h>
2255 #include <linux/personality.h>
2256 #include <linux/binfmts.h>
2257+#include <linux/freezer.h>
2258
2259 #include <asm/ucontext.h>
2260 #include <asm/uaccess.h>
2261diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
2262index 9e2ffc4..1666d3e 100644
2263--- a/arch/sh64/kernel/signal.c
2264+++ b/arch/sh64/kernel/signal.c
2265@@ -22,7 +22,7 @@ #include <linux/signal.h>
2266 #include <linux/errno.h>
2267 #include <linux/wait.h>
2268 #include <linux/personality.h>
2269-#include <linux/suspend.h>
2270+#include <linux/freezer.h>
2271 #include <linux/ptrace.h>
2272 #include <linux/unistd.h>
2273 #include <linux/stddef.h>
2274diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
2275index 3c7cbff..3cb3c7b 100644
2276--- a/arch/x86_64/kernel/Makefile
2277+++ b/arch/x86_64/kernel/Makefile
2278@@ -26,7 +26,7 @@ obj-y += io_apic.o mpparse.o \
2279 obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
2280 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
2281 obj-$(CONFIG_PM) += suspend.o
2282-obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o
2283+obj-$(CONFIG_SUSPEND_SHARED) += suspend_asm.o
2284 obj-$(CONFIG_CPU_FREQ) += cpufreq/
2285 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
2286 obj-$(CONFIG_IOMMU) += pci-gart.o aperture.o
2287diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
2288index 91f7e67..983f16f 100644
2289--- a/arch/x86_64/kernel/suspend.c
2290+++ b/arch/x86_64/kernel/suspend.c
2291@@ -140,7 +140,7 @@ void fix_processor_context(void)
2292
2293 }
2294
2295-#ifdef CONFIG_SOFTWARE_SUSPEND
2296+#ifdef CONFIG_SUSPEND_SHARED
2297 /* Defined in arch/x86_64/kernel/suspend_asm.S */
2298 extern int restore_image(void);
2299
2300@@ -219,4 +219,4 @@ int swsusp_arch_resume(void)
2301 restore_image();
2302 return 0;
2303 }
2304-#endif /* CONFIG_SOFTWARE_SUSPEND */
2305+#endif /* CONFIG_SUSPEND_SHARED */
2306diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
2307index e3ef544..e1c72af 100644
2308--- a/arch/x86_64/kernel/time.c
2309+++ b/arch/x86_64/kernel/time.c
2310@@ -1053,9 +1053,9 @@ #ifdef CONFIG_X86_PM_TIMER
2311 #endif
2312 } else
2313 vxtime.last_tsc = get_cycles_sync();
2314- write_sequnlock_irqrestore(&xtime_lock,flags);
2315 jiffies += sleep_length;
2316 monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
2317+ write_sequnlock_irqrestore(&xtime_lock,flags);
2318 touch_softlockup_watchdog();
2319 return 0;
2320 }
2321diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
2322index 9eaee66..e00692a 100644
2323--- a/block/ll_rw_blk.c
2324+++ b/block/ll_rw_blk.c
2325@@ -28,6 +28,8 @@ #include <linux/writeback.h>
2326 #include <linux/interrupt.h>
2327 #include <linux/cpu.h>
2328 #include <linux/blktrace_api.h>
2329+#include <linux/freezer.h>
2330+#include <linux/suspend.h>
2331
2332 /*
2333 * for max sense size
2334@@ -3124,6 +3126,10 @@ void submit_bio(int rw, struct bio *bio)
2335 bdevname(bio->bi_bdev,b));
2336 }
2337
2338+ BUG_ON( test_suspend_state(SUSPEND_RUNNING) && /* Suspend2, that is */
2339+ freezer_is_on() &&
2340+ !(bio->bi_flags & (1 << BIO_SUSPEND_DATA)));
2341+
2342 generic_make_request(bio);
2343 }
2344
2345diff --git a/crypto/Kconfig b/crypto/Kconfig
2346index cbae839..6abd015 100644
2347--- a/crypto/Kconfig
2348+++ b/crypto/Kconfig
2349@@ -405,6 +405,13 @@ config CRYPTO_DEFLATE
2350
2351 You will most probably want this if using IPSec.
2352
2353+config CRYPTO_LZF
2354+ tristate "LZF compression algorithm"
2355+ select CRYPTO_ALGAPI
2356+ help
2357+ This is the LZF algorithm. It is especially useful for Suspend2,
2358+ because it achieves good compression quickly.
2359+
2360 config CRYPTO_MICHAEL_MIC
2361 tristate "Michael MIC keyed digest algorithm"
2362 select CRYPTO_ALGAPI
2363diff --git a/crypto/Makefile b/crypto/Makefile
2364index 7236620..212eb1a 100644
2365--- a/crypto/Makefile
2366+++ b/crypto/Makefile
2367@@ -40,5 +40,6 @@ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
2368 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
2369 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
2370 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
2371+obj-$(CONFIG_CRYPTO_LZF) += lzf.o
2372
2373 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
2374diff --git a/crypto/lzf.c b/crypto/lzf.c
2375new file mode 100644
2376index 0000000..2da44d9
2377--- /dev/null
2378+++ b/crypto/lzf.c
2379@@ -0,0 +1,335 @@
2380+/*
2381+ * Cryptoapi LZF compression module.
2382+ *
2383+ * Copyright (c) 2004-2005 Nigel Cunningham <nigel@suspend2.net>
2384+ *
2385+ * based on the deflate.c file:
2386+ *
2387+ * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
2388+ *
2389+ * and upon the LZF compression module donated to the Suspend2 project with
2390+ * the following copyright:
2391+ *
2392+ * This program is free software; you can redistribute it and/or modify it
2393+ * under the terms of the GNU General Public License as published by the Free
2394+ * Software Foundation; either version 2 of the License, or (at your option)
2395+ * any later version.
2396+ * Copyright (c) 2000-2003 Marc Alexander Lehmann <pcg@goof.com>
2397+ *
2398+ * Redistribution and use in source and binary forms, with or without modifica-
2399+ * tion, are permitted provided that the following conditions are met:
2400+ *
2401+ * 1. Redistributions of source code must retain the above copyright notice,
2402+ * this list of conditions and the following disclaimer.
2403+ *
2404+ * 2. Redistributions in binary form must reproduce the above copyright
2405+ * notice, this list of conditions and the following disclaimer in the
2406+ * documentation and/or other materials provided with the distribution.
2407+ *
2408+ * 3. The name of the author may not be used to endorse or promote products
2409+ * derived from this software without specific prior written permission.
2410+ *
2411+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
2412+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
2413+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
2414+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
2415+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2416+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2417+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2418+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
2419+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2420+ * OF THE POSSIBILITY OF SUCH DAMAGE.
2421+ *
2422+ * Alternatively, the contents of this file may be used under the terms of
2423+ * the GNU General Public License version 2 (the "GPL"), in which case the
2424+ * provisions of the GPL are applicable instead of the above. If you wish to
2425+ * allow the use of your version of this file only under the terms of the
2426+ * GPL and not to allow others to use your version of this file under the
2427+ * BSD license, indicate your decision by deleting the provisions above and
2428+ * replace them with the notice and other provisions required by the GPL. If
2429+ * you do not delete the provisions above, a recipient may use your version
2430+ * of this file under either the BSD or the GPL.
2431+ */
2432+
2433+#include <linux/kernel.h>
2434+#include <linux/module.h>
2435+#include <linux/init.h>
2436+#include <linux/module.h>
2437+#include <linux/crypto.h>
2438+#include <linux/err.h>
2439+#include <linux/vmalloc.h>
2440+#include <asm/string.h>
2441+
2442+struct lzf_ctx {
2443+ void *hbuf;
2444+ unsigned int bufofs;
2445+};
2446+
2447+/*
2448+ * size of hashtable is (1 << hlog) * sizeof (char *)
2449+ * decompression is independent of the hash table size
2450+ * the difference between 15 and 14 is very small
2451+ * for small blocks (and 14 is also faster).
2452+ * For a low-memory configuration, use hlog == 13;
2453+ * For best compression, use 15 or 16.
2454+ */
2455+static const int hlog = 14;
2456+
2457+/*
2458+ * don't play with this unless you benchmark!
2459+ * decompression is not dependent on the hash function
2460+ * the hashing function might seem strange, just believe me
2461+ * it works ;)
2462+ */
2463+static inline u16 first(const u8 *p)
2464+{
2465+ return ((p[0]) << 8) + p[1];
2466+}
2467+
2468+static inline u16 next(u8 v, const u8 *p)
2469+{
2470+ return ((v) << 8) + p[2];
2471+}
2472+
2473+static inline u32 idx(unsigned int h)
2474+{
2475+ return (((h ^ (h << 5)) >> (3*8 - hlog)) + h*3) & ((1 << hlog) - 1);
2476+}
2477+
2478+/*
2479+ * IDX works because it is very similar to a multiplicative hash, e.g.
2480+ * (h * 57321 >> (3*8 - hlog))
2481+ * the next one is also quite good, albeit slow ;)
2482+ * (int)(cos(h & 0xffffff) * 1e6)
2483+ */
2484+
2485+static const int max_lit = (1 << 5);
2486+static const int max_off = (1 << 13);
2487+static const int max_ref = ((1 << 8) + (1 << 3));
2488+
2489+/*
2490+ * compressed format
2491+ *
2492+ * 000LLLLL <L+1> ; literal
2493+ * LLLOOOOO oooooooo ; backref L
2494+ * 111OOOOO LLLLLLLL oooooooo ; backref L+7
2495+ *
2496+ */
2497+
2498+static void lzf_compress_exit(struct crypto_tfm *tfm)
2499+{
2500+ struct lzf_ctx *ctx = crypto_tfm_ctx(tfm);
2501+
2502+ if (ctx->hbuf) {
2503+ vfree(ctx->hbuf);
2504+ ctx->hbuf = NULL;
2505+ }
2506+}
2507+
2508+static int lzf_compress_init(struct crypto_tfm *tfm)
2509+{
2510+ struct lzf_ctx *ctx = crypto_tfm_ctx(tfm);
2511+
2512+ /* Get LZF ready to go */
2513+ ctx->hbuf = vmalloc_32((1 << hlog) * sizeof(char *));
2514+ if (!ctx->hbuf) {
2515+ printk(KERN_WARNING
2516+ "Failed to allocate %ld bytes for lzf workspace\n",
2517+ (long) ((1 << hlog) * sizeof(char *)));
2518+ return -ENOMEM;
2519+ }
2520+ return 0;
2521+}
2522+
2523+static int lzf_compress(struct crypto_tfm *tfm, const u8 *in_data,
2524+ unsigned int in_len, u8 *out_data, unsigned int *out_len)
2525+{
2526+ struct lzf_ctx *ctx = crypto_tfm_ctx(tfm);
2527+ const u8 **htab = ctx->hbuf;
2528+ const u8 **hslot;
2529+ const u8 *ip = in_data;
2530+ u8 *op = out_data;
2531+ const u8 *in_end = ip + in_len;
2532+ u8 *out_end = op + *out_len - 3;
2533+ const u8 *ref;
2534+
2535+ unsigned int hval = first(ip);
2536+ unsigned long off;
2537+ int lit = 0;
2538+
2539+ memset(htab, 0, sizeof(htab));
2540+
2541+ for (;;) {
2542+ if (ip < in_end - 2) {
2543+ hval = next(hval, ip);
2544+ hslot = htab + idx(hval);
2545+ ref = *hslot;
2546+ *hslot = ip;
2547+
2548+ if ((off = ip - ref - 1) < max_off
2549+ && ip + 4 < in_end && ref > in_data
2550+ && *(u16 *) ref == *(u16 *) ip && ref[2] == ip[2]
2551+ ) {
2552+ /* match found at *ref++ */
2553+ unsigned int len = 2;
2554+ unsigned int maxlen = in_end - ip - len;
2555+ maxlen = maxlen > max_ref ? max_ref : maxlen;
2556+
2557+ do
2558+ len++;
2559+ while (len < maxlen && ref[len] == ip[len]);
2560+
2561+ if (op + lit + 1 + 3 >= out_end) {
2562+ *out_len = PAGE_SIZE;
2563+ return 0;
2564+ }
2565+
2566+ if (lit) {
2567+ *op++ = lit - 1;
2568+ lit = -lit;
2569+ do
2570+ *op++ = ip[lit];
2571+ while (++lit);
2572+ }
2573+
2574+ len -= 2;
2575+ ip++;
2576+
2577+ if (len < 7) {
2578+ *op++ = (off >> 8) + (len << 5);
2579+ } else {
2580+ *op++ = (off >> 8) + (7 << 5);
2581+ *op++ = len - 7;
2582+ }
2583+
2584+ *op++ = off;
2585+
2586+ ip += len;
2587+ hval = first(ip);
2588+ hval = next(hval, ip);
2589+ htab[idx(hval)] = ip;
2590+ ip++;
2591+ continue;
2592+ }
2593+ } else if (ip == in_end)
2594+ break;
2595+
2596+ /* one more literal byte we must copy */
2597+ lit++;
2598+ ip++;
2599+
2600+ if (lit == max_lit) {
2601+ if (op + 1 + max_lit >= out_end) {
2602+ *out_len = PAGE_SIZE;
2603+ return 0;
2604+ }
2605+
2606+ *op++ = max_lit - 1;
2607+ memcpy(op, ip - max_lit, max_lit);
2608+ op += max_lit;
2609+ lit = 0;
2610+ }
2611+ }
2612+
2613+ if (lit) {
2614+ if (op + lit + 1 >= out_end) {
2615+ *out_len = PAGE_SIZE;
2616+ return 0;
2617+ }
2618+
2619+ *op++ = lit - 1;
2620+ lit = -lit;
2621+ do
2622+ *op++ = ip[lit];
2623+ while (++lit);
2624+ }
2625+
2626+ *out_len = op - out_data;
2627+ return 0;
2628+}
2629+
2630+static int lzf_decompress(struct crypto_tfm *tfm, const u8 *src,
2631+ unsigned int slen, u8 *dst, unsigned int *dlen)
2632+{
2633+ u8 const *ip = src;
2634+ u8 *op = dst;
2635+ u8 const *const in_end = ip + slen;
2636+ u8 *const out_end = op + *dlen;
2637+
2638+ do {
2639+ unsigned int ctrl = *ip++;
2640+
2641+ if (ctrl < (1 << 5)) { /* literal run */
2642+ ctrl++;
2643+
2644+ if (op + ctrl > out_end) {
2645+ *dlen = PAGE_SIZE;
2646+ return 0;
2647+ }
2648+ memcpy(op, ip, ctrl);
2649+ op += ctrl;
2650+ ip += ctrl;
2651+ } else { /* back reference */
2652+
2653+ unsigned int len = ctrl >> 5;
2654+
2655+ u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;
2656+
2657+ if (len == 7)
2658+ len += *ip++;
2659+
2660+ ref -= *ip++;
2661+
2662+ if (op + len + 2 > out_end) {
2663+ *dlen = PAGE_SIZE;
2664+ return 0;
2665+ }
2666+
2667+ if (ref < (u8 *) dst) {
2668+ *dlen = PAGE_SIZE;
2669+ return 0;
2670+ }
2671+
2672+ *op++ = *ref++;
2673+ *op++ = *ref++;
2674+
2675+ do
2676+ *op++ = *ref++;
2677+ while (--len);
2678+ }
2679+ }
2680+ while (op < out_end && ip < in_end);
2681+
2682+ *dlen = op - (u8 *) dst;
2683+ return 0;
2684+}
2685+
2686+static struct crypto_alg alg = {
2687+ .cra_name = "lzf",
2688+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
2689+ .cra_ctxsize = 0,
2690+ .cra_module = THIS_MODULE,
2691+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
2692+ .cra_init = lzf_compress_init,
2693+ .cra_exit = lzf_compress_exit,
2694+ .cra_u = { .compress = {
2695+ .coa_compress = lzf_compress,
2696+ .coa_decompress = lzf_decompress } }
2697+};
2698+
2699+static int __init init(void)
2700+{
2701+ return crypto_register_alg(&alg);
2702+}
2703+
2704+static void __exit fini(void)
2705+{
2706+ crypto_unregister_alg(&alg);
2707+}
2708+
2709+module_init(init);
2710+module_exit(fini);
2711+
2712+MODULE_LICENSE("GPL");
2713+MODULE_DESCRIPTION("LZF Compression Algorithm");
2714+MODULE_AUTHOR("Marc Alexander Lehmann & Nigel Cunningham");
2715diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
2716index f2904f6..e45eaa2 100644
2717--- a/drivers/block/pktcdvd.c
2718+++ b/drivers/block/pktcdvd.c
2719@@ -54,7 +54,7 @@ #include <linux/file.h>
2720 #include <linux/proc_fs.h>
2721 #include <linux/seq_file.h>
2722 #include <linux/miscdevice.h>
2723-#include <linux/suspend.h>
2724+#include <linux/freezer.h>
2725 #include <linux/mutex.h>
2726 #include <scsi/scsi_cmnd.h>
2727 #include <scsi/scsi_ioctl.h>
2728diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
2729index 9902ffa..cc2cd46 100644
2730--- a/drivers/char/hvc_console.c
2731+++ b/drivers/char/hvc_console.c
2732@@ -38,6 +38,7 @@ #include <linux/tty_flip.h>
2733 #include <linux/sched.h>
2734 #include <linux/spinlock.h>
2735 #include <linux/delay.h>
2736+#include <linux/freezer.h>
2737
2738 #include <asm/uaccess.h>
2739
2740diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
2741index 75e9e38..1b4fc92 100644
2742--- a/drivers/edac/edac_mc.c
2743+++ b/drivers/edac/edac_mc.c
2744@@ -28,6 +28,7 @@ #include <linux/list.h>
2745 #include <linux/sysdev.h>
2746 #include <linux/ctype.h>
2747 #include <linux/kthread.h>
2748+#include <linux/freezer.h>
2749 #include <asm/uaccess.h>
2750 #include <asm/page.h>
2751 #include <asm/edac.h>
2752diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
2753index 8e7b83f..e829c93 100644
2754--- a/drivers/ieee1394/nodemgr.c
2755+++ b/drivers/ieee1394/nodemgr.c
2756@@ -15,6 +15,7 @@ #include <linux/slab.h>
2757 #include <linux/delay.h>
2758 #include <linux/kthread.h>
2759 #include <linux/moduleparam.h>
2760+#include <linux/freezer.h>
2761 #include <asm/atomic.h>
2762
2763 #include "csr.h"
2764diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
2765index a0af97e..79dfb4b 100644
2766--- a/drivers/input/gameport/gameport.c
2767+++ b/drivers/input/gameport/gameport.c
2768@@ -23,6 +23,7 @@ #include <linux/delay.h>
2769 #include <linux/kthread.h>
2770 #include <linux/sched.h> /* HZ */
2771 #include <linux/mutex.h>
2772+#include <linux/freezer.h>
2773
2774 /*#include <asm/io.h>*/
2775
2776diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
2777index 211943f..5f1d403 100644
2778--- a/drivers/input/serio/serio.c
2779+++ b/drivers/input/serio/serio.c
2780@@ -35,6 +35,7 @@ #include <linux/sched.h>
2781 #include <linux/slab.h>
2782 #include <linux/kthread.h>
2783 #include <linux/mutex.h>
2784+#include <linux/freezer.h>
2785
2786 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
2787 MODULE_DESCRIPTION("Serio abstraction core");
2788diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
2789index a0f30d0..9397b08 100644
2790--- a/drivers/macintosh/therm_adt746x.c
2791+++ b/drivers/macintosh/therm_adt746x.c
2792@@ -24,6 +24,7 @@ #include <linux/wait.h>
2793 #include <linux/suspend.h>
2794 #include <linux/kthread.h>
2795 #include <linux/moduleparam.h>
2796+#include <linux/freezer.h>
2797
2798 #include <asm/prom.h>
2799 #include <asm/machdep.h>
2800diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
2801index e63ea1c..c8558d4 100644
2802--- a/drivers/macintosh/via-pmu.c
2803+++ b/drivers/macintosh/via-pmu.c
2804@@ -42,7 +42,7 @@ #include <linux/init.h>
2805 #include <linux/interrupt.h>
2806 #include <linux/device.h>
2807 #include <linux/sysdev.h>
2808-#include <linux/suspend.h>
2809+#include <linux/freezer.h>
2810 #include <linux/syscalls.h>
2811 #include <linux/cpu.h>
2812 #include <asm/prom.h>
2813diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
2814index ab3faa7..e947af9 100644
2815--- a/drivers/macintosh/windfarm_core.c
2816+++ b/drivers/macintosh/windfarm_core.c
2817@@ -34,6 +34,7 @@ #include <linux/reboot.h>
2818 #include <linux/device.h>
2819 #include <linux/platform_device.h>
2820 #include <linux/mutex.h>
2821+#include <linux/freezer.h>
2822
2823 #include <asm/prom.h>
2824
2825diff --git a/drivers/md/md.c b/drivers/md/md.c
2826index 8cbf9c9..6c4345b 100644
2827--- a/drivers/md/md.c
2828+++ b/drivers/md/md.c
2829@@ -39,10 +39,10 @@ #include <linux/raid/md.h>
2830 #include <linux/raid/bitmap.h>
2831 #include <linux/sysctl.h>
2832 #include <linux/buffer_head.h> /* for invalidate_bdev */
2833-#include <linux/suspend.h>
2834 #include <linux/poll.h>
2835 #include <linux/mutex.h>
2836 #include <linux/ctype.h>
2837+#include <linux/freezer.h>
2838
2839 #include <linux/init.h>
2840
2841diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
2842index 53304e6..0fefdf0 100644
2843--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
2844+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
2845@@ -34,7 +34,7 @@ #include <linux/poll.h>
2846 #include <linux/module.h>
2847 #include <linux/moduleparam.h>
2848 #include <linux/list.h>
2849-#include <linux/suspend.h>
2850+#include <linux/freezer.h>
2851 #include <linux/jiffies.h>
2852 #include <asm/processor.h>
2853
2854diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
2855index cf43df3..e1b56dc 100644
2856--- a/drivers/media/video/msp3400-driver.c
2857+++ b/drivers/media/video/msp3400-driver.c
2858@@ -56,7 +56,7 @@ #include <media/v4l2-common.h>
2859 #include <media/tvaudio.h>
2860 #include <media/msp3400.h>
2861 #include <linux/kthread.h>
2862-#include <linux/suspend.h>
2863+#include <linux/freezer.h>
2864 #include "msp3400-driver.h"
2865
2866 /* ---------------------------------------------------------------------- */
2867diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
2868index fcaef4b..d506dfa 100644
2869--- a/drivers/media/video/tvaudio.c
2870+++ b/drivers/media/video/tvaudio.c
2871@@ -29,6 +29,7 @@ #include <linux/i2c-algo-bit.h>
2872 #include <linux/init.h>
2873 #include <linux/smp_lock.h>
2874 #include <linux/kthread.h>
2875+#include <linux/freezer.h>
2876
2877 #include <media/tvaudio.h>
2878 #include <media/v4l2-common.h>
2879diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
2880index f53edf1..fcc5467 100644
2881--- a/drivers/media/video/video-buf-dvb.c
2882+++ b/drivers/media/video/video-buf-dvb.c
2883@@ -20,7 +20,7 @@ #include <linux/device.h>
2884 #include <linux/fs.h>
2885 #include <linux/kthread.h>
2886 #include <linux/file.h>
2887-#include <linux/suspend.h>
2888+#include <linux/freezer.h>
2889
2890 #include <media/video-buf.h>
2891 #include <media/video-buf-dvb.h>
2892diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
2893index 3c8dc72..9986de5 100644
2894--- a/drivers/media/video/vivi.c
2895+++ b/drivers/media/video/vivi.c
2896@@ -36,6 +36,7 @@ #include <media/video-buf.h>
2897 #include <media/v4l2-common.h>
2898 #include <linux/kthread.h>
2899 #include <linux/highmem.h>
2900+#include <linux/freezer.h>
2901
2902 /* Wake up at about 30 fps */
2903 #define WAKE_NUMERATOR 30
2904diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
2905index 82938ad..ce1a481 100644
2906--- a/drivers/mfd/ucb1x00-ts.c
2907+++ b/drivers/mfd/ucb1x00-ts.c
2908@@ -28,7 +28,7 @@ #include <linux/delay.h>
2909 #include <linux/string.h>
2910 #include <linux/input.h>
2911 #include <linux/device.h>
2912-#include <linux/suspend.h>
2913+#include <linux/freezer.h>
2914 #include <linux/slab.h>
2915 #include <linux/kthread.h>
2916
2917diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
2918index 3b4c478..c14a746 100644
2919--- a/drivers/net/irda/stir4200.c
2920+++ b/drivers/net/irda/stir4200.c
2921@@ -50,6 +50,7 @@ #include <linux/delay.h>
2922 #include <linux/usb.h>
2923 #include <linux/crc32.h>
2924 #include <linux/kthread.h>
2925+#include <linux/freezer.h>
2926 #include <net/irda/irda.h>
2927 #include <net/irda/irlap.h>
2928 #include <net/irda/irda_device.h>
2929diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
2930index efcdaf1..44a2270 100644
2931--- a/drivers/net/wireless/airo.c
2932+++ b/drivers/net/wireless/airo.c
2933@@ -49,6 +49,7 @@ #include <linux/pci.h>
2934 #include <asm/uaccess.h>
2935 #include <net/ieee80211.h>
2936 #include <linux/kthread.h>
2937+#include <linux/freezer.h>
2938
2939 #include "airo.h"
2940
2941diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
2942index f9cd831..606a467 100644
2943--- a/drivers/pcmcia/cs.c
2944+++ b/drivers/pcmcia/cs.c
2945@@ -29,6 +29,7 @@ #include <linux/pm.h>
2946 #include <linux/pci.h>
2947 #include <linux/device.h>
2948 #include <linux/kthread.h>
2949+#include <linux/freezer.h>
2950 #include <asm/system.h>
2951 #include <asm/irq.h>
2952
2953diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
2954index 81a6c83..81186f4 100644
2955--- a/drivers/pnp/pnpbios/core.c
2956+++ b/drivers/pnp/pnpbios/core.c
2957@@ -61,6 +61,7 @@ #include <linux/spinlock.h>
2958 #include <linux/dmi.h>
2959 #include <linux/delay.h>
2960 #include <linux/acpi.h>
2961+#include <linux/freezer.h>
2962
2963 #include <asm/page.h>
2964 #include <asm/desc.h>
2965diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
2966index ba165af..0befb1d 100644
2967--- a/drivers/usb/core/hub.c
2968+++ b/drivers/usb/core/hub.c
2969@@ -22,6 +22,7 @@ #include <linux/usb.h>
2970 #include <linux/usbdevice_fs.h>
2971 #include <linux/kthread.h>
2972 #include <linux/mutex.h>
2973+#include <linux/freezer.h>
2974
2975 #include <asm/semaphore.h>
2976 #include <asm/uaccess.h>
2977diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
2978index 8b975d1..c98316c 100644
2979--- a/drivers/usb/gadget/file_storage.c
2980+++ b/drivers/usb/gadget/file_storage.c
2981@@ -250,7 +250,7 @@ #include <linux/signal.h>
2982 #include <linux/slab.h>
2983 #include <linux/spinlock.h>
2984 #include <linux/string.h>
2985-#include <linux/suspend.h>
2986+#include <linux/freezer.h>
2987 #include <linux/utsname.h>
2988
2989 #include <linux/usb_ch9.h>
2990diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
2991index b8d6031..e021bc9 100644
2992--- a/drivers/usb/storage/usb.c
2993+++ b/drivers/usb/storage/usb.c
2994@@ -49,7 +49,7 @@
2995
2996 #include <linux/sched.h>
2997 #include <linux/errno.h>
2998-#include <linux/suspend.h>
2999+#include <linux/freezer.h>
3000 #include <linux/module.h>
3001 #include <linux/init.h>
3002 #include <linux/slab.h>
3003diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
3004index de3e979..63c0724 100644
3005--- a/drivers/w1/w1.c
3006+++ b/drivers/w1/w1.c
3007@@ -31,6 +31,7 @@ #include <linux/device.h>
3008 #include <linux/slab.h>
3009 #include <linux/sched.h>
3010 #include <linux/kthread.h>
3011+#include <linux/freezer.h>
3012
3013 #include <asm/atomic.h>
3014
3015diff --git a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c
3016index f09a794..615df24 100644
3017--- a/fs/afs/kafsasyncd.c
3018+++ b/fs/afs/kafsasyncd.c
3019@@ -20,6 +20,7 @@ #include <linux/module.h>
3020 #include <linux/init.h>
3021 #include <linux/sched.h>
3022 #include <linux/completion.h>
3023+#include <linux/freezer.h>
3024 #include "cell.h"
3025 #include "server.h"
3026 #include "volume.h"
3027diff --git a/fs/afs/kafstimod.c b/fs/afs/kafstimod.c
3028index 65bc05a..694344e 100644
3029--- a/fs/afs/kafstimod.c
3030+++ b/fs/afs/kafstimod.c
3031@@ -13,6 +13,7 @@ #include <linux/module.h>
3032 #include <linux/init.h>
3033 #include <linux/sched.h>
3034 #include <linux/completion.h>
3035+#include <linux/freezer.h>
3036 #include "cell.h"
3037 #include "volume.h"
3038 #include "kafstimod.h"
3039diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
3040index 84976cd..df95c71 100644
3041--- a/fs/cifs/cifsfs.c
3042+++ b/fs/cifs/cifsfs.c
3043@@ -34,6 +34,7 @@ #include <linux/vfs.h>
3044 #include <linux/mempool.h>
3045 #include <linux/delay.h>
3046 #include <linux/kthread.h>
3047+#include <linux/freezer.h>
3048 #include "cifsfs.h"
3049 #include "cifspdu.h"
3050 #define DECLARE_GLOBALS_HERE
3051diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
3052index 71f7791..2caca06 100644
3053--- a/fs/cifs/connect.c
3054+++ b/fs/cifs/connect.c
3055@@ -31,6 +31,7 @@ #include <linux/mempool.h>
3056 #include <linux/delay.h>
3057 #include <linux/completion.h>
3058 #include <linux/pagevec.h>
3059+#include <linux/freezer.h>
3060 #include <asm/uaccess.h>
3061 #include <asm/processor.h>
3062 #include "cifspdu.h"
3063diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
3064index b85c686..75d3d86 100644
3065--- a/fs/jbd/journal.c
3066+++ b/fs/jbd/journal.c
3067@@ -31,7 +31,7 @@ #include <linux/slab.h>
3068 #include <linux/smp_lock.h>
3069 #include <linux/init.h>
3070 #include <linux/mm.h>
3071-#include <linux/suspend.h>
3072+#include <linux/freezer.h>
3073 #include <linux/pagemap.h>
3074 #include <linux/kthread.h>
3075 #include <linux/poison.h>
3076diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
3077index c60f378..93ca71c 100644
3078--- a/fs/jbd2/journal.c
3079+++ b/fs/jbd2/journal.c
3080@@ -31,7 +31,7 @@ #include <linux/slab.h>
3081 #include <linux/smp_lock.h>
3082 #include <linux/init.h>
3083 #include <linux/mm.h>
3084-#include <linux/suspend.h>
3085+#include <linux/freezer.h>
3086 #include <linux/pagemap.h>
3087 #include <linux/kthread.h>
3088 #include <linux/poison.h>
3089diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
3090index 4a543e1..478a74e 100644
3091--- a/fs/jffs/intrep.c
3092+++ b/fs/jffs/intrep.c
3093@@ -66,6 +66,7 @@ #include <asm/byteorder.h>
3094 #include <linux/smp_lock.h>
3095 #include <linux/time.h>
3096 #include <linux/ctype.h>
3097+#include <linux/freezer.h>
3098
3099 #include "intrep.h"
3100 #include "jffs_fm.h"
3101diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
3102index ff2a872..6eb3dae 100644
3103--- a/fs/jffs2/background.c
3104+++ b/fs/jffs2/background.c
3105@@ -16,6 +16,7 @@ #include <linux/jffs2.h>
3106 #include <linux/mtd/mtd.h>
3107 #include <linux/completion.h>
3108 #include <linux/sched.h>
3109+#include <linux/freezer.h>
3110 #include "nodelist.h"
3111
3112
3113diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
3114index b89c9ab..5065baa 100644
3115--- a/fs/jfs/jfs_logmgr.c
3116+++ b/fs/jfs/jfs_logmgr.c
3117@@ -67,7 +67,7 @@ #include <linux/completion.h>
3118 #include <linux/kthread.h>
3119 #include <linux/buffer_head.h> /* for sync_blockdev() */
3120 #include <linux/bio.h>
3121-#include <linux/suspend.h>
3122+#include <linux/freezer.h>
3123 #include <linux/delay.h>
3124 #include <linux/mutex.h>
3125 #include "jfs_incore.h"
3126diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
3127index 81f6f04..d558e51 100644
3128--- a/fs/jfs/jfs_txnmgr.c
3129+++ b/fs/jfs/jfs_txnmgr.c
3130@@ -46,7 +46,7 @@ #include <linux/fs.h>
3131 #include <linux/vmalloc.h>
3132 #include <linux/smp_lock.h>
3133 #include <linux/completion.h>
3134-#include <linux/suspend.h>
3135+#include <linux/freezer.h>
3136 #include <linux/module.h>
3137 #include <linux/moduleparam.h>
3138 #include <linux/kthread.h>
3139diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
3140index 3d84f60..50643b6 100644
3141--- a/fs/lockd/clntproc.c
3142+++ b/fs/lockd/clntproc.c
3143@@ -13,6 +13,7 @@ #include <linux/fs.h>
3144 #include <linux/nfs_fs.h>
3145 #include <linux/utsname.h>
3146 #include <linux/smp_lock.h>
3147+#include <linux/freezer.h>
3148 #include <linux/sunrpc/clnt.h>
3149 #include <linux/sunrpc/svc.h>
3150 #include <linux/lockd/lockd.h>
3151diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
3152index d338284..4cdd3d6 100644
3153--- a/fs/xfs/linux-2.6/xfs_buf.c
3154+++ b/fs/xfs/linux-2.6/xfs_buf.c
3155@@ -32,6 +32,7 @@ #include <linux/hash.h>
3156 #include <linux/kthread.h>
3157 #include <linux/migrate.h>
3158 #include <linux/backing-dev.h>
3159+#include <linux/freezer.h>
3160
3161 STATIC kmem_zone_t *xfs_buf_zone;
3162 STATIC kmem_shaker_t xfs_buf_shake;
3163diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
3164index de05abb..b93265b 100644
3165--- a/fs/xfs/linux-2.6/xfs_super.c
3166+++ b/fs/xfs/linux-2.6/xfs_super.c
3167@@ -56,6 +56,7 @@ #include <linux/mount.h>
3168 #include <linux/mempool.h>
3169 #include <linux/writeback.h>
3170 #include <linux/kthread.h>
3171+#include <linux/freezer.h>
3172
3173 STATIC struct quotactl_ops xfs_quotactl_operations;
3174 STATIC struct super_operations xfs_super_operations;
3175diff --git a/include/linux/bio.h b/include/linux/bio.h
3176index 092dbd0..d2e0f2c 100644
3177--- a/include/linux/bio.h
3178+++ b/include/linux/bio.h
3179@@ -125,6 +125,7 @@ #define BIO_CLONED 4 /* doesn't own data
3180 #define BIO_BOUNCED 5 /* bio is a bounce bio */
3181 #define BIO_USER_MAPPED 6 /* contains user pages */
3182 #define BIO_EOPNOTSUPP 7 /* not supported */
3183+#define BIO_SUSPEND_DATA 8
3184 #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))
3185
3186 /*
3187diff --git a/include/linux/dyn_pageflags.h b/include/linux/dyn_pageflags.h
3188new file mode 100644
3189index 0000000..1b2a8a0
3190--- /dev/null
3191+++ b/include/linux/dyn_pageflags.h
3192@@ -0,0 +1,67 @@
3193+/*
3194+ * include/linux/dyn_pageflags.h
3195+ *
3196+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
3197+ *
3198+ * This file is released under the GPLv2.
3199+ *
3200+ * It implements support for dynamically allocated bitmaps that are
3201+ * used for temporary or infrequently used pageflags, in lieu of
3202+ * bits in the struct page flags entry.
3203+ */
3204+
3205+#ifndef DYN_PAGEFLAGS_H
3206+#define DYN_PAGEFLAGS_H
3207+
3208+#include <linux/mm.h>
3209+
3210+typedef unsigned long *** dyn_pageflags_t;
3211+
3212+#if BITS_PER_LONG == 32
3213+#define UL_SHIFT 5
3214+#else
3215+#if BITS_PER_LONG == 64
3216+#define UL_SHIFT 6
3217+#else
3218+#error Bits per long not 32 or 64?
3219+#endif
3220+#endif
3221+
3222+#define BIT_NUM_MASK (sizeof(unsigned long) * 8 - 1)
3223+#define PAGE_NUM_MASK (~((1 << (PAGE_SHIFT + 3)) - 1))
3224+#define UL_NUM_MASK (~(BIT_NUM_MASK | PAGE_NUM_MASK))
3225+
3226+/*
3227+ * PAGENUMBER gives the index of the page within the zone.
3228+ * PAGEINDEX gives the index of the unsigned long within that page.
3229+ * PAGEBIT gives the index of the bit within the unsigned long.
3230+ */
3231+#define BITS_PER_PAGE (PAGE_SIZE << 3)
3232+#define PAGENUMBER(zone_offset) ((int) (zone_offset >> (PAGE_SHIFT + 3)))
3233+#define PAGEINDEX(zone_offset) ((int) ((zone_offset & UL_NUM_MASK) >> UL_SHIFT))
3234+#define PAGEBIT(zone_offset) ((int) (zone_offset & BIT_NUM_MASK))
3235+
3236+#define PAGE_UL_PTR(bitmap, zone_num, zone_pfn) \
3237+ ((bitmap[zone_num][PAGENUMBER(zone_pfn)])+PAGEINDEX(zone_pfn))
3238+
3239+#define BITMAP_FOR_EACH_SET(bitmap, counter) \
3240+ for (counter = get_next_bit_on(bitmap, max_pfn); counter < max_pfn; \
3241+ counter = get_next_bit_on(bitmap, counter))
3242+
3243+extern void clear_dyn_pageflags(dyn_pageflags_t pagemap);
3244+extern int allocate_dyn_pageflags(dyn_pageflags_t *pagemap);
3245+extern void free_dyn_pageflags(dyn_pageflags_t *pagemap);
3246+extern unsigned long get_next_bit_on(dyn_pageflags_t bitmap, unsigned long counter);
3247+
3248+extern int test_dynpageflag(dyn_pageflags_t *bitmap, struct page *page);
3249+extern void set_dynpageflag(dyn_pageflags_t *bitmap, struct page *page);
3250+extern void clear_dynpageflag(dyn_pageflags_t *bitmap, struct page *page);
3251+#endif
3252+
3253+/*
3254+ * With the above macros defined, you can do...
3255+ * #define PagePageset1(page) (test_dynpageflag(&pageset1_map, page))
3256+ * #define SetPagePageset1(page) (set_dynpageflag(&pageset1_map, page))
3257+ * #define ClearPagePageset1(page) (clear_dynpageflag(&pageset1_map, page))
3258+ */
3259+
3260diff --git a/include/linux/freezer.h b/include/linux/freezer.h
3261new file mode 100644
3262index 0000000..c54e2f6
3263--- /dev/null
3264+++ b/include/linux/freezer.h
3265@@ -0,0 +1,104 @@
3266+/* Freezer declarations */
3267+
3268+#define FREEZER_ON 0
3269+#define ABORT_FREEZING 1
3270+
3271+#define FREEZER_OFF 0
3272+#define USERSPACE_FROZEN 1
3273+#define FREEZING_COMPLETE 2
3274+
3275+#define FREEZER_KERNEL_THREADS 0
3276+#define FREEZER_ALL_THREADS 1
3277+
3278+#ifdef CONFIG_PM
3279+/*
3280+ * Check if a process has been frozen
3281+ */
3282+static inline int frozen(struct task_struct *p)
3283+{
3284+ return p->flags & PF_FROZEN;
3285+}
3286+
3287+/*
3288+ * Check if there is a request to freeze a process
3289+ */
3290+static inline int freezing(struct task_struct *p)
3291+{
3292+ return p->flags & PF_FREEZE;
3293+}
3294+
3295+/*
3296+ * Request that a process be frozen
3297+ * FIXME: SMP problem. We may not modify other process' flags!
3298+ */
3299+static inline void freeze(struct task_struct *p)
3300+{
3301+ p->flags |= PF_FREEZE;
3302+}
3303+
3304+/*
3305+ * Sometimes we may need to cancel the previous 'freeze' request
3306+ */
3307+static inline void do_not_freeze(struct task_struct *p)
3308+{
3309+ p->flags &= ~PF_FREEZE;
3310+}
3311+
3312+/*
3313+ * Wake up a frozen process
3314+ */
3315+static inline int thaw_process(struct task_struct *p)
3316+{
3317+ if (frozen(p)) {
3318+ p->flags &= ~PF_FROZEN;
3319+ wake_up_process(p);
3320+ return 1;
3321+ }
3322+ return 0;
3323+}
3324+
3325+/*
3326+ * freezing is complete, mark process as frozen
3327+ */
3328+static inline void frozen_process(struct task_struct *p)
3329+{
3330+ p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
3331+}
3332+
3333+extern void refrigerator(void);
3334+extern int freeze_processes(void);
3335+
3336+static inline int try_to_freeze(void)
3337+{
3338+ if (freezing(current)) {
3339+ refrigerator();
3340+ return 1;
3341+ } else
3342+ return 0;
3343+}
3344+extern int freezer_state;
3345+extern void thaw_some_processes(int all);
3346+
3347+#define freezer_is_on() (freezer_state == FREEZING_COMPLETE)
3348+
3349+#define thaw_processes() do { thaw_some_processes(FREEZER_ALL_THREADS); } while(0)
3350+#define thaw_kernel_threads() do { thaw_some_processes(FREEZER_KERNEL_THREADS); } while(0)
3351+
3352+#else
3353+
3354+#define freezer_is_on() (0)
3355+
3356+static inline int frozen(struct task_struct *p) { return 0; }
3357+static inline int freezing(struct task_struct *p) { return 0; }
3358+static inline void freeze(struct task_struct *p) { BUG(); }
3359+static inline int thaw_process(struct task_struct *p) { return 1; }
3360+static inline void frozen_process(struct task_struct *p) { BUG(); }
3361+
3362+static inline void refrigerator(void) {}
3363+static inline int freeze_processes(void) { BUG(); return 0; }
3364+static inline void thaw_processes(int which_threads) {}
3365+
3366+static inline int try_to_freeze(void) { return 0; }
3367+
3368+
3369+#endif
3370diff --git a/include/linux/kernel.h b/include/linux/kernel.h
3371index 24b6111..cdde41c 100644
3372--- a/include/linux/kernel.h
3373+++ b/include/linux/kernel.h
3374@@ -114,6 +114,8 @@ extern int vsprintf(char *buf, const cha
3375 __attribute__ ((format (printf, 2, 0)));
3376 extern int snprintf(char * buf, size_t size, const char * fmt, ...)
3377 __attribute__ ((format (printf, 3, 4)));
3378+extern int snprintf_used(char *buffer, int buffer_size,
3379+ const char *fmt, ...);
3380 extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
3381 __attribute__ ((format (printf, 3, 0)));
3382 extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
3383diff --git a/include/linux/netlink.h b/include/linux/netlink.h
3384index 6641162..5b3c3aa 100644
3385--- a/include/linux/netlink.h
3386+++ b/include/linux/netlink.h
3387@@ -23,6 +23,8 @@ #define NETLINK_KOBJECT_UEVENT 15 /* Ker
3388 #define NETLINK_GENERIC 16
3389 /* leave room for NETLINK_DM (DM Events) */
3390 #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
3391+#define NETLINK_SUSPEND2_USERUI 19 /* For suspend2's userui */
3392+#define NETLINK_SUSPEND2_USM 20 /* For suspend2's userspace storage manager */
3393
3394 #define MAX_LINKS 32
3395
3396diff --git a/include/linux/sched.h b/include/linux/sched.h
3397index eafe4a7..5dc3fe0 100644
3398--- a/include/linux/sched.h
3399+++ b/include/linux/sched.h
3400@@ -1610,87 +1610,6 @@ extern int sched_create_sysfs_power_savi
3401
3402 extern void normalize_rt_tasks(void);
3403
3404-#ifdef CONFIG_PM
3405-/*
3406- * Check if a process has been frozen
3407- */
3408-static inline int frozen(struct task_struct *p)
3409-{
3410- return p->flags & PF_FROZEN;
3411-}
3412-
3413-/*
3414- * Check if there is a request to freeze a process
3415- */
3416-static inline int freezing(struct task_struct *p)
3417-{
3418- return p->flags & PF_FREEZE;
3419-}
3420-
3421-/*
3422- * Request that a process be frozen
3423- * FIXME: SMP problem. We may not modify other process' flags!
3424- */
3425-static inline void freeze(struct task_struct *p)
3426-{
3427- p->flags |= PF_FREEZE;
3428-}
3429-
3430-/*
3431- * Sometimes we may need to cancel the previous 'freeze' request
3432- */
3433-static inline void do_not_freeze(struct task_struct *p)
3434-{
3435- p->flags &= ~PF_FREEZE;
3436-}
3437-
3438-/*
3439- * Wake up a frozen process
3440- */
3441-static inline int thaw_process(struct task_struct *p)
3442-{
3443- if (frozen(p)) {
3444- p->flags &= ~PF_FROZEN;
3445- wake_up_process(p);
3446- return 1;
3447- }
3448- return 0;
3449-}
3450-
3451-/*
3452- * freezing is complete, mark process as frozen
3453- */
3454-static inline void frozen_process(struct task_struct *p)
3455-{
3456- p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
3457-}
3458-
3459-extern void refrigerator(void);
3460-extern int freeze_processes(void);
3461-extern void thaw_processes(void);
3462-
3463-static inline int try_to_freeze(void)
3464-{
3465- if (freezing(current)) {
3466- refrigerator();
3467- return 1;
3468- } else
3469- return 0;
3470-}
3471-#else
3472-static inline int frozen(struct task_struct *p) { return 0; }
3473-static inline int freezing(struct task_struct *p) { return 0; }
3474-static inline void freeze(struct task_struct *p) { BUG(); }
3475-static inline int thaw_process(struct task_struct *p) { return 1; }
3476-static inline void frozen_process(struct task_struct *p) { BUG(); }
3477-
3478-static inline void refrigerator(void) {}
3479-static inline int freeze_processes(void) { BUG(); return 0; }
3480-static inline void thaw_processes(void) {}
3481-
3482-static inline int try_to_freeze(void) { return 0; }
3483-
3484-#endif /* CONFIG_PM */
3485 #endif /* __KERNEL__ */
3486
3487 #endif
3488diff --git a/include/linux/suspend.h b/include/linux/suspend.h
3489index b1237f1..0b95434 100644
3490--- a/include/linux/suspend.h
3491+++ b/include/linux/suspend.h
3492@@ -8,6 +8,7 @@ #include <linux/swap.h>
3493 #include <linux/notifier.h>
3494 #include <linux/init.h>
3495 #include <linux/pm.h>
3496+#include <linux/suspend2.h>
3497
3498 /* page backup entry */
3499 struct pbe {
3500@@ -24,14 +25,9 @@ #ifdef CONFIG_PM
3501 /* kernel/power/swsusp.c */
3502 extern int software_suspend(void);
3503
3504-#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
3505 extern int pm_prepare_console(void);
3506 extern void pm_restore_console(void);
3507 #else
3508-static inline int pm_prepare_console(void) { return 0; }
3509-static inline void pm_restore_console(void) {}
3510-#endif /* defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) */
3511-#else
3512 static inline int software_suspend(void)
3513 {
3514 printk("Warning: fake suspend called\n");
3515@@ -42,8 +38,6 @@ #endif /* CONFIG_PM */
3516 void save_processor_state(void);
3517 void restore_processor_state(void);
3518 struct saved_context;
3519-void __save_processor_state(struct saved_context *ctxt);
3520-void __restore_processor_state(struct saved_context *ctxt);
3521 unsigned long get_safe_page(gfp_t gfp_mask);
3522
3523 /*
3524diff --git a/include/linux/suspend2.h b/include/linux/suspend2.h
3525new file mode 100644
3526index 0000000..7c3a0c2
3527--- /dev/null
3528+++ b/include/linux/suspend2.h
3529@@ -0,0 +1,156 @@
3530+#ifndef _LINUX_SUSPEND2_H
3531+#define _LINUX_SUSPEND2_H
3532+
3533+#include <linux/dyn_pageflags.h>
3534+
3535+/* arch/i386/mm/init.c */
3536+//extern char __nosave_begin, __nosave_end;
3537+
3538+#define SECTOR_SIZE 512
3539+
3540+/* kernel/power/main.c */
3541+extern unsigned long suspend_result;
3542+
3543+/* kernel/power/process.c */
3544+extern unsigned long suspend_debug_state;
3545+
3546+/* arch/i386/power/suspend2.c */
3547+extern unsigned long suspend_action;
3548+extern int suspend_io_time[2][2];
3549+
3550+extern dyn_pageflags_t pageset1_map;
3551+extern dyn_pageflags_t pageset1_copy_map;
3552+
3553+#if 1 //#ifdef CONFIG_PM_DEBUG
3554+#define test_debug_state(bit) (test_bit(bit, &suspend_debug_state))
3555+#else
3556+#define test_debug_state(bit) (0)
3557+#endif
3558+
3559+#define test_result_state(bit) (test_bit(bit, &suspend_result))
3560+
3561+/* Debug sections - if debugging compiled in */
3562+enum {
3563+ SUSPEND_ANY_SECTION,
3564+ SUSPEND_EAT_MEMORY,
3565+ SUSPEND_IO,
3566+ SUSPEND_HEADER,
3567+ SUSPEND_WRITER,
3568+ SUSPEND_MEMORY,
3569+};
3570+
3571+/* debugging levels. */
3572+#define SUSPEND_STATUS 0
3573+#define SUSPEND_ERROR 2
3574+#define SUSPEND_LOW 3
3575+#define SUSPEND_MEDIUM 4
3576+#define SUSPEND_HIGH 5
3577+#define SUSPEND_VERBOSE 6
3578+
3579+/* Configuration flags */
3580+enum {
3581+ SUSPEND_REBOOT,
3582+ SUSPEND_PAUSE,
3583+ SUSPEND_SLOW,
3584+ SUSPEND_LOGALL,
3585+ SUSPEND_CAN_CANCEL,
3586+ SUSPEND_KEEP_IMAGE,
3587+ SUSPEND_FREEZER_TEST,
3588+ SUSPEND_SINGLESTEP,
3589+ SUSPEND_PAUSE_NEAR_PAGESET_END,
3590+ SUSPEND_TEST_FILTER_SPEED,
3591+ SUSPEND_TEST_BIO,
3592+ SUSPEND_NO_PAGESET2,
3593+ SUSPEND_PM_PREPARE_CONSOLE,
3594+ SUSPEND_IGNORE_ROOTFS,
3595+ SUSPEND_REPLACE_SWSUSP,
3596+ SUSPEND_RETRY_RESUME,
3597+ SUSPEND_PAGESET2_FULL,
3598+ SUSPEND_ABORT_ON_RESAVE_NEEDED,
3599+};
3600+
3601+#ifdef CONFIG_SUSPEND2
3602+#define test_action_state(bit) (test_bit(bit, &suspend_action))
3603+#define set_action_state(bit) (test_and_set_bit(bit, &suspend_action))
3604+#define clear_action_state(bit) (test_and_clear_bit(bit, &suspend_action))
3605+#else
3606+#define test_action_state(bit) (0)
3607+#endif
3608+
3609+enum {
3610+ SUSPEND_CAN_SUSPEND,
3611+ SUSPEND_CAN_RESUME,
3612+ SUSPEND_RUNNING,
3613+ SUSPEND_RESUME_DEVICE_OK,
3614+ SUSPEND_NORESUME_SPECIFIED,
3615+ SUSPEND_SANITY_CHECK_PROMPT,
3616+ SUSPEND_PAGESET2_NOT_LOADED,
3617+ SUSPEND_CONTINUE_REQ,
3618+ SUSPEND_RESUMED_BEFORE,
3619+ SUSPEND_RESUME_NOT_DONE,
3620+ SUSPEND_BOOT_TIME,
3621+ SUSPEND_NOW_RESUMING,
3622+ SUSPEND_IGNORE_LOGLEVEL,
3623+ SUSPEND_TRYING_TO_RESUME,
3624+ SUSPEND_TRY_RESUME_RD,
3625+};
3626+
3627+/* --------------------------------------------------------------------- */
3628+#ifdef CONFIG_SUSPEND2
3629+
3630+/* Used in init dir files */
3631+extern unsigned long suspend_state;
3632+
3633+extern void suspend2_try_resume(void);
3634+extern int suspend_early_boot_message
3635+ (int can_erase_image, int default_answer, char *warning_reason, ...);
3636+
3637+#define test_suspend_state(bit) \
3638+ (test_bit(bit, &suspend_state))
3639+
3640+#define clear_suspend_state(bit) \
3641+ (clear_bit(bit, &suspend_state))
3642+
3643+#define set_suspend_state(bit) \
3644+ (set_bit(bit, &suspend_state))
3645+
3646+extern void suspend2_try_suspend(int have_pmsem);
3647+
3648+/* --------------------------------------------------------------------- */
3649+#else
3650+/* --------------------------------------------------------------------- */
3651+
3652+#define suspend_state (0)
3653+#define clear_suspend_state(bit) do { } while (0)
3654+#define test_suspend_state(bit) (0)
3655+#define set_suspend_state(bit) do { } while(0)
3656+
3657+#define suspend2_try_resume() do { } while(0)
3658+static inline int suspend_early_boot_message(int a, int b, char *c, ...) { return 0; }
3659+#endif /* CONFIG_SUSPEND2 */
3660+
3661+#define test_and_set_suspend_state(bit) \
3662+ (test_and_set_bit(bit, &suspend_state))
3663+
3664+#define get_suspend_state() (suspend_state)
3665+
3666+#define restore_suspend_state(saved_state) \
3667+ do { suspend_state = saved_state; } while(0)
3668+
3669+#if defined(CONFIG_SUSPEND2) && defined(CONFIG_ACPI)
3670+#include <acpi/acpi.h>
3671+static inline int may_try_suspend2(u32 state)
3672+{
3673+ if (state == ACPI_STATE_S4) {
3674+ suspend2_try_suspend(0);
3675+ return 1;
3676+ }
3677+ return 0;
3678+}
3679+#else
3680+static inline int may_try_suspend2(u32 state)
3681+{
3682+ return 0;
3683+}
3684+#endif
3685+#endif /* _LINUX_SUSPEND2_H */
3686diff --git a/include/linux/swap.h b/include/linux/swap.h
3687index e7c36ba..60cf739 100644
3688--- a/include/linux/swap.h
3689+++ b/include/linux/swap.h
3690@@ -368,5 +368,10 @@ #define has_swap_token(x) 0
3691 #define disable_swap_token() do { } while(0)
3692
3693 #endif /* CONFIG_SWAP */
3694+
3695+/* For Suspend2 - unlink LRU pages while saving separately */
3696+void unlink_lru_lists(void);
3697+void relink_lru_lists(void);
3698+
3699 #endif /* __KERNEL__*/
3700 #endif /* _LINUX_SWAP_H */
3701diff --git a/init/do_mounts.c b/init/do_mounts.c
3702index dc1ec08..85567dc 100644
3703--- a/init/do_mounts.c
3704+++ b/init/do_mounts.c
3705@@ -26,6 +26,19 @@ static char __initdata saved_root_name[6
3706
3707 dev_t ROOT_DEV;
3708
3709+#ifdef CONFIG_SOFTWARE_SUSPEND
3710+extern int software_resume(void);
3711+#else
3712+#ifdef CONFIG_SUSPEND2
3713+extern void suspend2_try_resume(void);
3714+static int software_resume(void)
3715+{
3716+ suspend2_try_resume();
3717+ return 0;
3718+}
3719+#endif
3720+#endif
3721+
3722 static int __init load_ramdisk(char *str)
3723 {
3724 rd_doload = simple_strtol(str,NULL,0) & 3;
3725@@ -139,11 +152,16 @@ dev_t name_to_dev_t(char *name)
3726 char s[32];
3727 char *p;
3728 dev_t res = 0;
3729- int part;
3730+ int part, mount_result;
3731
3732 #ifdef CONFIG_SYSFS
3733 int mkdir_err = sys_mkdir("/sys", 0700);
3734- if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
3735+ /*
3736+ * When changing resume2 parameter for Software Suspend, sysfs may
3737+ * already be mounted.
3738+ */
3739+ mount_result = sys_mount("sysfs", "/sys", "sysfs", 0, NULL);
3740+ if (mount_result < 0 && mount_result != -EBUSY)
3741 goto out;
3742 #endif
3743
3744@@ -195,7 +213,8 @@ #endif
3745 res = try_name(s, part);
3746 done:
3747 #ifdef CONFIG_SYSFS
3748- sys_umount("/sys", 0);
3749+ if (mount_result >= 0)
3750+ sys_umount("/sys", 0);
3751 out:
3752 if (!mkdir_err)
3753 sys_rmdir("/sys");
3754@@ -434,9 +453,27 @@ void __init prepare_namespace(void)
3755
3756 is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
3757
3758+ /* Suspend2:
3759+ * By this point, suspend_early_init has been called to initialise our
3760+ * sysfs interface. If modules are built in, they have registered (all
3761+ * of the above via initcalls).
3762+ *
3763+ * We have not yet looked to see if an image exists, however. If we
3764+ * have an initrd, it is expected that the user will have set it up
3765+ * to echo > /sys/power/suspend2/do_resume and thus initiate any
3766+ * resume. If they don't do that, we do it immediately after the initrd
3767+ * is finished (major issues if they mount filesystems rw from the
3768+ * initrd! - they are warned. If there's no usable initrd, we do our
3769+ * check next.
3770+ */
3771 if (initrd_load())
3772 goto out;
3773
3774+#ifdef CONFIG_SUSPEND2
3775+ if (test_suspend_state(SUSPEND_RESUME_NOT_DONE))
3776+ software_resume();
3777+#endif
3778+
3779 if (is_floppy && rd_doload && rd_load_disk(0))
3780 ROOT_DEV = Root_RAM0;
3781
3782diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
3783index 919a80c..06584f2 100644
3784--- a/init/do_mounts_initrd.c
3785+++ b/init/do_mounts_initrd.c
3786@@ -6,6 +6,8 @@ #include <linux/ext2_fs.h>
3787 #include <linux/romfs_fs.h>
3788 #include <linux/initrd.h>
3789 #include <linux/sched.h>
3790+#include <linux/suspend.h>
3791+#include <linux/freezer.h>
3792
3793 #include "do_mounts.h"
3794
3795@@ -57,10 +59,17 @@ static void __init handle_initrd(void)
3796 current->flags |= PF_NOFREEZE;
3797 pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
3798 if (pid > 0) {
3799- while (pid != sys_wait4(-1, NULL, 0, NULL))
3800+ while (pid != sys_wait4(-1, NULL, 0, NULL)) {
3801 yield();
3802+ try_to_freeze();
3803+ }
3804 }
3805
3806+ if (test_suspend_state(SUSPEND_RESUME_NOT_DONE))
3807+ printk(KERN_ERR "Suspend2: Initrd lacks echo > /sys/power/suspend2/do_resume.\n");
3808+ clear_suspend_state(SUSPEND_BOOT_TIME);
3809+ current->flags &= ~PF_NOFREEZE;
3810+
3811 /* move initrd to rootfs' /old */
3812 sys_fchdir(old_fd);
3813 sys_mount("/", ".", NULL, MS_MOVE, NULL);
3814diff --git a/init/main.c b/init/main.c
3815index 36f608a..950c11f 100644
3816--- a/init/main.c
3817+++ b/init/main.c
3818@@ -743,7 +743,9 @@ static int init(void * unused)
3819
3820 /*
3821 * check if there is an early userspace init. If yes, let it do all
3822- * the work
3823+ * the work. For suspend2, we assume that it will do the right thing
3824+ * with regard to trying to resume at the right place. When that
3825+ * happens, the BOOT_TIME flag will be cleared.
3826 */
3827
3828 if (!ramdisk_execute_command)
3829diff --git a/kernel/audit.c b/kernel/audit.c
3830index 98106f6..d9b690a 100644
3831--- a/kernel/audit.c
3832+++ b/kernel/audit.c
3833@@ -57,6 +57,7 @@ #include <linux/skbuff.h>
3834 #include <linux/netlink.h>
3835 #include <linux/selinux.h>
3836 #include <linux/inotify.h>
3837+#include <linux/freezer.h>
3838
3839 #include "audit.h"
3840
3841diff --git a/kernel/kmod.c b/kernel/kmod.c
3842index bb4e29d..fd10004 100644
3843--- a/kernel/kmod.c
3844+++ b/kernel/kmod.c
3845@@ -34,6 +34,7 @@ #include <linux/mount.h>
3846 #include <linux/kernel.h>
3847 #include <linux/init.h>
3848 #include <linux/resource.h>
3849+#include <linux/freezer.h>
3850 #include <asm/uaccess.h>
3851
3852 extern int max_threads;
3853@@ -280,6 +281,11 @@ int call_usermodehelper_keys(char *path,
3854 if (path[0] == '\0')
3855 return 0;
3856
3857+ if (freezer_is_on()) {
3858+ printk(KERN_WARNING "Freezer is on. Refusing to start %s.\n", path);
3859+ return -EBUSY;
3860+ }
3861+
3862 queue_work(khelper_wq, &work);
3863 wait_for_completion(&done);
3864 return sub_info.retval;
3865diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
3866index 825068c..98e6c4d 100644
3867--- a/kernel/power/Kconfig
3868+++ b/kernel/power/Kconfig
3869@@ -130,3 +130,88 @@ config SUSPEND_SMP
3870 bool
3871 depends on HOTPLUG_CPU && X86 && PM
3872 default y
3873+
3874+config SUSPEND2_CRYPTO
3875+ bool
3876+ depends on SUSPEND2 && CRYPTO
3877+ default y
3878+
3879+menuconfig SUSPEND2
3880+ bool "Suspend2"
3881+ depends on PM
3882+ select DYN_PAGEFLAGS
3883+ select HOTPLUG_CPU if SMP
3884+ select CRYPTO
3885+ select CRYPTO_ALGAPI
3886+ select CRYPTO_MD5
3887+ ---help---
3888+ Suspend2 is the 'new and improved' suspend support.
3889+
3890+ See the Suspend2 home page (suspend2.net)
3891+ for FAQs, HOWTOs and other documentation.
3892+
3893+ comment "Image Storage (you need at least one allocator)"
3894+ depends on SUSPEND2
3895+
3896+ config SUSPEND2_FILE
3897+ bool "File Allocator"
3898+ depends on SUSPEND2
3899+ ---help---
3900+ This option enables support for storing an image in a
3901+ simple file. This should be possible, but we're still
3902+ testing it.
3903+
3904+ config SUSPEND2_SWAP
3905+ bool "Swap Allocator"
3906+ depends on SUSPEND2
3907+ select SWAP
3908+ ---help---
3909+ This option enables support for storing an image in your
3910+ swap space.
3911+
3912+ comment "General Options"
3913+ depends on SUSPEND2
3914+
3915+ config SUSPEND2_DEFAULT_RESUME2
3916+ string "Default resume device name"
3917+ depends on SUSPEND2
3918+ ---help---
3919+ You normally need to add a resume2= parameter to your lilo.conf or
3920+ equivalent. With this option properly set, the kernel has a value
3921+ to default. No damage will be done if the value is invalid.
3922+
3923+ config SUSPEND2_KEEP_IMAGE
3924+ bool "Allow Keep Image Mode"
3925+ depends on SUSPEND2
3926+ ---help---
3927+ This option allows you to keep and image and reuse it. It is intended
3928+ __ONLY__ for use with systems where all filesystems are mounted read-
3929+ only (kiosks, for example). To use it, compile this option in and boot
3930+ normally. Set the KEEP_IMAGE flag in /proc/suspend2 and suspend.
3931+ When you resume, the image will not be removed. You will be unable to turn
3932+ off swap partitions (assuming you are using the swap allocator), but future
3933+ suspends simply do a power-down. The image can be updated using the
3934+ kernel command line parameter suspend_act= to turn off the keep image
3935+ bit. Keep image mode is a little less user friendly on purpose - it
3936+ should not be used without thought!
3937+
3938+ config SUSPEND2_REPLACE_SWSUSP
3939+ bool "Replace swsusp by default"
3940+ default y
3941+ depends on SUSPEND2
3942+ ---help---
3943+ Suspend2 can replace swsusp. This option makes that the default state,
3944+ requiring you to echo 0 > /sys/power/suspend2/replace_swsusp if you want
3945+ to use the vanilla kernel functionality. Note that your initrd/ramfs will
3946+ need to do this before trying to resume, too.
3947+ With overriding swsusp enabled, Suspend2 will use both the resume= and
3948+ noresume commandline options _and_ the resume2= and noresume2 ones (for
3949+ compatibility). resume= takes precedence over resume2=. Echoing disk
3950+ to /sys/power/state will start a Suspend2 cycle. If resume= doesn't
3951+ specify an allocator and both the swap and file allocators are compiled in,
3952+ the swap allocator will be used by default.
3953+
3954+config SUSPEND_SHARED
3955+ bool
3956+ depends on SUSPEND2 || SOFTWARE_SUSPEND
3957+ default y
3958diff --git a/kernel/power/Makefile b/kernel/power/Makefile
3959index 38725f5..f2a035b 100644
3960--- a/kernel/power/Makefile
3961+++ b/kernel/power/Makefile
3962@@ -5,6 +5,26 @@ endif
3963
3964 obj-y := main.o process.o console.o
3965 obj-$(CONFIG_PM_LEGACY) += pm.o
3966-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o swap.o user.o
3967+obj-$(CONFIG_SUSPEND_SHARED) += snapshot.o
3968+
3969+# Order is important for compression and encryption - we
3970+# compress before encrypting.
3971+
3972+suspend_core-objs := io.o pagedir.o prepare_image.o \
3973+ extent.o suspend.o modules.o \
3974+ pageflags.o ui.o sysfs.o \
3975+ power_off.o atomic_copy.o checksum.o
3976+
3977+#ifdef CONFIG_NET
3978+suspend_core-objs += storage.o netlink.o
3979+#endif
3980+
3981+obj-$(CONFIG_SUSPEND2) += suspend_core.o
3982+obj-$(CONFIG_SUSPEND2_CRYPTO) += compression.o encryption.o
3983+
3984+obj-$(CONFIG_SUSPEND2_SWAP) += suspend_block_io.o suspend_swap.o
3985+obj-$(CONFIG_SUSPEND2_FILE) += suspend_block_io.o suspend_file.o
3986+
3987+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o swap.o user.o
3988
3989 obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
3990diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
3991new file mode 100644
3992index 0000000..5765cd2
3993--- /dev/null
3994+++ b/kernel/power/atomic_copy.c
3995@@ -0,0 +1,478 @@
3996+/*
3997+ * kernel/power/atomic_copy.c
3998+ *
3999+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
4000+ * Copyright (C) 2006 Red Hat, inc.
4001+ *
4002+ * Distributed under GPLv2.
4003+ *
4004+ * Routines for doing the atomic save/restore.
4005+ */
4006+
4007+#include <linux/suspend.h>
4008+#include <linux/highmem.h>
4009+#include <linux/bootmem.h>
4010+#include <linux/vt_kern.h>
4011+#include <linux/cpu.h>
4012+#include <linux/freezer.h>
4013+#include <asm/setup.h>
4014+#include "suspend.h"
4015+#include "storage.h"
4016+#include "power_off.h"
4017+#include "ui.h"
4018+#include "power.h"
4019+#include "io.h"
4020+#include "prepare_image.h"
4021+#include "pageflags.h"
4022+#include "extent.h"
4023+#include "checksum.h"
4024+
4025+static unsigned long state1 __nosavedata = 0;
4026+static unsigned long state2 __nosavedata = 0;
4027+static int state3 __nosavedata = 0;
4028+static int io_speed_save[2][2] __nosavedata;
4029+__nosavedata char suspend_resume_commandline[COMMAND_LINE_SIZE];
4030+
4031+#define SUSPEND_FREQ_START 2000
4032+#define FREQ_CHANGE -100
4033+#define GROUP_SIZE 10
4034+#define RESUME_FREQ_START (SUSPEND_FREQ_START + (GROUP_SIZE - 1) * FREQ_CHANGE)
4035+
4036+extern void suspend_power_down(void);
4037+extern int swsusp_resume(void);
4038+extern int suspend2_in_suspend __nosavedata;
4039+int extra_pd1_pages_used;
4040+
4041+#ifdef CONFIG_HIGHMEM
4042+static dyn_pageflags_t __nosavedata origmap;
4043+static dyn_pageflags_t __nosavedata copymap;
4044+static unsigned long __nosavedata origoffset;
4045+static unsigned long __nosavedata copyoffset;
4046+static __nosavedata int o_zone_num, c_zone_num;
4047+
4048+struct zone_data {
4049+ unsigned long start_pfn;
4050+ unsigned long end_pfn;
4051+ int is_highmem;
4052+};
4053+
4054+static __nosavedata struct zone_data *zone_nosave;
4055+static __nosavedata unsigned long boot_max_pfn;
4056+
4057+/**
4058+ * suspend_init_nosave_zone_table: Set up nosave copy of zone table data.
4059+ *
4060+ * Zone information might be overwritten during the copy back, so we copy
4061+ * the fields we need to a non-conflicting page and use it.
4062+ **/
4063+static void suspend_init_nosave_zone_table(void)
4064+{
4065+ struct zone *zone;
4066+
4067+ zone_nosave = (struct zone_data *) suspend_get_nonconflicting_page();
4068+
4069+ BUG_ON(!zone_nosave);
4070+
4071+ /* It should all fit in one page. */
4072+ BUG_ON(ZONETABLE_MASK > (PAGE_SIZE / sizeof(struct zone_data)));
4073+
4074+ memset((char *) zone_nosave, 0, PAGE_SIZE);
4075+
4076+ for_each_zone(zone) {
4077+ if (populated_zone(zone)) {
4078+ int zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
4079+ zone_nosave[zone_num].start_pfn = zone->zone_start_pfn;
4080+ zone_nosave[zone_num].end_pfn = zone->zone_start_pfn +
4081+ zone->spanned_pages - 1;
4082+ zone_nosave[zone_num].is_highmem = is_highmem(zone);
4083+ }
4084+ }
4085+
4086+ boot_max_pfn = max_pfn;
4087+}
4088+
4089+/**
4090+ * __suspend_get_next_bit_on: Atomic-copy safe location of next bit on in a bitmap.
4091+ *
4092+ * @bitmap: The bitmap we are traversing.
4093+ * @zone_num: Which zone we are in.
4094+ * @counter: The current pfn.
4095+ *
4096+ * A version of __get_next_bit_on that can be used when doing the atomic
4097+ * copy. While doing it, we can't rely on the zone information being in
4098+ * a constant location.
4099+ **/
4100+static unsigned long __suspend_get_next_bit_on(dyn_pageflags_t bitmap,
4101+ int *zone_num, unsigned long counter)
4102+{
4103+ unsigned long *ul_ptr = NULL;
4104+ int reset_ul_ptr = 1, pagebit;
4105+ BUG_ON(*zone_num == (1 << ZONETABLE_SHIFT));
4106+
4107+ if (counter == boot_max_pfn) {
4108+ *zone_num = 0;
4109+ while (!zone_nosave[*zone_num].end_pfn)
4110+ (*zone_num)++;
4111+ counter = zone_nosave[*zone_num].start_pfn - 1;
4112+ }
4113+
4114+ do {
4115+ counter++;
4116+ if (counter > zone_nosave[*zone_num].end_pfn) {
4117+ (*zone_num)++;
4118+ while (*zone_num < (1 << ZONETABLE_SHIFT) &&
4119+ !zone_nosave[*zone_num].end_pfn)
4120+ (*zone_num)++;
4121+
4122+ if (*zone_num == (1 << ZONETABLE_SHIFT))
4123+ return boot_max_pfn;
4124+ counter = zone_nosave[*zone_num].start_pfn;
4125+ reset_ul_ptr = 1;
4126+ } else
4127+ if (!(counter & BIT_NUM_MASK))
4128+ reset_ul_ptr = 1;
4129+
4130+ pagebit = PAGEBIT(counter);
4131+
4132+ if (reset_ul_ptr) {
4133+ reset_ul_ptr = 0;
4134+ ul_ptr = PAGE_UL_PTR(bitmap, *zone_num,
4135+ (counter - zone_nosave[*zone_num].start_pfn));
4136+ }
4137+
4138+ if (!(*ul_ptr & ~((1 << pagebit) - 1))) {
4139+ counter += BITS_PER_LONG - pagebit - 1;
4140+ continue;
4141+ }
4142+ } while(!test_bit(pagebit, ul_ptr));
4143+
4144+ return counter;
4145+}
4146+
4147+/*
4148+ * copyback_high: Restore highmem pages.
4149+ *
4150+ * Iterate through the source and destination bitmaps, restoring
4151+ * highmem pages that were atomically copied.
4152+ */
4153+void copyback_high(void)
4154+{
4155+ unsigned long *origpage;
4156+ unsigned long *copypage;
4157+
4158+ origoffset = __suspend_get_next_bit_on(origmap, &o_zone_num, boot_max_pfn);
4159+ copyoffset = __suspend_get_next_bit_on(copymap, &c_zone_num, boot_max_pfn);
4160+
4161+ while (o_zone_num < (1 << ZONETABLE_SHIFT)) {
4162+ if (zone_nosave[o_zone_num].is_highmem) {
4163+ origpage = (unsigned long *) kmap_atomic(pfn_to_page(origoffset), KM_USER1);
4164+ copypage = (unsigned long *) __va(copyoffset << PAGE_SHIFT);
4165+
4166+ memcpy(origpage, copypage, PAGE_SIZE);
4167+
4168+ kunmap_atomic(origpage, KM_USER1);
4169+ }
4170+
4171+ origoffset = __suspend_get_next_bit_on(origmap, &o_zone_num, origoffset);
4172+ copyoffset = __suspend_get_next_bit_on(copymap, &c_zone_num, copyoffset);
4173+ }
4174+}
4175+#else
4176+void copyback_high(void) { }
4177+#endif
4178+
4179+/*
4180+ * prepare_suspend2_pbe_list
4181+ *
4182+ * Prepare pageset2 pages for doing the atomic copy. If necessary,
4183+ * we allocate extra pages.
4184+ *
4185+ */
4186+
4187+void prepare_suspend2_pbe_list(void)
4188+{
4189+ unsigned long orig_pfn, copy_pfn;
4190+ int i = 1;
4191+ struct pbe *this_pbe = NULL, *last_pbe = NULL;
4192+
4193+ orig_pfn = copy_pfn = max_pfn;
4194+
4195+ restore_pblist = NULL;
4196+
4197+ do {
4198+ if (!this_pbe ||
4199+ ((((unsigned long) this_pbe) & (PAGE_SIZE - 1))
4200+ + 2 * sizeof(struct pbe)) > PAGE_SIZE) {
4201+ /* Get the next page for pbes */
4202+ this_pbe = (struct pbe *) suspend_get_nonconflicting_page();
4203+ BUG_ON(!this_pbe);
4204+ BUG_ON(PagePageset1(virt_to_page(this_pbe)));
4205+ } else
4206+ this_pbe++;
4207+
4208+ do {
4209+ orig_pfn = get_next_bit_on(pageset1_map, orig_pfn);
4210+ if (orig_pfn == max_pfn)
4211+ return;
4212+ copy_pfn = get_next_bit_on(pageset1_copy_map, copy_pfn);
4213+ } while (PageHighMem(pfn_to_page(orig_pfn)));
4214+
4215+ if (!last_pbe)
4216+ restore_pblist = this_pbe;
4217+ else
4218+ last_pbe->next = this_pbe;
4219+
4220+ last_pbe = this_pbe;
4221+ this_pbe->orig_address = (unsigned long) page_address(pfn_to_page(orig_pfn));
4222+ this_pbe->address = (unsigned long) page_address(pfn_to_page(copy_pfn));
4223+ this_pbe->next = NULL; /* get_nonconflicting_page doesn't get zeroed pages */
4224+
4225+ i++;
4226+
4227+ } while (1);
4228+}
4229+
4230+/*
4231+ * copyback_post: Post atomic-restore actions.
4232+ *
4233+ * After doing the atomic restore, we have a few more things to do:
4234+ * 1) We want to retain some values across the restore, so we now copy
4235+ * these from the nosave variables to the normal ones.
4236+ * 2) Set the status flags.
4237+ * 3) Resume devices.
4238+ * 4) Get userui to redraw.
4239+ * 5) Reread the page cache.
4240+ */
4241+
4242+void copyback_post(void)
4243+{
4244+ int loop;
4245+
4246+ suspend_action = state1;
4247+ suspend_debug_state = state2;
4248+ console_loglevel = state3;
4249+
4250+ for (loop = 0; loop < 4; loop++)
4251+ suspend_io_time[loop/2][loop%2] =
4252+ io_speed_save[loop/2][loop%2];
4253+
4254+ set_suspend_state(SUSPEND_NOW_RESUMING);
4255+ set_suspend_state(SUSPEND_PAGESET2_NOT_LOADED);
4256+
4257+ if (pm_ops && pm_ops->finish && suspend_powerdown_method > 3)
4258+ pm_ops->finish(suspend_powerdown_method);
4259+
4260+ if (suspend_activate_storage(1))
4261+ panic("Failed to reactivate our storage.");
4262+
4263+ userui_redraw();
4264+
4265+ suspend_cond_pause(1, "About to reload secondary pagedir.");
4266+
4267+ if (read_pageset2(0))
4268+ panic("Unable to successfully reread the page cache.");
4269+
4270+ clear_suspend_state(SUSPEND_PAGESET2_NOT_LOADED);
4271+
4272+ suspend_prepare_status(DONT_CLEAR_BAR, "Cleaning up...");
4273+}
4274+
4275+/*
4276+ * suspend_post_context_save: Steps after saving the cpu context.
4277+ *
4278+ * Steps taken after saving the CPU state to make the actual
4279+ * atomic copy.
4280+ *
4281+ * Called from swsusp_save in snapshot.c.
4282+ */
4283+
4284+int suspend_post_context_save(void)
4285+{
4286+ int old_ps1_size = pagedir1.size;
4287+ int old_ps2_size = pagedir2.size;
4288+
4289+ BUG_ON(!irqs_disabled());
4290+
4291+ calculate_check_checksums(1);
4292+
4293+ free_checksum_pages();
4294+
4295+ suspend_recalculate_image_contents(1);
4296+
4297+ extra_pd1_pages_used = pagedir1.size - old_ps1_size;
4298+
4299+ if ((pagedir1.size - old_ps1_size) > extra_pd1_pages_allowance) {
4300+ printk("Pageset1 has grown by %ld pages. "
4301+ "extra_pages_allowance is currently only %d.\n",
4302+ pagedir1.size - old_ps1_size,
4303+ extra_pd1_pages_allowance);
4304+ set_result_state(SUSPEND_ABORTED);
4305+ set_result_state(SUSPEND_EXTRA_PAGES_ALLOW_TOO_SMALL);
4306+ return -1;
4307+ }
4308+
4309+ BUG_ON(old_ps2_size != pagedir2.size);
4310+
4311+ BUG_ON(!irqs_disabled());
4312+
4313+ if (!test_action_state(SUSPEND_TEST_FILTER_SPEED) &&
4314+ !test_action_state(SUSPEND_TEST_BIO))
4315+ suspend_copy_pageset1();
4316+
4317+ return 0;
4318+}
4319+
4320+/* suspend_copy_pageset1: Do the atomic copy of pageset1.
4321+ *
4322+ * Make the atomic copy of pageset1. We can't use copy_page (as we once did)
4323+ * because we can't be sure what side effects it has. On my old Duron, with
4324+ * 3DNOW, kernel_fpu_begin increments preempt count, making our preempt
4325+ * count at resume time 4 instead of 3.
4326+ *
4327+ * We don't want to call kmap_atomic unconditionally because it has the side
4328+ * effect of incrementing the preempt count, which will leave it one too high
4329+ * post resume (the page containing the preempt count will be copied after
4330+ * its incremented. This is essentially the same problem.
4331+ */
4332+
4333+void suspend_copy_pageset1(void)
4334+{
4335+ int i;
4336+ unsigned long source_index, dest_index;
4337+
4338+ source_index = get_next_bit_on(pageset1_map, max_pfn);
4339+ dest_index = get_next_bit_on(pageset1_copy_map, max_pfn);
4340+
4341+ for (i = 0; i < pagedir1.size; i++) {
4342+ unsigned long *origvirt, *copyvirt;
4343+ struct page *origpage;
4344+ int loop = (PAGE_SIZE / sizeof(unsigned long)) - 1;
4345+
4346+ origpage = pfn_to_page(source_index);
4347+
4348+ if (PageHighMem(origpage))
4349+ origvirt = kmap_atomic(origpage, KM_USER0);
4350+ else
4351+ origvirt = page_address(origpage);
4352+
4353+ copyvirt = (unsigned long *) page_address(pfn_to_page(dest_index));
4354+
4355+ while (loop >= 0) {
4356+ *(copyvirt + loop) = *(origvirt + loop);
4357+ loop--;
4358+ }
4359+
4360+ if (PageHighMem(origpage))
4361+ kunmap_atomic(origvirt, KM_USER0);
4362+
4363+ source_index = get_next_bit_on(pageset1_map, source_index);
4364+ dest_index = get_next_bit_on(pageset1_copy_map, dest_index);
4365+ }
4366+}
4367+
4368+int suspend2_suspend(void)
4369+{
4370+ int error;
4371+
4372+ if (test_action_state(SUSPEND_PM_PREPARE_CONSOLE))
4373+ pm_prepare_console();
4374+
4375+ if ((error = arch_prepare_suspend()))
4376+ return error;
4377+ local_irq_disable();
4378+ /* At this point, device_suspend() has been called, but *not*
4379+ * device_power_down(). We *must* device_power_down() now.
4380+ * Otherwise, drivers for some devices (e.g. interrupt controllers)
4381+ * become desynchronized with the actual state of the hardware
4382+ * at resume time, and evil weirdness ensues.
4383+ */
4384+ if ((error = device_power_down(PMSG_FREEZE))) {
4385+ set_result_state(SUSPEND_DEVICE_REFUSED);
4386+ set_result_state(SUSPEND_ABORTED);
4387+ printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
4388+ goto enable_irqs;
4389+ }
4390+
4391+ save_processor_state();
4392+ if ((error = swsusp_arch_suspend()))
4393+ printk(KERN_ERR "Error %d suspending\n", error);
4394+ /* Restore control flow appears here */
4395+ restore_processor_state();
4396+
4397+ if (!suspend2_in_suspend)
4398+ copyback_high();
4399+ device_power_up();
4400+enable_irqs:
4401+ local_irq_enable();
4402+ if (test_action_state(SUSPEND_PM_PREPARE_CONSOLE))
4403+ pm_restore_console();
4404+
4405+ return error;
4406+}
4407+
4408+/*
4409+ * suspend_atomic_restore
4410+ *
4411+ * Get ready to do the atomic restore. This part gets us into the same
4412+ * state we are in prior to do calling do_suspend2_lowlevel while
4413+ * suspending: hotunplugging secondary cpus and freeze processes,
4414+ * before starting the thread that will do the restore.
4415+ */
4416+int suspend_atomic_restore(void)
4417+{
4418+ int error, loop;
4419+
4420+ suspend_prepare_status(DONT_CLEAR_BAR, "Atomic restore preparation");
4421+ prepare_suspend2_pbe_list();
4422+
4423+ if (test_action_state(SUSPEND_PM_PREPARE_CONSOLE))
4424+ pm_prepare_console();
4425+
4426+ disable_nonboot_cpus();
4427+
4428+ if ((error = freeze_processes())) {
4429+ printk("Some processes failed to suspend\n");
4430+ if (test_action_state(SUSPEND_PM_PREPARE_CONSOLE))
4431+ pm_restore_console();
4432+ BUG();
4433+ }
4434+
4435+ if ((error = device_suspend(PMSG_FREEZE))) {
4436+ printk("Some devices failed to suspend\n");
4437+ if (test_action_state(SUSPEND_PM_PREPARE_CONSOLE))
4438+ pm_restore_console();
4439+ BUG();
4440+ }
4441+
4442+#ifdef CONFIG_HIGHMEM
4443+ origmap = pageset1_map;
4444+ copymap = pageset1_copy_map;
4445+ suspend_init_nosave_zone_table();
4446+#endif
4447+
4448+ state1 = suspend_action;
4449+ state2 = suspend_debug_state;
4450+ state3 = console_loglevel;
4451+
4452+ for (loop = 0; loop < 4; loop++)
4453+ io_speed_save[loop/2][loop%2] =
4454+ suspend_io_time[loop/2][loop%2];
4455+ memcpy(suspend_resume_commandline, saved_command_line, COMMAND_LINE_SIZE);
4456+
4457+ mb();
4458+
4459+ local_irq_disable();
4460+ if (device_power_down(PMSG_FREEZE)) {
4461+ printk(KERN_ERR "Some devices failed to power down. Very bad.\n");
4462+ BUG();
4463+ }
4464+
4465+ /* We'll ignore saved state, but this gets preempt count (etc) right */
4466+ save_processor_state();
4467+ error = swsusp_arch_resume();
4468+ /* Code below is only ever reached in case of failure. Otherwise
4469+ * execution continues at place where swsusp_arch_suspend was called.
4470+ */
4471+ BUG();
4472+ return 1;
4473+}
4474diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
4475new file mode 100644
4476index 0000000..267fab4
4477--- /dev/null
4478+++ b/kernel/power/block_io.h
4479@@ -0,0 +1,56 @@
4480+/*
4481+ * kernel/power/block_io.h
4482+ *
4483+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
4484+ * Copyright (C) 2006 Red Hat, inc.
4485+ *
4486+ * Distributed under GPLv2.
4487+ *
4488+ * This file contains declarations for functions exported from
4489+ * block_io.c, which contains low level io functions.
4490+ */
4491+
4492+#include <linux/buffer_head.h>
4493+#include "extent.h"
4494+
4495+struct suspend_bdev_info {
4496+ struct block_device *bdev;
4497+ dev_t dev_t;
4498+ int bmap_shift;
4499+ int blocks_per_page;
4500+};
4501+
4502+/*
4503+ * Our exported interface so the swapwriter and filewriter don't
4504+ * need these functions duplicated.
4505+ */
4506+struct suspend_bio_ops {
4507+ int (*bdev_page_io) (int rw, struct block_device *bdev, long pos,
4508+ struct page *page);
4509+ void (*check_io_stats) (void);
4510+ void (*reset_io_stats) (void);
4511+ void (*finish_all_io) (void);
4512+ int (*prepare_readahead) (int index);
4513+ void (*cleanup_readahead) (int index);
4514+ struct page ** readahead_pages;
4515+ int (*readahead_ready) (int readahead_index);
4516+ int (*forward_one_page) (void);
4517+ void (*set_extra_page_forward) (void);
4518+ void (*set_devinfo) (struct suspend_bdev_info *info);
4519+ int (*read_chunk) (struct page *buffer_page, int sync);
4520+ int (*write_chunk) (struct page *buffer_page);
4521+ int (*rw_header_chunk) (int rw, struct suspend_module_ops *owner,
4522+ char *buffer, int buffer_size);
4523+ int (*write_header_chunk_finish) (void);
4524+ int (*rw_init) (int rw, int stream_number);
4525+ int (*rw_cleanup) (int rw);
4526+};
4527+
4528+extern struct suspend_bio_ops suspend_bio_ops;
4529+
4530+extern char *suspend_writer_buffer;
4531+extern int suspend_writer_buffer_posn;
4532+extern int suspend_read_fd;
4533+extern struct extent_iterate_saved_state suspend_writer_posn_save[3];
4534+extern struct extent_iterate_state suspend_writer_posn;
4535+extern int suspend_header_bytes_used;
4536diff --git a/kernel/power/checksum.c b/kernel/power/checksum.c
4537new file mode 100644
4538index 0000000..04b89b0
4539--- /dev/null
4540+++ b/kernel/power/checksum.c
4541@@ -0,0 +1,322 @@
4542+/*
4543+ * kernel/power/checksum.c
4544+ *
4545+ * Copyright (C) 2006 Nigel Cunningham <nigel@suspend2.net>
4546+ * Copyright (C) 2006 Red Hat, inc.
4547+ *
4548+ * This file is released under the GPLv2.
4549+ *
4550+ * This file contains data checksum routines for suspend2,
4551+ * using cryptoapi. They are used to locate any modifications
4552+ * made to pageset 2 while we're saving it.
4553+ */
4554+
4555+#include <linux/suspend.h>
4556+#include <linux/module.h>
4557+#include <linux/highmem.h>
4558+#include <linux/vmalloc.h>
4559+#include <linux/crypto.h>
4560+#include <linux/scatterlist.h>
4561+
4562+#include "suspend.h"
4563+#include "modules.h"
4564+#include "sysfs.h"
4565+#include "io.h"
4566+#include "pageflags.h"
4567+
4568+static struct suspend_module_ops suspend_checksum_ops;
4569+
4570+/* Constant at the mo, but I might allow tuning later */
4571+static char suspend_checksum_name[32] = "md5";
4572+/* Bytes per checksum */
4573+#define CHECKSUM_SIZE (128 / 8)
4574+
4575+#define CHECKSUMS_PER_PAGE ((PAGE_SIZE - sizeof(void *)) / CHECKSUM_SIZE)
4576+
4577+static struct crypto_hash *suspend_checksum_transform;
4578+static struct hash_desc desc;
4579+static int pages_allocated;
4580+static unsigned long page_list;
4581+
4582+int suspend_num_resaved = 0;
4583+
4584+#if 1
4585+#define PRINTK(a, b...) do { } while(0)
4586+#else
4587+#define PRINTK(a, b...) do { printk(a, ##b); } while(0)
4588+#endif
4589+
4590+/* ---- Local buffer management ---- */
4591+
4592+/*
4593+ * suspend_checksum_cleanup
4594+ *
4595+ * Frees memory allocated for our labours.
4596+ */
4597+static void suspend_checksum_cleanup(int ending_cycle)
4598+{
4599+ if (ending_cycle && suspend_checksum_transform) {
4600+ crypto_free_hash(suspend_checksum_transform);
4601+ suspend_checksum_transform = NULL;
4602+ desc.tfm = NULL;
4603+ }
4604+}
4605+
4606+/*
4607+ * suspend_crypto_prepare
4608+ *
4609+ * Prepare to do some work by allocating buffers and transforms.
4610+ * Returns: Int: Zero. Even if we can't set up checksum, we still
4611+ * seek to suspend.
4612+ */
4613+static int suspend_checksum_prepare(int starting_cycle)
4614+{
4615+ if (!starting_cycle || !suspend_checksum_ops.enabled)
4616+ return 0;
4617+
4618+ if (!*suspend_checksum_name) {
4619+ printk("Suspend2: No checksum algorithm name set.\n");
4620+ return 1;
4621+ }
4622+
4623+ suspend_checksum_transform = crypto_alloc_hash(suspend_checksum_name, 0, 0);
4624+ if (IS_ERR(suspend_checksum_transform)) {
4625+ printk("Suspend2: Failed to initialise the %s checksum algorithm: %ld.\n",
4626+ suspend_checksum_name,
4627+ (long) suspend_checksum_transform);
4628+ suspend_checksum_transform = NULL;
4629+ return 1;
4630+ }
4631+
4632+ desc.tfm = suspend_checksum_transform;
4633+ desc.flags = 0;
4634+
4635+ return 0;
4636+}
4637+
4638+/*
4639+ * suspend_checksum_print_debug_stats
4640+ * @buffer: Pointer to a buffer into which the debug info will be printed.
4641+ * @size: Size of the buffer.
4642+ *
4643+ * Print information to be recorded for debugging purposes into a buffer.
4644+ * Returns: Number of characters written to the buffer.
4645+ */
4646+
4647+static int suspend_checksum_print_debug_stats(char *buffer, int size)
4648+{
4649+ int len;
4650+
4651+ if (!suspend_checksum_ops.enabled)
4652+ return snprintf_used(buffer, size,
4653+ "- Checksumming disabled.\n");
4654+
4655+ len = snprintf_used(buffer, size, "- Checksum method is '%s'.\n",
4656+ suspend_checksum_name);
4657+ len+= snprintf_used(buffer + len, size - len,
4658+ " %d pages resaved in atomic copy.\n", suspend_num_resaved);
4659+ return len;
4660+}
4661+
4662+static int suspend_checksum_storage_needed(void)
4663+{
4664+ if (suspend_checksum_ops.enabled)
4665+ return strlen(suspend_checksum_name) + sizeof(int) + 1;
4666+ else
4667+ return 0;
4668+}
4669+
4670+/*
4671+ * suspend_checksum_save_config_info
4672+ * @buffer: Pointer to a buffer of size PAGE_SIZE.
4673+ *
4674+ * Save informaton needed when reloading the image at resume time.
4675+ * Returns: Number of bytes used for saving our data.
4676+ */
4677+static int suspend_checksum_save_config_info(char *buffer)
4678+{
4679+ int namelen = strlen(suspend_checksum_name) + 1;
4680+ int total_len;
4681+
4682+ *((unsigned int *) buffer) = namelen;
4683+ strncpy(buffer + sizeof(unsigned int), suspend_checksum_name,
4684+ namelen);
4685+ total_len = sizeof(unsigned int) + namelen;
4686+ return total_len;
4687+}
4688+
4689+/* suspend_checksum_load_config_info
4690+ * @buffer: Pointer to the start of the data.
4691+ * @size: Number of bytes that were saved.
4692+ *
4693+ * Description: Reload information needed for dechecksuming the image at
4694+ * resume time.
4695+ */
4696+static void suspend_checksum_load_config_info(char *buffer, int size)
4697+{
4698+ int namelen;
4699+
4700+ namelen = *((unsigned int *) (buffer));
4701+ strncpy(suspend_checksum_name, buffer + sizeof(unsigned int),
4702+ namelen);
4703+ return;
4704+}
4705+
4706+/*
4707+ * Free Checksum Memory
4708+ */
4709+
4710+void free_checksum_pages(void)
4711+{
4712+ PRINTK("Freeing %d checksum pages.\n", pages_allocated);
4713+ while (pages_allocated) {
4714+ unsigned long next = *((unsigned long *) page_list);
4715+ PRINTK("Page %3d is at %lx and points to %lx.\n", pages_allocated, page_list, next);
4716+ ClearPageNosave(virt_to_page(page_list));
4717+ free_page((unsigned long) page_list);
4718+ page_list = next;
4719+ pages_allocated--;
4720+ }
4721+}
4722+
4723+/*
4724+ * Allocate Checksum Memory
4725+ */
4726+
4727+int allocate_checksum_pages(void)
4728+{
4729+ int pages_needed = DIV_ROUND_UP(pagedir2.size, CHECKSUMS_PER_PAGE);
4730+
4731+ if (!suspend_checksum_ops.enabled)
4732+ return 0;
4733+
4734+ PRINTK("Need %d checksum pages for %ld pageset2 pages.\n", pages_needed, pagedir2.size);
4735+ while (pages_allocated < pages_needed) {
4736+ unsigned long *new_page =
4737+ (unsigned long *) get_zeroed_page(GFP_ATOMIC);
4738+ if (!new_page)
4739+ return -ENOMEM;
4740+ SetPageNosave(virt_to_page(new_page));
4741+ (*new_page) = page_list;
4742+ page_list = (unsigned long) new_page;
4743+ pages_allocated++;
4744+ PRINTK("Page %3d is at %lx and points to %lx.\n", pages_allocated, page_list, *((unsigned long *) page_list));
4745+ }
4746+
4747+ return 0;
4748+}
4749+
4750+void print_checksum(char *buf, int size)
4751+{
4752+ int index;
4753+
4754+ for (index = 0; index < size; index++)
4755+ printk("%x ", buf[index]);
4756+
4757+ printk("\n");
4758+}
4759+
4760+/*
4761+ * Calculate checksums
4762+ */
4763+
4764+void calculate_check_checksums(int check)
4765+{
4766+ int pfn, index = 0;
4767+ unsigned long next_page, this_checksum = 0;
4768+ struct scatterlist sg[2];
4769+ char current_checksum[CHECKSUM_SIZE];
4770+
4771+ if (!suspend_checksum_ops.enabled)
4772+ return;
4773+
4774+ next_page = (unsigned long) page_list;
4775+
4776+ if (check)
4777+ suspend_num_resaved = 0;
4778+
4779+ BITMAP_FOR_EACH_SET(pageset2_map, pfn) {
4780+ int ret;
4781+ if (index % CHECKSUMS_PER_PAGE) {
4782+ this_checksum += CHECKSUM_SIZE;
4783+ } else {
4784+ this_checksum = next_page + sizeof(void *);
4785+ next_page = *((unsigned long *) next_page);
4786+ }
4787+ PRINTK("Put checksum for page %3d %p in %lx.\n", index, page_address(pfn_to_page(pfn)), this_checksum);
4788+ sg_set_buf(&sg[0], page_address(pfn_to_page(pfn)), PAGE_SIZE);
4789+ if (check) {
4790+ ret = crypto_hash_digest(&desc, sg,
4791+ PAGE_SIZE, current_checksum);
4792+ if (memcmp(current_checksum, (char *) this_checksum, CHECKSUM_SIZE)) {
4793+ SetPageResave(pfn_to_page(pfn));
4794+ printk("Page %d changed. Saving in atomic copy.\n", pfn);
4795+ suspend_num_resaved++;
4796+ if (test_action_state(SUSPEND_ABORT_ON_RESAVE_NEEDED))
4797+ set_result_state(SUSPEND_ABORTED);
4798+ }
4799+ } else
4800+ ret = crypto_hash_digest(&desc, sg,
4801+ PAGE_SIZE, (char *) this_checksum);
4802+ if (ret) {
4803+ printk("Digest failed. Returned %d.\n", ret);
4804+ BUG();
4805+ }
4806+ index++;
4807+ }
4808+}
4809+
4810+static struct suspend_sysfs_data sysfs_params[] = {
4811+ { SUSPEND2_ATTR("enabled", SYSFS_RW),
4812+ SYSFS_INT(&suspend_checksum_ops.enabled, 0, 1)
4813+ },
4814+
4815+ { SUSPEND2_ATTR("abort_if_resave_needed", SYSFS_RW),
4816+ SYSFS_BIT(&suspend_action, SUSPEND_ABORT_ON_RESAVE_NEEDED)
4817+ }
4818+};
4819+
4820+/*
4821+ * Ops structure.
4822+ */
4823+static struct suspend_module_ops suspend_checksum_ops = {
4824+ .type = MISC_MODULE,
4825+ .name = "Checksumming",
4826+ .directory = "checksum",
4827+ .module = THIS_MODULE,
4828+ .initialise = suspend_checksum_prepare,
4829+ .cleanup = suspend_checksum_cleanup,
4830+ .print_debug_info = suspend_checksum_print_debug_stats,
4831+ .save_config_info = suspend_checksum_save_config_info,
4832+ .load_config_info = suspend_checksum_load_config_info,
4833+ .storage_needed = suspend_checksum_storage_needed,
4834+
4835+ .sysfs_data = sysfs_params,
4836+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
4837+};
4838+
4839+/* ---- Registration ---- */
4840+
4841+static __init int suspend_checksum_load(void)
4842+{
4843+ int result = suspend_register_module(&suspend_checksum_ops);
4844+
4845+ /* Disabled by default */
4846+ suspend_checksum_ops.enabled = 0;
4847+ return result;
4848+}
4849+
4850+#ifdef MODULE
4851+static __exit void suspend_checksum_unload(void)
4852+{
4853+ suspend_unregister_module(&suspend_checksum_ops);
4854+}
4855+
4856+module_init(suspend_checksum_load);
4857+module_exit(suspend_checksum_unload);
4858+MODULE_LICENSE("GPL");
4859+MODULE_AUTHOR("Nigel Cunningham");
4860+MODULE_DESCRIPTION("Checksum Support for Suspend2");
4861+#else
4862+late_initcall(suspend_checksum_load);
4863+#endif
4864diff --git a/kernel/power/checksum.h b/kernel/power/checksum.h
4865new file mode 100644
4866index 0000000..f2232e8
4867--- /dev/null
4868+++ b/kernel/power/checksum.h
4869@@ -0,0 +1,3 @@
4870+void calculate_check_checksums(int check);
4871+int allocate_checksum_pages(void);
4872+void free_checksum_pages(void);
4873diff --git a/kernel/power/compression.c b/kernel/power/compression.c
4874new file mode 100644
4875index 0000000..346fa95
4876--- /dev/null
4877+++ b/kernel/power/compression.c
4878@@ -0,0 +1,520 @@
4879+/*
4880+ * kernel/power/compression.c
4881+ *
4882+ * Copyright (C) 2003-2006 Nigel Cunningham <nigel@suspend2.net>
4883+ * Copyright (C) 2006 Red Hat, inc.
4884+ *
4885+ * This file is released under the GPLv2.
4886+ *
4887+ * This file contains data compression routines for suspend,
4888+ * using cryptoapi.
4889+ */
4890+
4891+#include <linux/suspend.h>
4892+#include <linux/module.h>
4893+#include <linux/highmem.h>
4894+#include <linux/vmalloc.h>
4895+#include <linux/crypto.h>
4896+
4897+#include "suspend.h"
4898+#include "modules.h"
4899+#include "sysfs.h"
4900+#include "io.h"
4901+
4902+static int suspend_expected_compression = 0;
4903+
4904+static struct suspend_module_ops suspend_compression_ops;
4905+static struct suspend_module_ops *next_driver;
4906+
4907+static char suspend_compressor_name[32] = "lzf";
4908+static struct crypto_tfm *suspend_compressor_transform;
4909+
4910+static u8 *local_buffer = NULL;
4911+static u8 *page_buffer = NULL;
4912+static unsigned int bufofs;
4913+
4914+/* Compression ratio */
4915+static __nosavedata unsigned long bytes_in = 0, bytes_out = 0;
4916+
4917+/* ---- Local buffer management ---- */
4918+
4919+/*
4920+ * suspend_compress_allocate_local_buffer
4921+ *
4922+ * Allocates a page of memory for buffering output.
4923+ * Int: Zero if successful, -ENONEM otherwise.
4924+ */
4925+static int suspend_compress_allocate_local_buffer(void)
4926+{
4927+ local_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
4928+
4929+ if (!local_buffer) {
4930+ printk(KERN_ERR
4931+ "Failed to allocate the local buffer for "
4932+ "suspend2 compression driver.\n");
4933+ return -ENOMEM;
4934+ }
4935+
4936+ page_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
4937+
4938+ if (!page_buffer) {
4939+ printk(KERN_ERR
4940+ "Failed to allocate the page buffer for "
4941+ "suspend2 compression driver.\n");
4942+ return -ENOMEM;
4943+ }
4944+
4945+ return 0;
4946+}
4947+
4948+/*
4949+ * suspend_compress_free_local_buffer
4950+ *
4951+ * Frees memory allocated for buffering output.
4952+ */
4953+static inline void suspend_compress_free_local_buffer(void)
4954+{
4955+ if (local_buffer)
4956+ free_page((unsigned long) local_buffer);
4957+
4958+ local_buffer = NULL;
4959+
4960+ if (page_buffer)
4961+ free_page((unsigned long) page_buffer);
4962+
4963+ page_buffer = NULL;
4964+}
4965+
4966+/*
4967+ * suspend_compress_cleanup
4968+ *
4969+ * Frees memory allocated for our labours.
4970+ */
4971+static void suspend_compress_cleanup(void)
4972+{
4973+ if (suspend_compressor_transform) {
4974+ crypto_free_tfm(suspend_compressor_transform);
4975+ suspend_compressor_transform = NULL;
4976+ }
4977+}
4978+
4979+/*
4980+ * suspend_crypto_prepare
4981+ *
4982+ * Prepare to do some work by allocating buffers and transforms.
4983+ * Returns: Int: Zero. Even if we can't set up compression, we still
4984+ * seek to suspend.
4985+ */
4986+static void suspend_compress_crypto_prepare(void)
4987+{
4988+ if (!*suspend_compressor_name) {
4989+ printk("Suspend2: Compression enabled but no compressor name set.\n");
4990+ suspend_compression_ops.enabled = 0;
4991+ return;
4992+ }
4993+
4994+ if (!(suspend_compressor_transform = crypto_alloc_tfm(suspend_compressor_name, 0))) {
4995+ printk("Suspend2: Failed to initialise the %s compression transform.\n",
4996+ suspend_compressor_name);
4997+ suspend_compression_ops.enabled = 0;
4998+ }
4999+}
5000+
5001+/*
5002+ * suspend_compress_write_cleanup(): Write unflushed data and free workspace.
5003+ *
5004+ * Returns: Result of writing last page.
5005+ */
5006+static int suspend_compress_rw_cleanup(int rw)
5007+{
5008+ int ret = 0;
5009+
5010+ if (rw == WRITE && suspend_compressor_transform)
5011+ ret = next_driver->write_chunk(virt_to_page(local_buffer));
5012+
5013+ suspend_compress_cleanup();
5014+ suspend_compress_free_local_buffer();
5015+
5016+ return ret;
5017+}
5018+
5019+/*
5020+ * suspend_compress_rw_init()
5021+ * @stream_number: Ignored.
5022+ *
5023+ * Allocate buffers and prepare to compress data.
5024+ * Returns: Zero on success, -ENOMEM if unable to vmalloc.
5025+ */
5026+static int suspend_compress_rw_init(int rw, int stream_number)
5027+{
5028+ int result;
5029+
5030+ next_driver = suspend_get_next_filter(&suspend_compression_ops);
5031+
5032+ if (!next_driver) {
5033+ printk("Compression Driver: Argh! Nothing follows me in"
5034+ " the pipeline!");
5035+ return -ECHILD;
5036+ }
5037+
5038+ suspend_compress_crypto_prepare();
5039+
5040+ if (!suspend_compression_ops.enabled)
5041+ return 0;
5042+
5043+ if ((result = suspend_compress_allocate_local_buffer()))
5044+ return result;
5045+
5046+ if (rw == READ)
5047+ bufofs = PAGE_SIZE;
5048+ else
5049+ bufofs = 0;
5050+
5051+ return 0;
5052+}
5053+
5054+/*
5055+ * suspend_compress_write()
5056+ * @u8*: Output buffer to be written.
5057+ * @unsigned int: Length of buffer.
5058+ *
5059+ * Helper function for write_chunk. Write the compressed data.
5060+ * Return: Int. Result to be passed back to caller.
5061+ */
5062+static int suspend_compress_write (u8 *buffer, unsigned int len)
5063+{
5064+ int ret;
5065+
5066+ bytes_out += len;
5067+
5068+ while (len + bufofs > PAGE_SIZE) {
5069+ unsigned int chunk = PAGE_SIZE - bufofs;
5070+ memcpy (local_buffer + bufofs, buffer, chunk);
5071+ buffer += chunk;
5072+ len -= chunk;
5073+ bufofs = 0;
5074+ if ((ret = next_driver->write_chunk(virt_to_page(local_buffer))) < 0)
5075+ return ret;
5076+ }
5077+ memcpy (local_buffer + bufofs, buffer, len);
5078+ bufofs += len;
5079+ return 0;
5080+}
5081+
5082+/*
5083+ * suspend_compress_write_chunk()
5084+ *
5085+ * Compress a page of data, buffering output and passing on filled
5086+ * pages to the next module in the pipeline.
5087+ *
5088+ * Buffer_page: Pointer to a buffer of size PAGE_SIZE, containing
5089+ * data to be compressed.
5090+ *
5091+ * Returns: 0 on success. Otherwise the error is that returned by later
5092+ * modules, -ECHILD if we have a broken pipeline or -EIO if
5093+ * zlib errs.
5094+ */
5095+static int suspend_compress_write_chunk(struct page *buffer_page)
5096+{
5097+ int ret;
5098+ unsigned int len;
5099+ u16 len_written;
5100+ char *buffer_start;
5101+
5102+ if (!suspend_compressor_transform)
5103+ return next_driver->write_chunk(buffer_page);
5104+
5105+ buffer_start = kmap(buffer_page);
5106+
5107+ bytes_in += PAGE_SIZE;
5108+
5109+ len = PAGE_SIZE;
5110+
5111+ ret = crypto_comp_compress(suspend_compressor_transform,
5112+ buffer_start, PAGE_SIZE,
5113+ page_buffer, &len);
5114+
5115+ if (ret) {
5116+ printk("Compression failed.\n");
5117+ goto failure;
5118+ }
5119+
5120+ len_written = (u16) len;
5121+
5122+ if ((ret = suspend_compress_write((u8 *)&len_written, 2)) >= 0) {
5123+ if (len < PAGE_SIZE) /* some compression */
5124+ ret = suspend_compress_write(page_buffer, len);
5125+ else
5126+ ret = suspend_compress_write(buffer_start, PAGE_SIZE);
5127+ }
5128+
5129+failure:
5130+ kunmap(buffer_page);
5131+ return ret;
5132+}
5133+
5134+/*
5135+ * suspend_compress_read()
5136+ * @buffer: u8 *. Address of the buffer.
5137+ * @len: unsigned int. Length.
5138+ *
5139+ * Description: Read data into compression buffer.
5140+ * Returns: int: Result of reading the image chunk.
5141+ */
5142+static int suspend_compress_read (u8 *buffer, unsigned int len)
5143+{
5144+ int ret;
5145+
5146+ while (len + bufofs > PAGE_SIZE) {
5147+ unsigned int chunk = PAGE_SIZE - bufofs;
5148+ memcpy(buffer, local_buffer + bufofs, chunk);
5149+ buffer += chunk;
5150+ len -= chunk;
5151+ bufofs = 0;
5152+ if ((ret = next_driver->read_chunk(
5153+ virt_to_page(local_buffer), SUSPEND_SYNC)) < 0) {
5154+ return ret;
5155+ }
5156+ }
5157+ memcpy (buffer, local_buffer + bufofs, len);
5158+ bufofs += len;
5159+ return 0;
5160+}
5161+
5162+/*
5163+ * suspend_compress_read_chunk()
5164+ * @buffer_page: struct page *. Pointer to a buffer of size PAGE_SIZE.
5165+ * @sync: int. Whether the previous module (or core) wants its data synchronously.
5166+ *
5167+ * Retrieve data from later modules and decompress it until the input buffer
5168+ * is filled.
5169+ * Zero if successful. Error condition from me or from downstream on failure.
5170+ */
5171+static int suspend_compress_read_chunk(struct page *buffer_page, int sync)
5172+{
5173+ int ret;
5174+ unsigned int len;
5175+ u16 len_written;
5176+ char *buffer_start;
5177+
5178+ if (!suspend_compressor_transform)
5179+ return next_driver->read_chunk(buffer_page, SUSPEND_ASYNC);
5180+
5181+ /*
5182+ * All our reads must be synchronous - we can't decompress
5183+ * data that hasn't been read yet.
5184+ */
5185+
5186+ buffer_start = kmap(buffer_page);
5187+
5188+ if ((ret = suspend_compress_read ((u8 *)&len_written, 2)) >= 0) {
5189+ len = (unsigned int) len_written;
5190+
5191+ if (len >= PAGE_SIZE) { /* uncompressed */
5192+ ret = suspend_compress_read(buffer_start, PAGE_SIZE);
5193+ if (ret)
5194+ return ret;
5195+ } else { /* compressed */
5196+ if ((ret = suspend_compress_read(page_buffer, len)) >= 0) {
5197+ int outlen = PAGE_SIZE;
5198+ crypto_comp_decompress(suspend_compressor_transform,
5199+ page_buffer, len,
5200+ buffer_start, &outlen);
5201+ if (outlen != PAGE_SIZE) {
5202+ printk("Decompression yielded %d bytes instead of %ld.\n", outlen, PAGE_SIZE);
5203+ ret = -EIO;
5204+ } else
5205+ ret = 0;
5206+ }
5207+ }
5208+ } else
5209+ printk("Compress_read returned %d.\n", ret);
5210+ kunmap(buffer_page);
5211+ return ret;
5212+}
5213+
5214+/*
5215+ * suspend_compress_print_debug_stats
5216+ * @buffer: Pointer to a buffer into which the debug info will be printed.
5217+ * @size: Size of the buffer.
5218+ *
5219+ * Print information to be recorded for debugging purposes into a buffer.
5220+ * Returns: Number of characters written to the buffer.
5221+ */
5222+
5223+static int suspend_compress_print_debug_stats(char *buffer, int size)
5224+{
5225+ int pages_in = bytes_in >> PAGE_SHIFT,
5226+ pages_out = bytes_out >> PAGE_SHIFT;
5227+ int len;
5228+
5229+ /* Output the compression ratio achieved. */
5230+ if (*suspend_compressor_name)
5231+ len = snprintf_used(buffer, size, "- Compressor is '%s'.\n",
5232+ suspend_compressor_name);
5233+ else
5234+ len = snprintf_used(buffer, size, "- Compressor is not set.\n");
5235+
5236+ if (pages_in)
5237+ len+= snprintf_used(buffer+len, size - len,
5238+ " Compressed %ld bytes into %ld (%d percent compression).\n",
5239+ bytes_in, bytes_out, (pages_in - pages_out) * 100 / pages_in);
5240+ return len;
5241+}
5242+
5243+/*
5244+ * suspend_compress_compression_memory_needed
5245+ *
5246+ * Tell the caller how much memory we need to operate during suspend/resume.
5247+ * Returns: Unsigned long. Maximum number of bytes of memory required for
5248+ * operation.
5249+ */
5250+static int suspend_compress_memory_needed(void)
5251+{
5252+ return 2 * PAGE_SIZE;
5253+}
5254+
5255+static int suspend_compress_storage_needed(void)
5256+{
5257+ return 4 * sizeof(unsigned long) + strlen(suspend_compressor_name) + 1;
5258+}
5259+
5260+/*
5261+ * suspend_compress_save_config_info
5262+ * @buffer: Pointer to a buffer of size PAGE_SIZE.
5263+ *
5264+ * Save informaton needed when reloading the image at resume time.
5265+ * Returns: Number of bytes used for saving our data.
5266+ */
5267+static int suspend_compress_save_config_info(char *buffer)
5268+{
5269+ int namelen = strlen(suspend_compressor_name) + 1;
5270+ int total_len;
5271+
5272+ *((unsigned long *) buffer) = bytes_in;
5273+ *((unsigned long *) (buffer + 1 * sizeof(unsigned long))) = bytes_out;
5274+ *((unsigned long *) (buffer + 2 * sizeof(unsigned long))) =
5275+ suspend_expected_compression;
5276+ *((unsigned long *) (buffer + 3 * sizeof(unsigned long))) = namelen;
5277+ strncpy(buffer + 4 * sizeof(unsigned long), suspend_compressor_name,
5278+ namelen);
5279+ total_len = 4 * sizeof(unsigned long) + namelen;
5280+ return total_len;
5281+}
5282+
5283+/* suspend_compress_load_config_info
5284+ * @buffer: Pointer to the start of the data.
5285+ * @size: Number of bytes that were saved.
5286+ *
5287+ * Description: Reload information needed for decompressing the image at
5288+ * resume time.
5289+ */
5290+static void suspend_compress_load_config_info(char *buffer, int size)
5291+{
5292+ int namelen;
5293+
5294+ bytes_in = *((unsigned long *) buffer);
5295+ bytes_out = *((unsigned long *) (buffer + 1 * sizeof(unsigned long)));
5296+ suspend_expected_compression = *((unsigned long *) (buffer + 2 *
5297+ sizeof(unsigned long)));
5298+ namelen = *((unsigned long *) (buffer + 3 * sizeof(unsigned long)));
5299+ strncpy(suspend_compressor_name, buffer + 4 * sizeof(unsigned long),
5300+ namelen);
5301+ return;
5302+}
5303+
5304+/*
5305+ * suspend_expected_compression_ratio
5306+ *
5307+ * Description: Returns the expected ratio between data passed into this module
5308+ * and the amount of data output when writing.
5309+ * Returns: 100 if the module is disabled. Otherwise the value set by the
5310+ * user via our sysfs entry.
5311+ */
5312+
5313+int suspend_expected_compression_ratio(void)
5314+{
5315+ if (!suspend_compression_ops.enabled)
5316+ return 100;
5317+ else
5318+ return 100 - suspend_expected_compression;
5319+}
5320+
5321+/*
5322+ * suspend_compress_init
5323+ *
5324+ */
5325+
5326+static int suspend_compress_init(int starting_cycle)
5327+{
5328+ if (starting_cycle)
5329+ bytes_in = bytes_out = 0;
5330+ return 0;
5331+}
5332+
5333+/*
5334+ * data for our sysfs entries.
5335+ */
5336+static struct suspend_sysfs_data sysfs_params[] = {
5337+ {
5338+ SUSPEND2_ATTR("expected_compression", SYSFS_RW),
5339+ SYSFS_INT(&suspend_expected_compression, 0, 99)
5340+ },
5341+
5342+ {
5343+ SUSPEND2_ATTR("enabled", SYSFS_RW),
5344+ SYSFS_INT(&suspend_compression_ops.enabled, 0, 1)
5345+ },
5346+
5347+ {
5348+ SUSPEND2_ATTR("algorithm", SYSFS_RW),
5349+ SYSFS_STRING(suspend_compressor_name, 31, SYSFS_SM_NOT_NEEDED)
5350+ }
5351+};
5352+
5353+/*
5354+ * Ops structure.
5355+ */
5356+static struct suspend_module_ops suspend_compression_ops = {
5357+ .type = FILTER_MODULE,
5358+ .name = "Compressor",
5359+ .directory = "compression",
5360+ .module = THIS_MODULE,
5361+ .initialise = suspend_compress_init,
5362+ .memory_needed = suspend_compress_memory_needed,
5363+ .print_debug_info = suspend_compress_print_debug_stats,
5364+ .save_config_info = suspend_compress_save_config_info,
5365+ .load_config_info = suspend_compress_load_config_info,
5366+ .storage_needed = suspend_compress_storage_needed,
5367+
5368+ .rw_init = suspend_compress_rw_init,
5369+ .rw_cleanup = suspend_compress_rw_cleanup,
5370+
5371+ .write_chunk = suspend_compress_write_chunk,
5372+ .read_chunk = suspend_compress_read_chunk,
5373+
5374+ .sysfs_data = sysfs_params,
5375+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
5376+};
5377+
5378+/* ---- Registration ---- */
5379+
5380+static __init int suspend_compress_load(void)
5381+{
5382+ return suspend_register_module(&suspend_compression_ops);
5383+}
5384+
5385+#ifdef MODULE
5386+static __exit void suspend_compress_unload(void)
5387+{
5388+ suspend_unregister_module(&suspend_compression_ops);
5389+}
5390+
5391+module_init(suspend_compress_load);
5392+module_exit(suspend_compress_unload);
5393+MODULE_LICENSE("GPL");
5394+MODULE_AUTHOR("Nigel Cunningham");
5395+MODULE_DESCRIPTION("Compression Support for Suspend2");
5396+#else
5397+late_initcall(suspend_compress_load);
5398+#endif
5399diff --git a/kernel/power/disk.c b/kernel/power/disk.c
5400index b1fb786..08babe4 100644
5401--- a/kernel/power/disk.c
5402+++ b/kernel/power/disk.c
5403@@ -10,6 +10,7 @@
5404 */
5405
5406 #include <linux/suspend.h>
5407+#include <linux/freezer.h>
5408 #include <linux/syscalls.h>
5409 #include <linux/reboot.h>
5410 #include <linux/string.h>
5411@@ -23,6 +24,7 @@ #include <linux/cpu.h>
5412
5413 #include "power.h"
5414
5415+#include "suspend.h"
5416
5417 static int noresume = 0;
5418 char resume_file[256] = CONFIG_PM_STD_PARTITION;
5419@@ -122,6 +124,16 @@ int pm_suspend_disk(void)
5420 {
5421 int error;
5422
5423+#ifdef CONFIG_SUSPEND2
5424+ if (test_action_state(SUSPEND_REPLACE_SWSUSP)) {
5425+ if (suspend_start_anything(1))
5426+ return -EBUSY;
5427+ suspend_main(1);
5428+ suspend_finish_anything(1);
5429+ return 0;
5430+ }
5431+#endif
5432+
5433 error = prepare_processes();
5434 if (error)
5435 return error;
5436@@ -185,10 +197,20 @@ int pm_suspend_disk(void)
5437 *
5438 */
5439
5440-static int software_resume(void)
5441+int software_resume(void)
5442 {
5443 int error;
5444
5445+#ifdef CONFIG_SUSPEND2
5446+ /*
5447+ * We can't know (until an image header - if any - is loaded), whether
5448+ * we did override swsusp. We therefore ensure that both are tried.
5449+ */
5450+ if (test_action_state(SUSPEND_REPLACE_SWSUSP))
5451+ printk("Replacing swsusp.\n");
5452+ suspend2_try_resume();
5453+#endif
5454+
5455 down(&pm_sem);
5456 if (!swsusp_resume_device) {
5457 if (!strlen(resume_file)) {
5458@@ -256,9 +278,6 @@ static int software_resume(void)
5459 return 0;
5460 }
5461
5462-late_initcall(software_resume);
5463-
5464-
5465 static const char * const pm_disk_modes[] = {
5466 [PM_DISK_FIRMWARE] = "firmware",
5467 [PM_DISK_PLATFORM] = "platform",
5468@@ -426,6 +445,7 @@ static int __init resume_setup(char *str
5469 static int __init noresume_setup(char *str)
5470 {
5471 noresume = 1;
5472+ set_suspend_state(SUSPEND_NORESUME_SPECIFIED);
5473 return 1;
5474 }
5475
5476diff --git a/kernel/power/encryption.c b/kernel/power/encryption.c
5477new file mode 100644
5478index 0000000..d25f41e
5479--- /dev/null
5480+++ b/kernel/power/encryption.c
5481@@ -0,0 +1,473 @@
5482+/*
5483+ * kernel/power/encryption.c
5484+ *
5485+ * Copyright (C) 2003-2006 Nigel Cunningham <nigel@suspend2.net>
5486+ * Copyright (C) 2006 Red Hat, inc.
5487+ *
5488+ * This file is released under the GPLv2.
5489+ *
5490+ * This file contains data encryption routines for suspend,
5491+ * using cryptoapi transforms.
5492+ *
5493+ * ToDo:
5494+ * - Apply min/max_keysize the cipher changes.
5495+ * - Test.
5496+ */
5497+
5498+#include <linux/suspend.h>
5499+#include <linux/module.h>
5500+#include <linux/highmem.h>
5501+#include <linux/vmalloc.h>
5502+#include <linux/crypto.h>
5503+#include <asm/scatterlist.h>
5504+
5505+#include "suspend.h"
5506+#include "modules.h"
5507+#include "sysfs.h"
5508+#include "io.h"
5509+
5510+static struct suspend_module_ops suspend_encryption_ops;
5511+static struct suspend_module_ops *next_driver;
5512+
5513+static char suspend_encryptor_name[32];
5514+static struct crypto_blkcipher *suspend_encryptor_transform;
5515+static struct blkcipher_desc suspend_encryptor_desc;
5516+static char suspend_encryptor_key[256];
5517+static int suspend_key_len;
5518+static char suspend_encryptor_iv[256];
5519+static int suspend_encryptor_save_key_and_iv;
5520+
5521+static u8 *page_buffer = NULL;
5522+static unsigned int bufofs;
5523+
5524+static struct scatterlist suspend_crypt_sg[PAGE_SIZE/8];
5525+
5526+/* ---- Local buffer management ---- */
5527+
5528+/* allocate_local_buffer
5529+ *
5530+ * Description: Allocates a page of memory for buffering output.
5531+ * Returns: Int: Zero if successful, -ENONEM otherwise.
5532+ */
5533+static int allocate_local_buffer(void)
5534+{
5535+ if (!page_buffer) {
5536+ int i, remainder;
5537+
5538+ page_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
5539+
5540+ if (!page_buffer) {
5541+ printk(KERN_ERR
5542+ "Failed to allocate the page buffer for "
5543+ "suspend2 encryption driver.\n");
5544+ return -ENOMEM;
5545+ }
5546+
5547+ for (i=0; i < (PAGE_SIZE / suspend_key_len); i++) {
5548+ suspend_crypt_sg[i].page = virt_to_page(page_buffer);
5549+ suspend_crypt_sg[i].offset = suspend_key_len * i;
5550+ suspend_crypt_sg[i].length = suspend_key_len;
5551+ }
5552+
5553+ remainder = PAGE_SIZE % suspend_key_len;
5554+
5555+ if (remainder) {
5556+ suspend_crypt_sg[i].page = virt_to_page(page_buffer);
5557+ suspend_crypt_sg[i].offset = suspend_key_len * i;
5558+ suspend_crypt_sg[i].length = remainder;
5559+ }
5560+ }
5561+
5562+ return 0;
5563+}
5564+
5565+/* free_local_buffer
5566+ *
5567+ * Description: Frees memory allocated for buffering output.
5568+ */
5569+static void free_local_buffer(void)
5570+{
5571+ if (page_buffer)
5572+ free_page((unsigned long) page_buffer);
5573+
5574+ page_buffer = NULL;
5575+}
5576+
5577+/* suspend_encrypt_rw_cleanup
5578+ *
5579+ * Description: Frees memory allocated for our labours.
5580+ */
5581+static int suspend_encrypt_rw_cleanup(int rw)
5582+{
5583+ if (suspend_encryptor_transform) {
5584+ crypto_free_blkcipher(suspend_encryptor_transform);
5585+ suspend_encryptor_transform = NULL;
5586+ }
5587+
5588+ free_local_buffer();
5589+
5590+ return 0;
5591+}
5592+
5593+/* suspend_crypto_prepare
5594+ *
5595+ * Description: Prepare to do some work by allocating buffers and transforms.
5596+ * Returns: Int: Zero if successful, 1 otherwise.
5597+ */
5598+static int suspend_encrypt_rw_prepare(int rw)
5599+{
5600+ int iv_len;
5601+
5602+ if (!*suspend_encryptor_name) {
5603+ printk("Suspend2: Encryptor enabled but no name set.\n");
5604+ suspend_encryption_ops.enabled = 0;
5605+ return 1;
5606+ }
5607+
5608+ suspend_encryptor_desc.tfm = suspend_encryptor_transform;
5609+ suspend_encryptor_desc.flags = 0;
5610+
5611+ suspend_encryptor_transform = crypto_alloc_blkcipher(
5612+ suspend_encryptor_name, 0, 0);
5613+ if (!suspend_encryptor_transform) {
5614+ printk("Suspend2: Failed to initialise the encryption "
5615+ "transform (%s).\n",
5616+ suspend_encryptor_name);
5617+ suspend_encryption_ops.enabled = 0;
5618+ return 1;
5619+ }
5620+
5621+ if (rw == READ)
5622+ bufofs = PAGE_SIZE;
5623+ else
5624+ bufofs = 0;
5625+
5626+ crypto_blkcipher_clear_flags(suspend_encryptor_transform, 0);
5627+
5628+ suspend_key_len = strlen(suspend_encryptor_key);
5629+
5630+ if (crypto_blkcipher_setkey(suspend_encryptor_transform,
5631+ suspend_encryptor_key, suspend_key_len)) {
5632+ printk("%d is an invalid key length for cipher %s.\n",
5633+ suspend_key_len,
5634+ suspend_encryptor_name);
5635+ return 1;
5636+ }
5637+
5638+ iv_len = crypto_blkcipher_ivsize(suspend_encryptor_transform);
5639+
5640+ if (iv_len)
5641+ crypto_blkcipher_set_iv(suspend_encryptor_transform,
5642+ suspend_encryptor_iv,
5643+ iv_len);
5644+
5645+ return 0;
5646+}
5647+
5648+/* ---- Exported functions ---- */
5649+
5650+/* suspend_encrypt_write_chunk()
5651+ *
5652+ * Description: Encrypt a page of data, buffering output and passing on
5653+ * filled pages to the next module in the pipeline.
5654+ * Arguments: Buffer_page: Pointer to a buffer of size PAGE_SIZE,
5655+ * containing data to be encrypted.
5656+ * Returns: 0 on success. Otherwise the error is that returned by later
5657+ * modules, -ECHILD if we have a broken pipeline or -EIO if
5658+ * zlib errs.
5659+ */
5660+static int suspend_encrypt_write_chunk(struct page *buffer_page)
5661+{
5662+ int ret;
5663+ unsigned int len;
5664+ u16 len_written;
5665+ char *buffer_start;
5666+
5667+ if (!suspend_encryptor_transform)
5668+ return next_driver->write_chunk(buffer_page);
5669+
5670+ buffer_start = kmap(buffer_page);
5671+ memcpy(page_buffer, buffer_start, PAGE_SIZE);
5672+ kunmap(buffer_page);
5673+
5674+ len = PAGE_SIZE;
5675+
5676+ ret = crypto_blkcipher_encrypt(&suspend_encryptor_desc,
5677+ suspend_crypt_sg, suspend_crypt_sg, PAGE_SIZE);
5678+
5679+ if (ret) {
5680+ printk("Encryption failed.\n");
5681+ return -EIO;
5682+ }
5683+
5684+ len_written = (u16) len;
5685+
5686+ ret = next_driver->write_chunk(virt_to_page(page_buffer));
5687+
5688+ return ret;
5689+}
5690+
5691+/* rw_init()
5692+ *
5693+ * Description: Prepare to read a new stream of data.
5694+ * Arguments: int: Section of image about to be read.
5695+ * Returns: int: Zero on success, error number otherwise.
5696+ */
5697+static int suspend_encrypt_rw_init(int rw, int stream_number)
5698+{
5699+ int result;
5700+
5701+ next_driver = suspend_get_next_filter(&suspend_encryption_ops);
5702+
5703+ if (!next_driver) {
5704+ printk("Encryption Driver: Argh! I'm at the end of the pipeline!");
5705+ return -ECHILD;
5706+ }
5707+
5708+ if ((result = suspend_encrypt_rw_prepare(rw))) {
5709+ set_result_state(SUSPEND_ENCRYPTION_SETUP_FAILED);
5710+ suspend_encrypt_rw_cleanup(rw);
5711+ return result;
5712+ }
5713+
5714+ if ((result = allocate_local_buffer()))
5715+ return result;
5716+
5717+ bufofs = (rw == READ) ? PAGE_SIZE : 0;
5718+
5719+ return 0;
5720+}
5721+
5722+/* suspend_encrypt_read_chunk()
5723+ *
5724+ * Description: Retrieve data from later modules and deencrypt it until the
5725+ * input buffer is filled.
5726+ * Arguments: Buffer_start: Pointer to a buffer of size PAGE_SIZE.
5727+ * Sync: Whether the previous module (or core) wants its
5728+ * data synchronously.
5729+ * Returns: Zero if successful. Error condition from me or from downstream
5730+ * on failure.
5731+ */
5732+static int suspend_encrypt_read_chunk(struct page *buffer_page, int sync)
5733+{
5734+ int ret;
5735+ char *buffer_start;
5736+
5737+ if (!suspend_encryptor_transform)
5738+ return next_driver->read_chunk(buffer_page, sync);
5739+
5740+ /*
5741+ * All our reads must be synchronous - we can't deencrypt
5742+ * data that hasn't been read yet.
5743+ */
5744+
5745+ if ((ret = next_driver->read_chunk(
5746+ virt_to_page(page_buffer), SUSPEND_SYNC)) < 0) {
5747+ printk("Failed to read an encrypted block.\n");
5748+ return ret;
5749+ }
5750+
5751+ ret = crypto_blkcipher_decrypt(&suspend_encryptor_desc,
5752+ suspend_crypt_sg, suspend_crypt_sg, PAGE_SIZE);
5753+
5754+ if (ret)
5755+ printk("Decrypt function returned %d.\n", ret);
5756+
5757+ buffer_start = kmap(buffer_page);
5758+ memcpy(buffer_start, page_buffer, PAGE_SIZE);
5759+ kunmap(buffer_page);
5760+ return ret;
5761+}
5762+
5763+/* suspend_encrypt_print_debug_stats
5764+ *
5765+ * Description: Print information to be recorded for debugging purposes into a
5766+ * buffer.
5767+ * Arguments: buffer: Pointer to a buffer into which the debug info will be
5768+ * printed.
5769+ * size: Size of the buffer.
5770+ * Returns: Number of characters written to the buffer.
5771+ */
5772+static int suspend_encrypt_print_debug_stats(char *buffer, int size)
5773+{
5774+ int len;
5775+
5776+ if (*suspend_encryptor_name)
5777+ len = snprintf_used(buffer, size, "- Encryptor is '%s'.\n",
5778+ suspend_encryptor_name);
5779+ else
5780+ len = snprintf_used(buffer, size, "- Encryptor is not set.\n");
5781+ return len;
5782+}
5783+
5784+/* encryption_memory_needed
5785+ *
5786+ * Description: Tell the caller how much memory we need to operate during
5787+ * suspend/resume.
5788+ * Returns: Unsigned long. Maximum number of bytes of memory required for
5789+ * operation.
5790+ */
5791+static int suspend_encrypt_memory_needed(void)
5792+{
5793+ return PAGE_SIZE;
5794+}
5795+
5796+static int suspend_encrypt_storage_needed(void)
5797+{
5798+ return 3 + strlen(suspend_encryptor_name) +
5799+ (suspend_encryptor_save_key_and_iv ?
5800+ (4 + strlen(suspend_encryptor_key) +
5801+ strlen(suspend_encryptor_iv)) : 0);
5802+}
5803+
5804+/* suspend_encrypt_save_config_info
5805+ *
5806+ * Description: Save informaton needed when reloading the image at resume time.
5807+ * Arguments: Buffer: Pointer to a buffer of size PAGE_SIZE.
5808+ * Returns: Number of bytes used for saving our data.
5809+ */
5810+static int suspend_encrypt_save_config_info(char *buffer)
5811+{
5812+ int buf_offset, str_size;
5813+
5814+ str_size = strlen(suspend_encryptor_name);
5815+ *buffer = (char) str_size;
5816+ strncpy(buffer + 1, suspend_encryptor_name, str_size + 1);
5817+ buf_offset = str_size + 2;
5818+
5819+ *(buffer + buf_offset) = (char) suspend_encryptor_save_key_and_iv;
5820+ buf_offset++;
5821+
5822+ if (suspend_encryptor_save_key_and_iv) {
5823+
5824+ str_size = strlen(suspend_encryptor_key);
5825+ *(buffer + buf_offset) = (char) str_size;
5826+ strncpy(buffer + buf_offset + 1, suspend_encryptor_key, str_size + 1);
5827+
5828+ buf_offset += str_size + 2;
5829+
5830+ str_size = strlen(suspend_encryptor_iv);
5831+ *(buffer + buf_offset) = (char) str_size;
5832+ strncpy(buffer + buf_offset + 1, suspend_encryptor_iv, str_size + 1);
5833+
5834+ buf_offset += str_size + 2;
5835+ }
5836+
5837+ return buf_offset;
5838+}
5839+
5840+/* suspend_encrypt_load_config_info
5841+ *
5842+ * Description: Reload information needed for deencrypting the image at
5843+ * resume time.
5844+ * Arguments: Buffer: Pointer to the start of the data.
5845+ * Size: Number of bytes that were saved.
5846+ */
5847+static void suspend_encrypt_load_config_info(char *buffer, int size)
5848+{
5849+ int buf_offset, str_size;
5850+
5851+ str_size = (int) *buffer;
5852+ strncpy(suspend_encryptor_name, buffer + 1, str_size + 1);
5853+ buf_offset = str_size + 2;
5854+
5855+ suspend_encryptor_save_key_and_iv = (int) *(buffer + buf_offset);
5856+ buf_offset++;
5857+
5858+ if (suspend_encryptor_save_key_and_iv) {
5859+ str_size = (int) *(buffer + buf_offset);
5860+ strncpy(suspend_encryptor_key, buffer + buf_offset + 1, str_size + 1);
5861+
5862+ buf_offset += str_size + 2;
5863+
5864+ str_size = (int) *(buffer + buf_offset);
5865+ strncpy(suspend_encryptor_iv, buffer + buf_offset + 1, str_size + 1);
5866+
5867+ buf_offset += str_size + 2;
5868+ }
5869+
5870+ if (buf_offset != size) {
5871+ printk("Suspend Encryptor config info size mismatch (%d != %d): settings ignored.\n",
5872+ buf_offset, size);
5873+ *suspend_encryptor_key = 0;
5874+ *suspend_encryptor_iv = 0;
5875+ }
5876+ return;
5877+}
5878+
5879+/*
5880+ * data for our sysfs entries.
5881+ */
5882+static struct suspend_sysfs_data sysfs_params[] = {
5883+ {
5884+ SUSPEND2_ATTR("algorithm", SYSFS_RW),
5885+ SYSFS_STRING(suspend_encryptor_name, 31, SYSFS_SM_NOT_NEEDED)
5886+ },
5887+
5888+ {
5889+ SUSPEND2_ATTR("save_key_and_iv", SYSFS_RW),
5890+ SYSFS_INT(&suspend_encryptor_save_key_and_iv, 0, 1)
5891+ },
5892+
5893+ {
5894+ SUSPEND2_ATTR("key", SYSFS_RW),
5895+ SYSFS_STRING(suspend_encryptor_key, 255, SYSFS_SM_NOT_NEEDED)
5896+ },
5897+
5898+ {
5899+ SUSPEND2_ATTR("iv", SYSFS_RW),
5900+ SYSFS_STRING(suspend_encryptor_iv, 255, SYSFS_SM_NOT_NEEDED)
5901+ },
5902+
5903+ {
5904+ SUSPEND2_ATTR("enabled", SYSFS_RW),
5905+ SYSFS_INT(&suspend_encryption_ops.enabled, 0, 1)
5906+ }
5907+};
5908+
5909+/*
5910+ * Ops structure.
5911+ */
5912+
5913+static struct suspend_module_ops suspend_encryption_ops = {
5914+ .type = FILTER_MODULE,
5915+ .name = "Encryptor",
5916+ .directory = "encryption",
5917+ .module = THIS_MODULE,
5918+ .memory_needed = suspend_encrypt_memory_needed,
5919+ .print_debug_info = suspend_encrypt_print_debug_stats,
5920+ .save_config_info = suspend_encrypt_save_config_info,
5921+ .load_config_info = suspend_encrypt_load_config_info,
5922+ .storage_needed = suspend_encrypt_storage_needed,
5923+
5924+ .rw_init = suspend_encrypt_rw_init,
5925+ .rw_cleanup = suspend_encrypt_rw_cleanup,
5926+
5927+ .write_chunk = suspend_encrypt_write_chunk,
5928+ .read_chunk = suspend_encrypt_read_chunk,
5929+
5930+ .sysfs_data = sysfs_params,
5931+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
5932+};
5933+
5934+/* ---- Registration ---- */
5935+
5936+static __init int suspend_encrypt_load(void)
5937+{
5938+ return suspend_register_module(&suspend_encryption_ops);
5939+}
5940+
5941+#ifdef MODULE
5942+static __exit void suspend_compress_unload(void)
5943+{
5944+ suspend_unregister_module(&suspend_encryption_ops);
5945+}
5946+
5947+module_init(suspend_encrypt_load);
5948+module_exit(suspend_encrypt_unload);
5949+MODULE_LICENSE("GPL");
5950+MODULE_AUTHOR("Nigel Cunningham");
5951+MODULE_DESCRIPTION("Encryption Support for Suspend2");
5952+#else
5953+late_initcall(suspend_encrypt_load);
5954+#endif
5955diff --git a/kernel/power/extent.c b/kernel/power/extent.c
5956new file mode 100644
5957index 0000000..c248932
5958--- /dev/null
5959+++ b/kernel/power/extent.c
5960@@ -0,0 +1,289 @@
5961+/*
5962+ * kernel/power/extent.c
5963+ *
5964+ * Copyright (C) 2003-2006 Nigel Cunningham <nigel@suspend2.net>
5965+ * Copyright (C) 2006 Red Hat, inc.
5966+ *
5967+ * Distributed under GPLv2.
5968+ *
5969+ * These functions encapsulate the manipulation of storage metadata. For
5970+ * pageflags, we use dynamically allocated bitmaps.
5971+ */
5972+
5973+#include <linux/module.h>
5974+#include <linux/suspend.h>
5975+#include "modules.h"
5976+#include "extent.h"
5977+#include "ui.h"
5978+
5979+/* suspend_get_extent
5980+ *
5981+ * Returns a free extent. May fail, returning NULL instead.
5982+ */
5983+static struct extent *suspend_get_extent(void)
5984+{
5985+ struct extent *result;
5986+
5987+ if (!(result = kmalloc(sizeof(struct extent), GFP_ATOMIC)))
5988+ return NULL;
5989+
5990+ result->minimum = result->maximum = 0;
5991+ result->next = NULL;
5992+
5993+ return result;
5994+}
5995+
5996+/* suspend_put_extent_chain.
5997+ *
5998+ * Frees a whole chain of extents.
5999+ */
6000+void suspend_put_extent_chain(struct extent_chain *chain)
6001+{
6002+ struct extent *this;
6003+
6004+ this = chain->first;
6005+
6006+ while(this) {
6007+ struct extent *next = this->next;
6008+ kfree(this);
6009+ chain->num_extents--;
6010+ this = next;
6011+ }
6012+
6013+ BUG_ON(chain->num_extents);
6014+ chain->first = chain->last_touched = NULL;
6015+ chain->size = 0;
6016+}
6017+
6018+/*
6019+ * suspend_add_to_extent_chain
6020+ *
6021+ * Add an extent to an existing chain.
6022+ */
6023+int suspend_add_to_extent_chain(struct extent_chain *chain,
6024+ unsigned long minimum, unsigned long maximum)
6025+{
6026+ struct extent *new_extent = NULL, *start_at;
6027+
6028+ /* Find the right place in the chain */
6029+ start_at = (chain->last_touched &&
6030+ (chain->last_touched->minimum < minimum)) ?
6031+ chain->last_touched : NULL;
6032+
6033+ if (!start_at && chain->first && chain->first->minimum < minimum)
6034+ start_at = chain->first;
6035+
6036+ while (start_at && start_at->next && start_at->next->minimum < minimum)
6037+ start_at = start_at->next;
6038+
6039+ if (start_at && start_at->maximum == (minimum - 1)) {
6040+ start_at->maximum = maximum;
6041+
6042+ /* Merge with the following one? */
6043+ if (start_at->next &&
6044+ start_at->maximum + 1 == start_at->next->minimum) {
6045+ struct extent *to_free = start_at->next;
6046+ start_at->maximum = start_at->next->maximum;
6047+ start_at->next = start_at->next->next;
6048+ chain->num_extents--;
6049+ kfree(to_free);
6050+ }
6051+
6052+ chain->last_touched = start_at;
6053+ chain->size+= (maximum - minimum + 1);
6054+
6055+ return 0;
6056+ }
6057+
6058+ new_extent = suspend_get_extent();
6059+ if (!new_extent) {
6060+ printk("Error unable to append a new extent to the chain.\n");
6061+ return 2;
6062+ }
6063+
6064+ chain->num_extents++;
6065+ chain->size+= (maximum - minimum + 1);
6066+ new_extent->minimum = minimum;
6067+ new_extent->maximum = maximum;
6068+ new_extent->next = NULL;
6069+
6070+ chain->last_touched = new_extent;
6071+
6072+ if (start_at) {
6073+ struct extent *next = start_at->next;
6074+ start_at->next = new_extent;
6075+ new_extent->next = next;
6076+ } else {
6077+ if (chain->first)
6078+ new_extent->next = chain->first;
6079+ chain->first = new_extent;
6080+ }
6081+
6082+ return 0;
6083+}
6084+
6085+/* suspend_serialise_extent_chain
6086+ *
6087+ * Write a chain in the image.
6088+ */
6089+int suspend_serialise_extent_chain(struct suspend_module_ops *owner,
6090+ struct extent_chain *chain)
6091+{
6092+ struct extent *this;
6093+ int ret, i = 0;
6094+
6095+ if ((ret = suspendActiveAllocator->rw_header_chunk(WRITE, owner,
6096+ (char *) chain,
6097+ 2 * sizeof(int))))
6098+ return ret;
6099+
6100+ this = chain->first;
6101+ while (this) {
6102+ if ((ret = suspendActiveAllocator->rw_header_chunk(WRITE, owner,
6103+ (char *) this,
6104+ 2 * sizeof(unsigned long))))
6105+ return ret;
6106+ this = this->next;
6107+ i++;
6108+ }
6109+
6110+ if (i != chain->num_extents) {
6111+ printk(KERN_EMERG "Saved %d extents but chain metadata says there "
6112+ "should be %d.\n", i, chain->num_extents);
6113+ BUG();
6114+ }
6115+
6116+ return ret;
6117+}
6118+
6119+/* suspend_load_extent_chain
6120+ *
6121+ * Read back a chain saved in the image.
6122+ */
6123+int suspend_load_extent_chain(struct extent_chain *chain)
6124+{
6125+ struct extent *this, *last = NULL;
6126+ int i, ret;
6127+
6128+ if (!(ret = suspendActiveAllocator->rw_header_chunk(READ, NULL,
6129+ (char *) chain,
6130+ 2 * sizeof(int))))
6131+ return ret;
6132+
6133+ for (i = 0; i < chain->num_extents; i++) {
6134+ this = kmalloc(sizeof(struct extent), GFP_ATOMIC);
6135+ BUG_ON(!this); /* Shouldn't run out of memory trying this! */
6136+ this->next = NULL;
6137+ if (!(ret = suspendActiveAllocator->rw_header_chunk(READ, NULL,
6138+ (char *) this, 2 * sizeof(unsigned long))))
6139+ return ret;
6140+ if (last)
6141+ last->next = this;
6142+ else
6143+ chain->first = this;
6144+ last = this;
6145+ }
6146+ return ret;
6147+}
6148+
6149+/* suspend_extent_state_next
6150+ *
6151+ * Given a state, progress to the next valid entry. We may begin in an
6152+ * invalid state, as we do when invoked after extent_state_goto_start below.
6153+ *
6154+ * When using compression and expected_compression > 0, we let the image size
6155+ * be larger than storage, so we can validly run out of data to return.
6156+ */
6157+unsigned long suspend_extent_state_next(struct extent_iterate_state *state)
6158+{
6159+ if (state->current_chain > state->num_chains)
6160+ return 0;
6161+
6162+ if (state->current_extent) {
6163+ if (state->current_offset == state->current_extent->maximum) {
6164+ if (state->current_extent->next) {
6165+ state->current_extent = state->current_extent->next;
6166+ state->current_offset = state->current_extent->minimum;
6167+ } else {
6168+ state->current_extent = NULL;
6169+ state->current_offset = 0;
6170+ }
6171+ } else
6172+ state->current_offset++;
6173+ }
6174+
6175+ while(!state->current_extent) {
6176+ int chain_num = ++(state->current_chain);
6177+
6178+ if (chain_num > state->num_chains)
6179+ return 0;
6180+
6181+ state->current_extent = (state->chains + chain_num)->first;
6182+
6183+ if (!state->current_extent)
6184+ continue;
6185+
6186+ state->current_offset = state->current_extent->minimum;
6187+ }
6188+
6189+ return state->current_offset;
6190+}
6191+
6192+/* suspend_extent_state_goto_start
6193+ *
6194+ * Find the first valid value in a group of chains.
6195+ */
6196+void suspend_extent_state_goto_start(struct extent_iterate_state *state)
6197+{
6198+ state->current_chain = -1;
6199+ state->current_extent = NULL;
6200+ state->current_offset = 0;
6201+}
6202+
6203+/* suspend_extent_start_save
6204+ *
6205+ * Given a state and a struct extent_state_store, save the crreutn
6206+ * position in a format that can be used with relocated chains (at
6207+ * resume time).
6208+ */
6209+void suspend_extent_state_save(struct extent_iterate_state *state,
6210+ struct extent_iterate_saved_state *saved_state)
6211+{
6212+ struct extent *extent;
6213+
6214+ saved_state->chain_num = state->current_chain;
6215+ saved_state->extent_num = 0;
6216+ saved_state->offset = state->current_offset;
6217+
6218+ if (saved_state->chain_num == -1)
6219+ return;
6220+
6221+ extent = (state->chains + state->current_chain)->first;
6222+
6223+ while (extent != state->current_extent) {
6224+ saved_state->extent_num++;
6225+ extent = extent->next;
6226+ }
6227+}
6228+
6229+/* suspend_extent_start_restore
6230+ *
6231+ * Restore the position saved by extent_state_save.
6232+ */
6233+void suspend_extent_state_restore(struct extent_iterate_state *state,
6234+ struct extent_iterate_saved_state *saved_state)
6235+{
6236+ int posn = saved_state->extent_num;
6237+
6238+ if (saved_state->chain_num == -1) {
6239+ suspend_extent_state_goto_start(state);
6240+ return;
6241+ }
6242+
6243+ state->current_chain = saved_state->chain_num;
6244+ state->current_extent = (state->chains + state->current_chain)->first;
6245+ state->current_offset = saved_state->offset;
6246+
6247+ while (posn--)
6248+ state->current_extent = state->current_extent->next;
6249+}
6250diff --git a/kernel/power/extent.h b/kernel/power/extent.h
6251new file mode 100644
6252index 0000000..c647384
6253--- /dev/null
6254+++ b/kernel/power/extent.h
6255@@ -0,0 +1,78 @@
6256+/*
6257+ * kernel/power/extent.h
6258+ *
6259+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
6260+ * Copyright (C) 2006 Red Hat, inc.
6261+ *
6262+ * This file is released under the GPLv2.
6263+ *
6264+ * It contains declarations related to extents. Extents are
6265+ * suspend's method of storing some of the metadata for the image.
6266+ * See extent.c for more info.
6267+ *
6268+ */
6269+
6270+#include "modules.h"
6271+
6272+#ifndef EXTENT_H
6273+#define EXTENT_H
6274+
6275+struct extent {
6276+ unsigned long minimum, maximum;
6277+ struct extent *next;
6278+};
6279+
6280+struct extent_chain {
6281+ int size; /* size of the chain ie sum (max-min+1) */
6282+ int num_extents;
6283+ struct extent *first, *last_touched;
6284+};
6285+
6286+struct extent_iterate_state {
6287+ struct extent_chain *chains;
6288+ int num_chains;
6289+ int current_chain;
6290+ struct extent *current_extent;
6291+ unsigned long current_offset;
6292+};
6293+
6294+struct extent_iterate_saved_state {
6295+ int chain_num;
6296+ int extent_num;
6297+ unsigned long offset;
6298+};
6299+
6300+#define suspend_extent_state_eof(state) ((state)->num_chains < (state)->current_chain)
6301+
6302+/* Simplify iterating through all the values in an extent chain */
6303+#define suspend_extent_for_each(extent_chain, extentpointer, value) \
6304+if ((extent_chain)->first) \
6305+ for ((extentpointer) = (extent_chain)->first, (value) = \
6306+ (extentpointer)->minimum; \
6307+ ((extentpointer) && ((extentpointer)->next || (value) <= \
6308+ (extentpointer)->maximum)); \
6309+ (((value) == (extentpointer)->maximum) ? \
6310+ ((extentpointer) = (extentpointer)->next, (value) = \
6311+ ((extentpointer) ? (extentpointer)->minimum : 0)) : \
6312+ (value)++))
6313+
6314+void suspend_put_extent_chain(struct extent_chain *chain);
6315+int suspend_add_to_extent_chain(struct extent_chain *chain,
6316+ unsigned long minimum, unsigned long maximum);
6317+int suspend_serialise_extent_chain(struct suspend_module_ops *owner,
6318+ struct extent_chain *chain);
6319+int suspend_load_extent_chain(struct extent_chain *chain);
6320+
6321+/* swap_entry_to_extent_val & extent_val_to_swap_entry:
6322+ * We are putting offset in the low bits so consecutive swap entries
6323+ * make consecutive extent values */
6324+#define swap_entry_to_extent_val(swp_entry) (swp_entry.val)
6325+#define extent_val_to_swap_entry(val) (swp_entry_t) { (val) }
6326+
6327+void suspend_extent_state_save(struct extent_iterate_state *state,
6328+ struct extent_iterate_saved_state *saved_state);
6329+void suspend_extent_state_restore(struct extent_iterate_state *state,
6330+ struct extent_iterate_saved_state *saved_state);
6331+void suspend_extent_state_goto_start(struct extent_iterate_state *state);
6332+unsigned long suspend_extent_state_next(struct extent_iterate_state *state);
6333+#endif
6334diff --git a/kernel/power/io.c b/kernel/power/io.c
6335new file mode 100644
6336index 0000000..b851e29
6337--- /dev/null
6338+++ b/kernel/power/io.c
6339@@ -0,0 +1,1005 @@
6340+/*
6341+ * kernel/power/io.c
6342+ *
6343+ * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
6344+ * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
6345+ * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr>
6346+ * Copyright (C) 2002-2006 Nigel Cunningham <nigel@suspend2.net>
6347+ * Copyright (C) 2006 Red Hat, inc.
6348+ *
6349+ * This file is released under the GPLv2.
6350+ *
6351+ * It contains high level IO routines for suspending.
6352+ *
6353+ */
6354+
6355+#include <linux/suspend.h>
6356+#include <linux/version.h>
6357+#include <linux/utsname.h>
6358+#include <linux/mount.h>
6359+#include <linux/suspend2.h>
6360+#include <linux/highmem.h>
6361+#include <asm/tlbflush.h>
6362+
6363+#include "power.h"
6364+#include "suspend.h"
6365+#include "modules.h"
6366+#include "pageflags.h"
6367+#include "io.h"
6368+#include "ui.h"
6369+#include "storage.h"
6370+#include "prepare_image.h"
6371+#include "extent.h"
6372+
6373+/* suspend_attempt_to_parse_resume_device
6374+ *
6375+ * Can we suspend, using the current resume2= parameter?
6376+ */
6377+int suspend_attempt_to_parse_resume_device(void)
6378+{
6379+ struct list_head *Allocator;
6380+ struct suspend_module_ops *thisAllocator;
6381+ int result, returning = 0;
6382+
6383+ if (suspend_activate_storage(0))
6384+ return 0;
6385+
6386+ suspendActiveAllocator = NULL;
6387+ clear_suspend_state(SUSPEND_RESUME_DEVICE_OK);
6388+ clear_suspend_state(SUSPEND_CAN_RESUME);
6389+ clear_result_state(SUSPEND_ABORTED);
6390+
6391+ if (!suspendNumAllocators) {
6392+ printk(name_suspend "No storage allocators have been "
6393+ "registered. Suspending will be disabled.\n");
6394+ goto cleanup;
6395+ }
6396+
6397+ if (!resume2_file[0]) {
6398+ printk(name_suspend "Resume2 parameter is empty."
6399+ " Suspending will be disabled.\n");
6400+ goto cleanup;
6401+ }
6402+
6403+ list_for_each(Allocator, &suspendAllocators) {
6404+ thisAllocator = list_entry(Allocator, struct suspend_module_ops,
6405+ type_list);
6406+
6407+ /*
6408+ * Not sure why you'd want to disable an allocator, but
6409+ * we should honour the flag if we're providing it
6410+ */
6411+ if (!thisAllocator->enabled)
6412+ continue;
6413+
6414+ result = thisAllocator->parse_sig_location(
6415+ resume2_file, (suspendNumAllocators == 1));
6416+
6417+ switch (result) {
6418+ case -EINVAL:
6419+ /* For this allocator, but not a valid
6420+ * configuration. Error already printed. */
6421+ goto cleanup;
6422+
6423+ case 0:
6424+ /* For this allocator and valid. */
6425+ suspendActiveAllocator = thisAllocator;
6426+
6427+ set_suspend_state(SUSPEND_RESUME_DEVICE_OK);
6428+ set_suspend_state(SUSPEND_CAN_RESUME);
6429+ printk(name_suspend "Resuming enabled.\n");
6430+
6431+ returning = 1;
6432+ goto cleanup;
6433+ }
6434+ }
6435+ printk(name_suspend "No matching enabled allocator found. Resuming disabled.\n");
6436+cleanup:
6437+ suspend_deactivate_storage(0);
6438+ return returning;
6439+}
6440+
6441+void attempt_to_parse_resume_device2(void)
6442+{
6443+ suspend_prepare_usm();
6444+ suspend_attempt_to_parse_resume_device();
6445+ suspend_cleanup_usm();
6446+}
6447+
6448+/* noresume_reset_modules
6449+ *
6450+ * Description: When we read the start of an image, modules (and especially the
6451+ * active allocator) might need to reset data structures if we
6452+ * decide to invalidate the image rather than resuming from it.
6453+ */
6454+
6455+static void noresume_reset_modules(void)
6456+{
6457+ struct suspend_module_ops *this_filter;
6458+
6459+ list_for_each_entry(this_filter, &suspend_filters, type_list)
6460+ if (this_filter->noresume_reset)
6461+ this_filter->noresume_reset();
6462+
6463+ if (suspendActiveAllocator && suspendActiveAllocator->noresume_reset)
6464+ suspendActiveAllocator->noresume_reset();
6465+}
6466+
6467+/* fill_suspend_header()
6468+ *
6469+ * Description: Fill the suspend header structure.
6470+ * Arguments: struct suspend_header: Header data structure to be filled.
6471+ */
6472+
6473+static void fill_suspend_header(struct suspend_header *sh)
6474+{
6475+ int i;
6476+
6477+ memset((char *)sh, 0, sizeof(*sh));
6478+
6479+ sh->version_code = LINUX_VERSION_CODE;
6480+ sh->num_physpages = num_physpages;
6481+ sh->orig_mem_free = suspend_orig_mem_free;
6482+ memcpy(&sh->uts, init_utsname(), sizeof(struct new_utsname));
6483+ sh->page_size = PAGE_SIZE;
6484+ sh->pagedir = pagedir1;
6485+ sh->pageset_2_size = pagedir2.size;
6486+ sh->param0 = suspend_result;
6487+ sh->param1 = suspend_action;
6488+ sh->param2 = suspend_debug_state;
6489+ sh->param3 = console_loglevel;
6490+ sh->root_fs = current->fs->rootmnt->mnt_sb->s_dev;
6491+ for (i = 0; i < 4; i++)
6492+ sh->io_time[i/2][i%2] = suspend_io_time[i/2][i%2];
6493+}
6494+
6495+/*
6496+ * rw_init_modules
6497+ *
6498+ * Iterate over modules, preparing the ones that will be used to read or write
6499+ * data.
6500+ */
6501+static int rw_init_modules(int rw, int which)
6502+{
6503+ struct suspend_module_ops *this_module;
6504+ /* Initialise page transformers */
6505+ list_for_each_entry(this_module, &suspend_filters, type_list) {
6506+ if (!this_module->enabled)
6507+ continue;
6508+ if (this_module->rw_init && this_module->rw_init(rw, which)) {
6509+ abort_suspend("Failed to initialise the %s filter.",
6510+ this_module->name);
6511+ return 1;
6512+ }
6513+ }
6514+
6515+ /* Initialise allocator */
6516+ if (suspendActiveAllocator->rw_init(rw, which)) {
6517+ abort_suspend("Failed to initialise the allocator.");
6518+ if (!rw)
6519+ suspendActiveAllocator->invalidate_image();
6520+ return 1;
6521+ }
6522+
6523+ /* Initialise other modules */
6524+ list_for_each_entry(this_module, &suspend_modules, module_list) {
6525+ if (!this_module->enabled ||
6526+ this_module->type == FILTER_MODULE ||
6527+ this_module->type == WRITER_MODULE)
6528+ continue;
6529+ if (this_module->rw_init && this_module->rw_init(rw, which)) {
6530+ set_result_state(SUSPEND_ABORTED);
6531+ return 1;
6532+ }
6533+ }
6534+
6535+ return 0;
6536+}
6537+
6538+/*
6539+ * rw_cleanup_modules
6540+ *
6541+ * Cleanup components after reading or writing a set of pages.
6542+ * Only the allocator may fail.
6543+ */
6544+static int rw_cleanup_modules(int rw)
6545+{
6546+ struct suspend_module_ops *this_module;
6547+ int result = 0;
6548+
6549+ /* Cleanup other modules */
6550+ list_for_each_entry(this_module, &suspend_modules, module_list) {
6551+ if (!this_module->enabled ||
6552+ this_module->type == FILTER_MODULE ||
6553+ this_module->type == WRITER_MODULE)
6554+ continue;
6555+ if (this_module->rw_cleanup)
6556+ result |= this_module->rw_cleanup(rw);
6557+ }
6558+
6559+ /* Flush data and cleanup */
6560+ list_for_each_entry(this_module, &suspend_filters, type_list) {
6561+ if (!this_module->enabled)
6562+ continue;
6563+ if (this_module->rw_cleanup)
6564+ result |= this_module->rw_cleanup(rw);
6565+ }
6566+
6567+ result |= suspendActiveAllocator->rw_cleanup(rw);
6568+
6569+ return result;
6570+}
6571+
6572+/*
6573+ * do_rw_loop
6574+ *
6575+ * The main I/O loop for reading or writing pages.
6576+ */
6577+static int do_rw_loop(int write, int finish_at, dyn_pageflags_t *pageflags,
6578+ int base, int barmax)
6579+{
6580+ int pfn, pc, step = 1, nextupdate = 0, i;
6581+ int result;
6582+ struct suspend_module_ops *first_filter = suspend_get_next_filter(NULL);
6583+ struct page *buffer = alloc_page(GFP_ATOMIC);
6584+
6585+ pfn = get_next_bit_on(*pageflags, max_pfn);
6586+
6587+ pc = finish_at / 5;
6588+
6589+ for (i=0; i< finish_at; i++) {
6590+ struct page *page = pfn_to_page(pfn);
6591+
6592+ if ((i + base) >= nextupdate)
6593+ nextupdate = suspend_update_status(i+base, barmax,
6594+ " %d/%d MB ", MB(base+i+1), MB(barmax));
6595+
6596+ if ((i + 1) == pc) {
6597+ printk("%d%%...", 20 * step);
6598+ step++;
6599+ pc = finish_at * step / 5;
6600+ }
6601+
6602+ if (write)
6603+ result = first_filter->write_chunk(page);
6604+ else
6605+ result = first_filter->read_chunk(
6606+ PageResave(page) ? buffer : page,
6607+ SUSPEND_ASYNC);
6608+
6609+ if (result) {
6610+ if (write) {
6611+ printk("Write chunk returned %d.\n", result);
6612+ abort_suspend("Failed to write a chunk of the "
6613+ "image.");
6614+ __free_pages(buffer, 0);
6615+ return result;
6616+ } else
6617+ panic("Failed to read chunk %d/%d of the image. (%d)",
6618+ i, finish_at, result);
6619+ }
6620+
6621+ suspend_cond_pause(0, NULL);
6622+
6623+ if (test_result_state(SUSPEND_ABORTED) && write) {
6624+ __free_pages(buffer, 0);
6625+ return 1;
6626+ }
6627+
6628+ pfn = get_next_bit_on(*pageflags, pfn);
6629+ }
6630+
6631+ printk("done.\n");
6632+
6633+ suspend_update_status(base + finish_at, barmax, " %d/%d MB ",
6634+ MB(base + finish_at), MB(barmax));
6635+ __free_pages(buffer, 0);
6636+ return 0;
6637+}
6638+
6639+/* write_pageset()
6640+ *
6641+ * Description: Write a pageset to disk.
6642+ * Arguments: pagedir: Which pagedir to write..
6643+ * Returns: Zero on success or -1 on failure.
6644+ */
6645+
6646+int write_pageset(struct pagedir *pagedir)
6647+{
6648+ int finish_at, base = 0, start_time, end_time;
6649+ int barmax = pagedir1.size + pagedir2.size;
6650+ long error = 0;
6651+ dyn_pageflags_t *pageflags;
6652+
6653+ /*
6654+ * Even if there is nothing to read or write, the allocator
6655+ * may need the init/cleanup for it's housekeeping. (eg:
6656+ * Pageset1 may start where pageset2 ends when writing).
6657+ */
6658+ finish_at = pagedir->size;
6659+
6660+ if (pagedir->id == 1) {
6661+ suspend_prepare_status(DONT_CLEAR_BAR,
6662+ "Writing kernel & process data...");
6663+ base = pagedir2.size;
6664+ if (test_action_state(SUSPEND_TEST_FILTER_SPEED) ||
6665+ test_action_state(SUSPEND_TEST_BIO))
6666+ pageflags = &pageset1_map;
6667+ else
6668+ pageflags = &pageset1_copy_map;
6669+ } else {
6670+ suspend_prepare_status(CLEAR_BAR, "Writing caches...");
6671+ pageflags = &pageset2_map;
6672+ }
6673+
6674+ start_time = jiffies;
6675+
6676+ if (!rw_init_modules(1, pagedir->id))
6677+ error = do_rw_loop(1, finish_at, pageflags, base, barmax);
6678+
6679+ if (rw_cleanup_modules(WRITE)) {
6680+ abort_suspend("Failed to cleanup after writing.");
6681+ error = 1;
6682+ }
6683+
6684+ end_time = jiffies;
6685+
6686+ if ((end_time - start_time) && (!test_result_state(SUSPEND_ABORTED))) {
6687+ suspend_io_time[0][0] += finish_at,
6688+ suspend_io_time[0][1] += (end_time - start_time);
6689+ }
6690+
6691+ return error;
6692+}
6693+
6694+/* read_pageset()
6695+ *
6696+ * Description: Read a pageset from disk.
6697+ * Arguments: whichtowrite: Controls what debugging output is printed.
6698+ * overwrittenpagesonly: Whether to read the whole pageset or
6699+ * only part.
6700+ * Returns: Zero on success or -1 on failure.
6701+ */
6702+
6703+static int read_pageset(struct pagedir *pagedir, int overwrittenpagesonly)
6704+{
6705+ int result = 0, base = 0, start_time, end_time;
6706+ int finish_at = pagedir->size;
6707+ int barmax = pagedir1.size + pagedir2.size;
6708+ dyn_pageflags_t *pageflags;
6709+
6710+ if (pagedir->id == 1) {
6711+ suspend_prepare_status(CLEAR_BAR,
6712+ "Reading kernel & process data...");
6713+ pageflags = &pageset1_copy_map;
6714+ } else {
6715+ suspend_prepare_status(DONT_CLEAR_BAR, "Reading caches...");
6716+ if (overwrittenpagesonly)
6717+ barmax = finish_at = min(pagedir1.size,
6718+ pagedir2.size);
6719+ else {
6720+ base = pagedir1.size;
6721+ }
6722+ pageflags = &pageset2_map;
6723+ }
6724+
6725+ start_time = jiffies;
6726+
6727+ if (rw_init_modules(0, pagedir->id)) {
6728+ suspendActiveAllocator->invalidate_image();
6729+ result = 1;
6730+ } else
6731+ result = do_rw_loop(0, finish_at, pageflags, base, barmax);
6732+
6733+ if (rw_cleanup_modules(READ)) {
6734+ abort_suspend("Failed to cleanup after reading.");
6735+ result = 1;
6736+ }
6737+
6738+ /* Statistics */
6739+ end_time=jiffies;
6740+
6741+ if ((end_time - start_time) && (!test_result_state(SUSPEND_ABORTED))) {
6742+ suspend_io_time[1][0] += finish_at,
6743+ suspend_io_time[1][1] += (end_time - start_time);
6744+ }
6745+
6746+ return result;
6747+}
6748+
6749+/* write_module_configs()
6750+ *
6751+ * Description: Store the configuration for each module in the image header.
6752+ * Returns: Int: Zero on success, Error value otherwise.
6753+ */
6754+static int write_module_configs(void)
6755+{
6756+ struct suspend_module_ops *this_module;
6757+ char *buffer = (char *) get_zeroed_page(GFP_ATOMIC);
6758+ int len, index = 1;
6759+ struct suspend_module_header suspend_module_header;
6760+
6761+ if (!buffer) {
6762+ printk("Failed to allocate a buffer for saving "
6763+ "module configuration info.\n");
6764+ return -ENOMEM;
6765+ }
6766+
6767+ /*
6768+ * We have to know which data goes with which module, so we at
6769+ * least write a length of zero for a module. Note that we are
6770+ * also assuming every module's config data takes <= PAGE_SIZE.
6771+ */
6772+
6773+ /* For each module (in registration order) */
6774+ list_for_each_entry(this_module, &suspend_modules, module_list) {
6775+ if (!this_module->enabled || !this_module->storage_needed ||
6776+ (this_module->type == WRITER_MODULE &&
6777+ suspendActiveAllocator != this_module))
6778+ continue;
6779+
6780+ /* Get the data from the module */
6781+ len = 0;
6782+ if (this_module->save_config_info)
6783+ len = this_module->save_config_info(buffer);
6784+
6785+ /* Save the details of the module */
6786+ suspend_module_header.enabled = this_module->enabled;
6787+ suspend_module_header.type = this_module->type;
6788+ suspend_module_header.index = index++;
6789+ strncpy(suspend_module_header.name, this_module->name,
6790+ sizeof(suspend_module_header.name));
6791+ suspendActiveAllocator->rw_header_chunk(WRITE,
6792+ this_module,
6793+ (char *) &suspend_module_header,
6794+ sizeof(suspend_module_header));
6795+
6796+ /* Save the size of the data and any data returned */
6797+ suspendActiveAllocator->rw_header_chunk(WRITE,
6798+ this_module,
6799+ (char *) &len, sizeof(int));
6800+ if (len)
6801+ suspendActiveAllocator->rw_header_chunk(
6802+ WRITE, this_module, buffer, len);
6803+ }
6804+
6805+ /* Write a blank header to terminate the list */
6806+ suspend_module_header.name[0] = '\0';
6807+ suspendActiveAllocator->rw_header_chunk(WRITE,
6808+ NULL,
6809+ (char *) &suspend_module_header,
6810+ sizeof(suspend_module_header));
6811+
6812+ free_page((unsigned long) buffer);
6813+ return 0;
6814+}
6815+
6816+/* read_module_configs()
6817+ *
6818+ * Description: Reload module configurations from the image header.
6819+ * Returns: Int. Zero on success, error value otherwise.
6820+ */
6821+
6822+static int read_module_configs(void)
6823+{
6824+ struct suspend_module_ops *this_module;
6825+ char *buffer = (char *) get_zeroed_page(GFP_ATOMIC);
6826+ int len, result = 0;
6827+ struct suspend_module_header suspend_module_header;
6828+
6829+ if (!buffer) {
6830+ printk("Failed to allocate a buffer for reloading module "
6831+ "configuration info.\n");
6832+ return -ENOMEM;
6833+ }
6834+
6835+ /* All modules are initially disabled. That way, if we have a module
6836+ * loaded now that wasn't loaded when we suspended, it won't be used
6837+ * in trying to read the data.
6838+ */
6839+ list_for_each_entry(this_module, &suspend_modules, module_list)
6840+ this_module->enabled = 0;
6841+
6842+ /* Get the first module header */
6843+ result = suspendActiveAllocator->rw_header_chunk(READ, NULL,
6844+ (char *) &suspend_module_header, sizeof(suspend_module_header));
6845+ if (!result) {
6846+ printk("Failed to read the next module header.\n");
6847+ free_page((unsigned long) buffer);
6848+ return -EINVAL;
6849+ }
6850+
6851+ /* For each module (in registration order) */
6852+ while (suspend_module_header.name[0]) {
6853+
6854+ /* Find the module */
6855+ this_module = suspend_find_module_given_name(suspend_module_header.name);
6856+
6857+ if (!this_module) {
6858+ /*
6859+ * Is it used? Only need to worry about filters. The active
6860+ * allocator must be loaded!
6861+ */
6862+ if (suspend_module_header.enabled) {
6863+ suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
6864+ "It looks like we need module %s for "
6865+ "reading the image but it hasn't been "
6866+ "registered.\n",
6867+ suspend_module_header.name);
6868+ if (!(test_suspend_state(SUSPEND_CONTINUE_REQ))) {
6869+ suspendActiveAllocator->invalidate_image();
6870+ free_page((unsigned long) buffer);
6871+ return -EINVAL;
6872+ }
6873+ } else
6874+ printk("Module %s configuration data found, but the module "
6875+ "hasn't registered. Looks like it was disabled, so "
6876+ "we're ignoring it's data.",
6877+ suspend_module_header.name);
6878+ }
6879+
6880+ /* Get the length of the data (if any) */
6881+ result = suspendActiveAllocator->rw_header_chunk(READ, NULL,
6882+ (char *) &len, sizeof(int));
6883+ if (!result) {
6884+ printk("Failed to read the length of the module %s's"
6885+ " configuration data.\n",
6886+ suspend_module_header.name);
6887+ free_page((unsigned long) buffer);
6888+ return -EINVAL;
6889+ }
6890+
6891+ /* Read any data and pass to the module (if we found one) */
6892+ if (len) {
6893+ suspendActiveAllocator->rw_header_chunk(READ, NULL,
6894+ buffer, len);
6895+ if (this_module) {
6896+ if (!this_module->save_config_info) {
6897+ printk("Huh? Module %s appears to have "
6898+ "a save_config_info, but not a "
6899+ "load_config_info function!\n",
6900+ this_module->name);
6901+ } else
6902+ this_module->load_config_info(buffer, len);
6903+ }
6904+ }
6905+
6906+ if (this_module) {
6907+ /* Now move this module to the tail of its lists. This
6908+ * will put it in order. Any new modules will end up at
6909+ * the top of the lists. They should have been set to
6910+ * disabled when loaded (people will normally not edit
6911+ * an initrd to load a new module and then suspend
6912+ * without using it!).
6913+ */
6914+
6915+ suspend_move_module_tail(this_module);
6916+
6917+ /*
6918+ * We apply the disabled state; modules don't need to
6919+ * save whether they were disabled and if they do, we
6920+ * override them anyway.
6921+ */
6922+ this_module->enabled = suspend_module_header.enabled;
6923+ }
6924+
6925+ /* Get the next module header */
6926+ result = suspendActiveAllocator->rw_header_chunk(READ, NULL,
6927+ (char *) &suspend_module_header,
6928+ sizeof(suspend_module_header));
6929+
6930+ if (!result) {
6931+ printk("Failed to read the next module header.\n");
6932+ free_page((unsigned long) buffer);
6933+ return -EINVAL;
6934+ }
6935+
6936+ }
6937+
6938+ free_page((unsigned long) buffer);
6939+ return 0;
6940+}
6941+
6942+/* write_image_header()
6943+ *
6944+ * Description: Write the image header after write the image proper.
6945+ * Returns: Int. Zero on success or -1 on failure.
6946+ */
6947+
6948+int write_image_header(void)
6949+{
6950+ int ret;
6951+ int total = pagedir1.size + pagedir2.size+2;
6952+ char *header_buffer = NULL;
6953+
6954+ /* Now prepare to write the header */
6955+ if ((ret = suspendActiveAllocator->write_header_init())) {
6956+ abort_suspend("Active allocator's write_header_init"
6957+ " function failed.");
6958+ goto write_image_header_abort;
6959+ }
6960+
6961+ /* Get a buffer */
6962+ header_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
6963+ if (!header_buffer) {
6964+ abort_suspend("Out of memory when trying to get page "
6965+ "for header!");
6966+ goto write_image_header_abort;
6967+ }
6968+
6969+ /* Write suspend header */
6970+ fill_suspend_header((struct suspend_header *) header_buffer);
6971+ suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
6972+ header_buffer, sizeof(struct suspend_header));
6973+
6974+ free_page((unsigned long) header_buffer);
6975+
6976+ /* Write module configurations */
6977+ if ((ret = write_module_configs())) {
6978+ abort_suspend("Failed to write module configs.");
6979+ goto write_image_header_abort;
6980+ }
6981+
6982+ save_dyn_pageflags(pageset1_map);
6983+
6984+ /* Flush data and let allocator cleanup */
6985+ if (suspendActiveAllocator->write_header_cleanup()) {
6986+ abort_suspend("Failed to cleanup writing header.");
6987+ goto write_image_header_abort_no_cleanup;
6988+ }
6989+
6990+ if (test_result_state(SUSPEND_ABORTED))
6991+ goto write_image_header_abort_no_cleanup;
6992+
6993+ suspend_message(SUSPEND_IO, SUSPEND_VERBOSE, 1, "|\n");
6994+ suspend_update_status(total, total, NULL);
6995+
6996+ return 0;
6997+
6998+write_image_header_abort:
6999+ suspendActiveAllocator->write_header_cleanup();
7000+write_image_header_abort_no_cleanup:
7001+ return -1;
7002+}
7003+
7004+/* sanity_check()
7005+ *
7006+ * Description: Perform a few checks, seeking to ensure that the kernel being
7007+ * booted matches the one suspended. They need to match so we can
7008+ * be _sure_ things will work. It is not absolutely impossible for
7009+ * resuming from a different kernel to work, just not assured.
7010+ * Arguments: Struct suspend_header. The header which was saved at suspend
7011+ * time.
7012+ */
7013+static char *sanity_check(struct suspend_header *sh)
7014+{
7015+ if (sh->version_code != LINUX_VERSION_CODE)
7016+ return "Incorrect kernel version.";
7017+
7018+ if (sh->num_physpages != num_physpages)
7019+ return "Incorrect memory size.";
7020+
7021+ if (strncmp(sh->uts.sysname, init_utsname()->sysname, 65))
7022+ return "Incorrect system type.";
7023+
7024+ if (strncmp(sh->uts.release, init_utsname()->release, 65))
7025+ return "Incorrect release.";
7026+
7027+ if (strncmp(sh->uts.version, init_utsname()->version, 65))
7028+ return "Right kernel version but wrong build number.";
7029+
7030+ if (strncmp(sh->uts.machine, init_utsname()->machine, 65))
7031+ return "Incorrect machine type.";
7032+
7033+ if (sh->page_size != PAGE_SIZE)
7034+ return "Incorrect PAGE_SIZE.";
7035+
7036+ if (!test_action_state(SUSPEND_IGNORE_ROOTFS)) {
7037+ const struct super_block *sb;
7038+ list_for_each_entry(sb, &super_blocks, s_list) {
7039+ if ((!(sb->s_flags & MS_RDONLY)) &&
7040+ (sb->s_type->fs_flags & FS_REQUIRES_DEV))
7041+ return "Device backed fs has been mounted "
7042+ "rw prior to resume or initrd/ramfs "
7043+ "is mounted rw.";
7044+ }
7045+ }
7046+
7047+ return 0;
7048+}
7049+
7050+/* __read_pageset1
7051+ *
7052+ * Description: Test for the existence of an image and attempt to load it.
7053+ * Returns: Int. Zero if image found and pageset1 successfully loaded.
7054+ * Error if no image found or loaded.
7055+ */
7056+static int __read_pageset1(void)
7057+{
7058+ int i, result = 0;
7059+ char *header_buffer = (char *) get_zeroed_page(GFP_ATOMIC),
7060+ *sanity_error = NULL;
7061+ struct suspend_header *suspend_header;
7062+
7063+ if (!header_buffer) {
7064+ printk("Unable to allocate a page for reading the signature.\n");
7065+ return -ENOMEM;
7066+ }
7067+
7068+ /* Check for an image */
7069+ if (!(result = suspendActiveAllocator->image_exists())) {
7070+ result = -ENODATA;
7071+ noresume_reset_modules();
7072+ printk(name_suspend "No image found.\n");
7073+ goto out;
7074+ }
7075+
7076+ /* Check for noresume command line option */
7077+ if (test_suspend_state(SUSPEND_NORESUME_SPECIFIED)) {
7078+ suspendActiveAllocator->invalidate_image();
7079+ result = -EINVAL;
7080+ noresume_reset_modules();
7081+ printk(name_suspend "Noresume: Invalidated image.\n");
7082+ goto out;
7083+ }
7084+
7085+ /* Check whether we've resumed before */
7086+ if (test_suspend_state(SUSPEND_RESUMED_BEFORE)) {
7087+ int resumed_before_default = 0;
7088+ if (test_suspend_state(SUSPEND_RETRY_RESUME))
7089+ resumed_before_default = SUSPEND_CONTINUE_REQ;
7090+ suspend_early_boot_message(1, resumed_before_default, NULL);
7091+ clear_suspend_state(SUSPEND_RETRY_RESUME);
7092+ if (!(test_suspend_state(SUSPEND_CONTINUE_REQ))) {
7093+ suspendActiveAllocator->invalidate_image();
7094+ result = -EINVAL;
7095+ noresume_reset_modules();
7096+ printk(name_suspend "Tried to resume before: Invalidated image.\n");
7097+ goto out;
7098+ }
7099+ }
7100+
7101+ clear_suspend_state(SUSPEND_CONTINUE_REQ);
7102+
7103+ /*
7104+ * Prepare the active allocator for reading the image header. The
7105+ * activate allocator might read its own configuration.
7106+ *
7107+ * NB: This call may never return because there might be a signature
7108+ * for a different image such that we warn the user and they choose
7109+ * to reboot. (If the device ids look erroneous (2.4 vs 2.6) or the
7110+ * location of the image might be unavailable if it was stored on a
7111+ * network connection.
7112+ */
7113+
7114+ if ((result = suspendActiveAllocator->read_header_init())) {
7115+ suspendActiveAllocator->read_header_cleanup();
7116+ noresume_reset_modules();
7117+ printk(name_suspend "Failed to initialise, reading the image header.\n");
7118+ goto out;
7119+ }
7120+
7121+ /* Read suspend header */
7122+ if ((result = suspendActiveAllocator->rw_header_chunk(READ, NULL,
7123+ header_buffer, sizeof(struct suspend_header))) < 0) {
7124+ suspendActiveAllocator->read_header_cleanup();
7125+ noresume_reset_modules();
7126+ printk(name_suspend "Failed to read the image signature.\n");
7127+ goto out;
7128+ }
7129+
7130+ suspend_header = (struct suspend_header *) header_buffer;
7131+
7132+ /*
7133+ * NB: This call may also result in a reboot rather than returning.
7134+ */
7135+
7136+ if ((sanity_error = sanity_check(suspend_header)) &&
7137+ suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ, sanity_error)) {
7138+ suspendActiveAllocator->invalidate_image();
7139+ result = -EINVAL;
7140+ suspendActiveAllocator->read_header_cleanup();
7141+ noresume_reset_modules();
7142+ printk(name_suspend "Sanity check failed.\n");
7143+ goto out;
7144+ }
7145+
7146+ /*
7147+ * We have an image and it looks like it will load okay.
7148+ */
7149+
7150+ /* Get metadata from header. Don't override commandline parameters.
7151+ *
7152+ * We don't need to save the image size limit because it's not used
7153+ * during resume and will be restored with the image anyway.
7154+ */
7155+
7156+ suspend_orig_mem_free = suspend_header->orig_mem_free;
7157+ memcpy((char *) &pagedir1,
7158+ (char *) &suspend_header->pagedir, sizeof(pagedir1));
7159+ suspend_result = suspend_header->param0;
7160+ suspend_action = suspend_header->param1;
7161+ suspend_debug_state = suspend_header->param2;
7162+ console_loglevel = suspend_header->param3;
7163+ clear_suspend_state(SUSPEND_IGNORE_LOGLEVEL);
7164+ pagedir2.size = suspend_header->pageset_2_size;
7165+ for (i = 0; i < 4; i++)
7166+ suspend_io_time[i/2][i%2] =
7167+ suspend_header->io_time[i/2][i%2];
7168+
7169+ /* Read module configurations */
7170+ if ((result = read_module_configs())) {
7171+ suspendActiveAllocator->read_header_cleanup();
7172+ noresume_reset_modules();
7173+ pagedir1.size = pagedir2.size = 0;
7174+ printk(name_suspend "Failed to read Suspend module configurations.\n");
7175+ goto out;
7176+ }
7177+
7178+ suspend_prepare_console();
7179+
7180+ suspend_cond_pause(1, "About to read original pageset1 locations.");
7181+
7182+ /*
7183+ * Read original pageset1 locations. These are the addresses we can't
7184+ * use for the data to be restored.
7185+ */
7186+
7187+ allocate_dyn_pageflags(&pageset1_map);
7188+ load_dyn_pageflags(pageset1_map);
7189+
7190+ set_suspend_state(SUSPEND_NOW_RESUMING);
7191+
7192+ /* Relocate it so that it's not overwritten while we're using it to
7193+ * copy the original contents back */
7194+ relocate_dyn_pageflags(&pageset1_map);
7195+
7196+ allocate_dyn_pageflags(&pageset1_copy_map);
7197+ relocate_dyn_pageflags(&pageset1_copy_map);
7198+
7199+ /* Clean up after reading the header */
7200+ if ((result = suspendActiveAllocator->read_header_cleanup())) {
7201+ noresume_reset_modules();
7202+ printk(name_suspend "Failed to cleanup after reading the image header.\n");
7203+ goto out_reset_console;
7204+ }
7205+
7206+ suspend_cond_pause(1, "About to read pagedir.");
7207+
7208+ /*
7209+ * Get the addresses of pages into which we will load the kernel to
7210+ * be copied back
7211+ */
7212+ if (suspend_get_pageset1_load_addresses()) {
7213+ result = -ENOMEM;
7214+ noresume_reset_modules();
7215+ printk(name_suspend "Failed to get load addresses for pageset1.\n");
7216+ goto out_reset_console;
7217+ }
7218+
7219+ /* Read the original kernel back */
7220+ suspend_cond_pause(1, "About to read pageset 1.");
7221+
7222+ if (read_pageset(&pagedir1, 0)) {
7223+ suspend_prepare_status(CLEAR_BAR, "Failed to read pageset 1.");
7224+ result = -EPERM;
7225+ noresume_reset_modules();
7226+ printk(name_suspend "Failed to get load pageset1.\n");
7227+ goto out_reset_console;
7228+ }
7229+
7230+ suspend_cond_pause(1, "About to restore original kernel.");
7231+ result = 0;
7232+
7233+ if (!test_action_state(SUSPEND_KEEP_IMAGE) &&
7234+ suspendActiveAllocator->mark_resume_attempted)
7235+ suspendActiveAllocator->mark_resume_attempted();
7236+
7237+out:
7238+ free_page((unsigned long) header_buffer);
7239+ return result;
7240+
7241+out_reset_console:
7242+ free_dyn_pageflags(&pageset1_map);
7243+ free_dyn_pageflags(&pageset1_copy_map);
7244+ suspend_cleanup_console();
7245+ goto out;
7246+}
7247+
7248+/* read_pageset1()
7249+ *
7250+ * Description: Attempt to read the header and pageset1 of a suspend image.
7251+ * Handle the outcome, complaining where appropriate.
7252+ */
7253+
7254+int read_pageset1(void)
7255+{
7256+ int error;
7257+
7258+ error = __read_pageset1();
7259+
7260+ switch (error) {
7261+ case 0:
7262+ case -ENODATA:
7263+ case -EINVAL: /* non fatal error */
7264+ return error;
7265+ case -EIO:
7266+ printk(KERN_CRIT name_suspend "I/O error\n");
7267+ break;
7268+ case -ENOENT:
7269+ printk(KERN_CRIT name_suspend "No such file or directory\n");
7270+ break;
7271+ case -EPERM:
7272+ printk(KERN_CRIT name_suspend "Sanity check error\n");
7273+ break;
7274+ default:
7275+ printk(KERN_CRIT name_suspend "Error %d resuming\n",
7276+ error);
7277+ break;
7278+ }
7279+ abort_suspend("Error %d in read_pageset1",error);
7280+ return error;
7281+}
7282+
7283+/*
7284+ * get_have_image_data()
7285+ */
7286+char *get_have_image_data(void)
7287+{
7288+ char *output_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
7289+ struct suspend_header *suspend_header;
7290+
7291+ if (!output_buffer) {
7292+ printk("Output buffer null.\n");
7293+ return NULL;
7294+ }
7295+
7296+ /* Check for an image */
7297+ if (!suspendActiveAllocator->image_exists() ||
7298+ suspendActiveAllocator->read_header_init() ||
7299+ suspendActiveAllocator->rw_header_chunk(READ, NULL,
7300+ output_buffer, sizeof(struct suspend_header)) !=
7301+ sizeof(struct suspend_header)) {
7302+ sprintf(output_buffer, "0\n");
7303+ goto out;
7304+ }
7305+
7306+ suspend_header = (struct suspend_header *) output_buffer;
7307+
7308+ sprintf(output_buffer, "1\n%s\n%s\n",
7309+ suspend_header->uts.machine,
7310+ suspend_header->uts.version);
7311+
7312+ /* Check whether we've resumed before */
7313+ if (test_suspend_state(SUSPEND_RESUMED_BEFORE))
7314+ strcat(output_buffer, "Resumed before.\n");
7315+
7316+out:
7317+ noresume_reset_modules();
7318+ return output_buffer;
7319+}
7320+
7321+/* read_pageset2()
7322+ *
7323+ * Description: Read in part or all of pageset2 of an image, depending upon
7324+ * whether we are suspending and have only overwritten a portion
7325+ * with pageset1 pages, or are resuming and need to read them
7326+ * all.
7327+ * Arguments: Int. Boolean. Read only pages which would have been
7328+ * overwritten by pageset1?
7329+ * Returns: Int. Zero if no error, otherwise the error value.
7330+ */
7331+int read_pageset2(int overwrittenpagesonly)
7332+{
7333+ int result = 0;
7334+
7335+ if (!pagedir2.size)
7336+ return 0;
7337+
7338+ result = read_pageset(&pagedir2, overwrittenpagesonly);
7339+
7340+ suspend_update_status(100, 100, NULL);
7341+ suspend_cond_pause(1, "Pagedir 2 read.");
7342+
7343+ return result;
7344+}
7345diff --git a/kernel/power/io.h b/kernel/power/io.h
7346new file mode 100644
7347index 0000000..a56c635
7348--- /dev/null
7349+++ b/kernel/power/io.h
7350@@ -0,0 +1,45 @@
7351+/*
7352+ * kernel/power/io.h
7353+ *
7354+ * Copyright (C) 2005-2006 Nigel Cunningham <nigel@suspend2.net>
7355+ * Copyright (C) 2006 Red Hat, inc.
7356+ *
7357+ * This file is released under the GPLv2.
7358+ *
7359+ * It contains high level IO routines for suspending.
7360+ *
7361+ */
7362+
7363+#include "pagedir.h"
7364+
7365+/* Non-module data saved in our image header */
7366+struct suspend_header {
7367+ u32 version_code;
7368+ unsigned long num_physpages;
7369+ unsigned long orig_mem_free;
7370+ struct new_utsname uts;
7371+ int num_cpus;
7372+ int page_size;
7373+ int pageset_2_size;
7374+ int param0;
7375+ int param1;
7376+ int param2;
7377+ int param3;
7378+ int progress0;
7379+ int progress1;
7380+ int progress2;
7381+ int progress3;
7382+ int io_time[2][2];
7383+ struct pagedir pagedir;
7384+ dev_t root_fs;
7385+};
7386+
7387+extern int write_pageset(struct pagedir *pagedir);
7388+extern int write_image_header(void);
7389+extern int read_pageset1(void);
7390+extern int read_pageset2(int overwrittenpagesonly);
7391+
7392+extern int suspend_attempt_to_parse_resume_device(void);
7393+extern void attempt_to_parse_resume_device2(void);
7394+extern dev_t name_to_dev_t(char *line);
7395+extern char *get_have_image_data(void);
7396diff --git a/kernel/power/main.c b/kernel/power/main.c
7397index 873228c..46f3ec4 100644
7398--- a/kernel/power/main.c
7399+++ b/kernel/power/main.c
7400@@ -9,6 +9,7 @@
7401 */
7402
7403 #include <linux/suspend.h>
7404+#include <linux/freezer.h>
7405 #include <linux/kobject.h>
7406 #include <linux/string.h>
7407 #include <linux/delay.h>
7408@@ -147,7 +148,7 @@ static void suspend_finish(suspend_state
7409 static const char * const pm_states[PM_SUSPEND_MAX] = {
7410 [PM_SUSPEND_STANDBY] = "standby",
7411 [PM_SUSPEND_MEM] = "mem",
7412-#ifdef CONFIG_SOFTWARE_SUSPEND
7413+#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_SUSPEND2)
7414 [PM_SUSPEND_DISK] = "disk",
7415 #endif
7416 };
7417diff --git a/kernel/power/modules.c b/kernel/power/modules.c
7418new file mode 100644
7419index 0000000..13b6e3a
7420--- /dev/null
7421+++ b/kernel/power/modules.c
7422@@ -0,0 +1,353 @@
7423+/*
7424+ * kernel/power/modules.c
7425+ *
7426+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
7427+ * Copyright (C) 2006 Red Hat, inc.
7428+ *
7429+ */
7430+
7431+#include <linux/suspend.h>
7432+#include <linux/module.h>
7433+#include "suspend.h"
7434+#include "modules.h"
7435+#include "sysfs.h"
7436+#include "ui.h"
7437+
7438+struct list_head suspend_filters, suspendAllocators, suspend_modules;
7439+struct suspend_module_ops *suspendActiveAllocator;
7440+static int suspend_num_filters;
7441+int suspendNumAllocators, suspend_num_modules;
7442+
7443+/*
7444+ * suspend_header_storage_for_modules
7445+ *
7446+ * Returns the amount of space needed to store configuration
7447+ * data needed by the modules prior to copying back the original
7448+ * kernel. We can exclude data for pageset2 because it will be
7449+ * available anyway once the kernel is copied back.
7450+ */
7451+int suspend_header_storage_for_modules(void)
7452+{
7453+ struct suspend_module_ops *this_module;
7454+ int bytes = 0;
7455+
7456+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7457+ if (!this_module->enabled ||
7458+ (this_module->type == WRITER_MODULE &&
7459+ suspendActiveAllocator != this_module))
7460+ continue;
7461+ if (this_module->storage_needed) {
7462+ int this = this_module->storage_needed() +
7463+ sizeof(struct suspend_module_header) +
7464+ sizeof(int);
7465+ this_module->header_requested = this;
7466+ bytes += this;
7467+ }
7468+ }
7469+
7470+ /* One more for the empty terminator */
7471+ return bytes + sizeof(struct suspend_module_header);
7472+}
7473+
7474+/*
7475+ * suspend_memory_for_modules
7476+ *
7477+ * Returns the amount of memory requested by modules for
7478+ * doing their work during the cycle.
7479+ */
7480+
7481+int suspend_memory_for_modules(void)
7482+{
7483+ int bytes = 0;
7484+ struct suspend_module_ops *this_module;
7485+
7486+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7487+ if (!this_module->enabled)
7488+ continue;
7489+ if (this_module->memory_needed)
7490+ bytes += this_module->memory_needed();
7491+ }
7492+
7493+ return ((bytes + PAGE_SIZE - 1) >> PAGE_SHIFT);
7494+}
7495+
7496+/* suspend_find_module_given_name
7497+ * Functionality : Return a module (if found), given a pointer
7498+ * to its name
7499+ */
7500+
7501+struct suspend_module_ops *suspend_find_module_given_name(char *name)
7502+{
7503+ struct suspend_module_ops *this_module, *found_module = NULL;
7504+
7505+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7506+ if (!strcmp(name, this_module->name)) {
7507+ found_module = this_module;
7508+ break;
7509+ }
7510+ }
7511+
7512+ return found_module;
7513+}
7514+
7515+/*
7516+ * suspend_print_module_debug_info
7517+ * Functionality : Get debugging info from modules into a buffer.
7518+ */
7519+int suspend_print_module_debug_info(char *buffer, int buffer_size)
7520+{
7521+ struct suspend_module_ops *this_module;
7522+ int len = 0;
7523+
7524+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7525+ if (!this_module->enabled)
7526+ continue;
7527+ if (this_module->print_debug_info) {
7528+ int result;
7529+ result = this_module->print_debug_info(buffer + len,
7530+ buffer_size - len);
7531+ len += result;
7532+ }
7533+ }
7534+
7535+ /* Ensure null terminated */
7536+ buffer[buffer_size] = 0;
7537+
7538+ return len;
7539+}
7540+
7541+/*
7542+ * suspend_register_module
7543+ *
7544+ * Register a module.
7545+ */
7546+int suspend_register_module(struct suspend_module_ops *module)
7547+{
7548+ int i;
7549+ struct kobject *kobj;
7550+
7551+ module->enabled = 1;
7552+
7553+ if (suspend_find_module_given_name(module->name)) {
7554+ printk(name_suspend "Trying to load module %s,"
7555+ " which is already registered.\n",
7556+ module->name);
7557+ return -EBUSY;
7558+ }
7559+
7560+ switch (module->type) {
7561+ case FILTER_MODULE:
7562+ list_add_tail(&module->type_list,
7563+ &suspend_filters);
7564+ suspend_num_filters++;
7565+ break;
7566+
7567+ case WRITER_MODULE:
7568+ list_add_tail(&module->type_list,
7569+ &suspendAllocators);
7570+ suspendNumAllocators++;
7571+ break;
7572+
7573+ case MISC_MODULE:
7574+ break;
7575+
7576+ default:
7577+ printk("Hmmm. Module '%s' has an invalid type."
7578+ " It has been ignored.\n", module->name);
7579+ return -EINVAL;
7580+ }
7581+ list_add_tail(&module->module_list, &suspend_modules);
7582+ suspend_num_modules++;
7583+
7584+ printk("Suspend2 %s module loaded.\n", module->name);
7585+ if (module->directory) {
7586+ kobj = make_suspend2_sysdir(module->directory);
7587+ for (i=0; i < module->num_sysfs_entries; i++) {
7588+ int result = suspend_register_sysfs_file(kobj, &module->sysfs_data[i]);
7589+ if (result)
7590+ return result;
7591+ }
7592+ }
7593+ return 0;
7594+}
7595+
7596+/*
7597+ * suspend_unregister_module
7598+ *
7599+ * Remove a module.
7600+ */
7601+void suspend_unregister_module(struct suspend_module_ops *module)
7602+{
7603+ int i;
7604+
7605+ for (i=0; i < module->num_sysfs_entries; i++)
7606+ suspend_unregister_sysfs_file(&module->sysfs_data[i]);
7607+ /* If we do kernel modules again, we'll need to unregister the dir here */
7608+
7609+ switch (module->type) {
7610+ case FILTER_MODULE:
7611+ list_del(&module->type_list);
7612+ suspend_num_filters--;
7613+ break;
7614+
7615+ case WRITER_MODULE:
7616+ list_del(&module->type_list);
7617+ suspendNumAllocators--;
7618+ if (suspendActiveAllocator == module) {
7619+ suspendActiveAllocator = NULL;
7620+ clear_suspend_state(SUSPEND_CAN_RESUME);
7621+ clear_suspend_state(SUSPEND_CAN_SUSPEND);
7622+ }
7623+ break;
7624+
7625+ case MISC_MODULE:
7626+ break;
7627+
7628+ default:
7629+ printk("Hmmm. Module '%s' has an invalid type."
7630+ " It has been ignored.\n", module->name);
7631+ return;
7632+ }
7633+ list_del(&module->module_list);
7634+ suspend_num_modules--;
7635+}
7636+
7637+/*
7638+ * suspend_move_module_tail
7639+ *
7640+ * Rearrange modules when reloading the config.
7641+ */
7642+void suspend_move_module_tail(struct suspend_module_ops *module)
7643+{
7644+ switch (module->type) {
7645+ case FILTER_MODULE:
7646+ if (suspend_num_filters > 1)
7647+ list_move_tail(&module->type_list,
7648+ &suspend_filters);
7649+ break;
7650+
7651+ case WRITER_MODULE:
7652+ if (suspendNumAllocators > 1)
7653+ list_move_tail(&module->type_list,
7654+ &suspendAllocators);
7655+ break;
7656+
7657+ case MISC_MODULE:
7658+ break;
7659+ default:
7660+ printk("Hmmm. Module '%s' has an invalid type."
7661+ " It has been ignored.\n", module->name);
7662+ return;
7663+ }
7664+ if ((suspend_num_filters + suspendNumAllocators) > 1)
7665+ list_move_tail(&module->module_list, &suspend_modules);
7666+}
7667+
7668+/*
7669+ * suspend_initialise_modules
7670+ *
7671+ * Get ready to do some work!
7672+ */
7673+int suspend_initialise_modules(int starting_cycle)
7674+{
7675+ struct suspend_module_ops *this_module;
7676+ int result;
7677+
7678+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7679+ this_module->header_requested = 0;
7680+ this_module->header_used = 0;
7681+ if (!this_module->enabled)
7682+ continue;
7683+ if (this_module->initialise) {
7684+ suspend_message(SUSPEND_MEMORY, SUSPEND_MEDIUM, 1,
7685+ "Initialising module %s.\n",
7686+ this_module->name);
7687+ if ((result = this_module->initialise(starting_cycle))) {
7688+ printk("%s didn't initialise okay.\n",
7689+ this_module->name);
7690+ return result;
7691+ }
7692+ }
7693+ }
7694+
7695+ return 0;
7696+}
7697+
7698+/*
7699+ * suspend_cleanup_modules
7700+ *
7701+ * Tell modules the work is done.
7702+ */
7703+void suspend_cleanup_modules(int finishing_cycle)
7704+{
7705+ struct suspend_module_ops *this_module;
7706+
7707+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7708+ if (!this_module->enabled)
7709+ continue;
7710+ if (this_module->cleanup) {
7711+ suspend_message(SUSPEND_MEMORY, SUSPEND_MEDIUM, 1,
7712+ "Cleaning up module %s.\n",
7713+ this_module->name);
7714+ this_module->cleanup(finishing_cycle);
7715+ }
7716+ }
7717+}
7718+
7719+/*
7720+ * suspend_get_next_filter
7721+ *
7722+ * Get the next filter in the pipeline.
7723+ */
7724+struct suspend_module_ops *suspend_get_next_filter(struct suspend_module_ops *filter_sought)
7725+{
7726+ struct suspend_module_ops *last_filter = NULL, *this_filter = NULL;
7727+
7728+ list_for_each_entry(this_filter, &suspend_filters, type_list) {
7729+ if (!this_filter->enabled)
7730+ continue;
7731+ if ((last_filter == filter_sought) || (!filter_sought))
7732+ return this_filter;
7733+ last_filter = this_filter;
7734+ }
7735+
7736+ return suspendActiveAllocator;
7737+}
7738+
7739+/* suspend_get_modules
7740+ *
7741+ * Take a reference to modules so they can't go away under us.
7742+ */
7743+
7744+int suspend_get_modules(void)
7745+{
7746+ struct suspend_module_ops *this_module;
7747+
7748+ list_for_each_entry(this_module, &suspend_modules, module_list) {
7749+ if (!try_module_get(this_module->module)) {
7750+ /* Failed! Reverse gets and return error */
7751+ struct suspend_module_ops *this_module2;
7752+ list_for_each_entry(this_module2, &suspend_modules, module_list) {
7753+ if (this_module == this_module2)
7754+ return -EINVAL;
7755+ module_put(this_module2->module);
7756+ }
7757+ }
7758+ }
7759+
7760+ return 0;
7761+}
7762+
7763+/* suspend_put_modules
7764+ *
7765+ * Release our references to modules we used.
7766+ */
7767+
7768+void suspend_put_modules(void)
7769+{
7770+ struct suspend_module_ops *this_module;
7771+
7772+ list_for_each_entry(this_module, &suspend_modules, module_list)
7773+ module_put(this_module->module);
7774+}
7775+
7776diff --git a/kernel/power/modules.h b/kernel/power/modules.h
7777new file mode 100644
7778index 0000000..b8c2780
7779--- /dev/null
7780+++ b/kernel/power/modules.h
7781@@ -0,0 +1,165 @@
7782+/*
7783+ * kernel/power/modules.h
7784+ *
7785+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
7786+ * Copyright (C) 2006 Red Hat, inc.
7787+ *
7788+ * This file is released under the GPLv2.
7789+ *
7790+ * It contains declarations for modules. Modules are additions to
7791+ * suspend2 that provide facilities such as image compression or
7792+ * encryption, backends for storage of the image and user interfaces.
7793+ *
7794+ */
7795+
7796+#ifndef SUSPEND_MODULES_H
7797+#define SUSPEND_MODULES_H
7798+
7799+/* This is the maximum size we store in the image header for a module name */
7800+#define SUSPEND_MAX_MODULE_NAME_LENGTH 30
7801+
7802+/* Per-module metadata */
7803+struct suspend_module_header {
7804+ char name[SUSPEND_MAX_MODULE_NAME_LENGTH];
7805+ int enabled;
7806+ int type;
7807+ int index;
7808+ int data_length;
7809+ unsigned long signature;
7810+};
7811+
7812+extern int suspend_num_modules, suspendNumAllocators;
7813+
7814+enum {
7815+ FILTER_MODULE,
7816+ WRITER_MODULE,
7817+ MISC_MODULE /* Block writer, eg. */
7818+};
7819+
7820+enum {
7821+ SUSPEND_ASYNC,
7822+ SUSPEND_SYNC
7823+};
7824+
7825+struct suspend_module_ops {
7826+ /* Functions common to all modules */
7827+ int type;
7828+ char *name;
7829+ char *directory;
7830+ struct module *module;
7831+ int enabled;
7832+ struct list_head module_list;
7833+
7834+ /* List of filters or allocators */
7835+ struct list_head list, type_list;
7836+
7837+ /*
7838+ * Requirements for memory and storage in
7839+ * the image header..
7840+ */
7841+ int (*memory_needed) (void);
7842+ int (*storage_needed) (void);
7843+
7844+ int header_requested, header_used;
7845+
7846+ /*
7847+ * Debug info
7848+ */
7849+ int (*print_debug_info) (char *buffer, int size);
7850+ int (*save_config_info) (char *buffer);
7851+ void (*load_config_info) (char *buffer, int len);
7852+
7853+ /*
7854+ * Initialise & cleanup - general routines called
7855+ * at the start and end of a cycle.
7856+ */
7857+ int (*initialise) (int starting_cycle);
7858+ void (*cleanup) (int finishing_cycle);
7859+
7860+ /*
7861+ * Calls for allocating storage (allocators only).
7862+ *
7863+ * Header space is allocated separately. Note that allocation
7864+ * of space for the header might result in allocated space
7865+ * being stolen from the main pool if there is no unallocated
7866+ * space. We have to be able to allocate enough space for
7867+ * the header. We can eat memory to ensure there is enough
7868+ * for the main pool.
7869+ */
7870+
7871+ int (*storage_available) (void);
7872+ int (*allocate_header_space) (int space_requested);
7873+ int (*allocate_storage) (int space_requested);
7874+ int (*storage_allocated) (void);
7875+ int (*release_storage) (void);
7876+
7877+ /*
7878+ * Routines used in image I/O.
7879+ */
7880+ int (*rw_init) (int rw, int stream_number);
7881+ int (*rw_cleanup) (int rw);
7882+ int (*write_chunk) (struct page *buffer_page);
7883+ int (*read_chunk) (struct page *buffer_page, int sync);
7884+
7885+ /* Reset module if image exists but reading aborted */
7886+ void (*noresume_reset) (void);
7887+
7888+ /* Read and write the metadata */
7889+ int (*write_header_init) (void);
7890+ int (*write_header_cleanup) (void);
7891+
7892+ int (*read_header_init) (void);
7893+ int (*read_header_cleanup) (void);
7894+
7895+ int (*rw_header_chunk) (int rw, struct suspend_module_ops *owner,
7896+ char *buffer_start, int buffer_size);
7897+
7898+ /* Attempt to parse an image location */
7899+ int (*parse_sig_location) (char *buffer, int only_writer);
7900+
7901+ /* Determine whether image exists that we can restore */
7902+ int (*image_exists) (void);
7903+
7904+ /* Mark the image as having tried to resume */
7905+ void (*mark_resume_attempted) (void);
7906+
7907+ /* Destroy image if one exists */
7908+ int (*invalidate_image) (void);
7909+
7910+ /* Sysfs Data */
7911+ struct suspend_sysfs_data *sysfs_data;
7912+ int num_sysfs_entries;
7913+};
7914+
7915+extern struct suspend_module_ops *suspendActiveAllocator;
7916+extern struct list_head suspend_filters, suspendAllocators, suspend_modules;
7917+
7918+extern void suspend_prepare_console_modules(void);
7919+extern void suspend_cleanup_console_modules(void);
7920+
7921+extern struct suspend_module_ops *suspend_find_module_given_name(char *name),
7922+ *suspend_get_next_filter(struct suspend_module_ops *);
7923+
7924+extern int suspend_register_module(struct suspend_module_ops *module);
7925+extern void suspend_move_module_tail(struct suspend_module_ops *module);
7926+
7927+extern int suspend_header_storage_for_modules(void);
7928+extern int suspend_memory_for_modules(void);
7929+
7930+extern int suspend_print_module_debug_info(char *buffer, int buffer_size);
7931+extern int suspend_register_module(struct suspend_module_ops *module);
7932+extern void suspend_unregister_module(struct suspend_module_ops *module);
7933+
7934+extern int suspend_initialise_modules(int starting_cycle);
7935+extern void suspend_cleanup_modules(int finishing_cycle);
7936+
7937+int suspend_get_modules(void);
7938+void suspend_put_modules(void);
7939+
7940+static inline void suspend_initialise_module_lists(void) {
7941+ INIT_LIST_HEAD(&suspend_filters);
7942+ INIT_LIST_HEAD(&suspendAllocators);
7943+ INIT_LIST_HEAD(&suspend_modules);
7944+}
7945+
7946+#endif
7947diff --git a/kernel/power/netlink.c b/kernel/power/netlink.c
7948new file mode 100644
7949index 0000000..a1998a8
7950--- /dev/null
7951+++ b/kernel/power/netlink.c
7952@@ -0,0 +1,376 @@
7953+/*
7954+ * kernel/power/netlink.c
7955+ *
7956+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
7957+ * Copyright (C) 2006 Red Hat, inc.
7958+ *
7959+ * This file is released under the GPLv2.
7960+ *
7961+ * Functions for communicating with a userspace helper via netlink.
7962+ */
7963+
7964+
7965+#include <linux/suspend.h>
7966+#include "netlink.h"
7967+
7968+#ifdef CONFIG_NET
7969+struct user_helper_data *uhd_list = NULL;
7970+
7971+/*
7972+ * Refill our pool of SKBs for use in emergencies (eg, when eating memory and none
7973+ * can be allocated).
7974+ */
7975+static void suspend_fill_skb_pool(struct user_helper_data *uhd)
7976+{
7977+ while (uhd->pool_level < uhd->pool_limit) {
7978+ struct sk_buff *new_skb =
7979+ alloc_skb(NLMSG_SPACE(uhd->skb_size), GFP_ATOMIC);
7980+
7981+ if (!new_skb)
7982+ break;
7983+
7984+ new_skb->next = uhd->emerg_skbs;
7985+ uhd->emerg_skbs = new_skb;
7986+ uhd->pool_level++;
7987+ }
7988+}
7989+
7990+/*
7991+ * Try to allocate a single skb. If we can't get one, try to use one from
7992+ * our pool.
7993+ */
7994+static struct sk_buff *suspend_get_skb(struct user_helper_data *uhd)
7995+{
7996+ struct sk_buff *skb =
7997+ alloc_skb(NLMSG_SPACE(uhd->skb_size), GFP_ATOMIC);
7998+
7999+ if (skb)
8000+ return skb;
8001+
8002+ skb = uhd->emerg_skbs;
8003+ if (skb) {
8004+ uhd->pool_level--;
8005+ uhd->emerg_skbs = skb->next;
8006+ skb->next = NULL;
8007+ }
8008+
8009+ return skb;
8010+}
8011+
8012+static void put_skb(struct user_helper_data *uhd, struct sk_buff *skb)
8013+{
8014+ if (uhd->pool_level < uhd->pool_limit) {
8015+ skb->next = uhd->emerg_skbs;
8016+ uhd->emerg_skbs = skb;
8017+ } else
8018+ kfree_skb(skb);
8019+}
8020+
8021+
8022+static void suspend_notify_userspace(void* data)
8023+{
8024+ struct task_struct *t;
8025+ struct user_helper_data *uhd = (struct user_helper_data *) data;
8026+
8027+ BUG_ON(!uhd);
8028+
8029+ read_lock(&tasklist_lock);
8030+ if ((t = find_task_by_pid(uhd->pid)))
8031+ wake_up_process(t);
8032+ read_unlock(&tasklist_lock);
8033+}
8034+
8035+DECLARE_WORK(suspend_notify_userspace_work, suspend_notify_userspace, NULL);
8036+
8037+void suspend_send_netlink_message(struct user_helper_data *uhd,
8038+ int type, void* params, size_t len)
8039+{
8040+ struct sk_buff *skb;
8041+ struct nlmsghdr *nlh;
8042+ void *dest;
8043+
8044+ if (uhd->pid == -1)
8045+ return;
8046+
8047+ skb = suspend_get_skb(uhd);
8048+ if (!skb) {
8049+ printk("suspend_netlink: Can't allocate skb!\n");
8050+ return;
8051+ }
8052+
8053+ /* NLMSG_PUT contains a hidden goto nlmsg_failure */
8054+ nlh = NLMSG_PUT(skb, 0, uhd->sock_seq, type, len);
8055+ uhd->sock_seq++;
8056+
8057+ dest = NLMSG_DATA(nlh);
8058+ if (params && len > 0)
8059+ memcpy(dest, params, len);
8060+
8061+ netlink_unicast(uhd->nl, skb, uhd->pid, 0);
8062+
8063+ /* We may be in an interrupt context so defer waking up userspace */
8064+ suspend_notify_userspace_work.data = uhd;
8065+ schedule_work(&suspend_notify_userspace_work);
8066+
8067+ return;
8068+
8069+nlmsg_failure:
8070+ if (skb)
8071+ put_skb(uhd, skb);
8072+}
8073+
8074+#if 1 //#ifdef CONFIG_PM_DEBUG
8075+static int is_debugging = 1;
8076+#else
8077+static int is_debugging = 0;
8078+#endif
8079+
8080+static void send_whether_debugging(struct user_helper_data *uhd)
8081+{
8082+ suspend_send_netlink_message(uhd, NETLINK_MSG_IS_DEBUGGING,
8083+ &is_debugging, sizeof(int));
8084+}
8085+
8086+/*
8087+ * Set the PF_NOFREEZE flag on the given process to ensure it can run whilst we
8088+ * are suspending.
8089+ */
8090+static int nl_set_nofreeze(struct user_helper_data *uhd, int pid)
8091+{
8092+ struct task_struct *t;
8093+
8094+ read_lock(&tasklist_lock);
8095+ if ((t = find_task_by_pid(pid)) == NULL) {
8096+ read_unlock(&tasklist_lock);
8097+ printk("Strange. Can't find the userspace task %d.\n", pid);
8098+ return -EINVAL;
8099+ }
8100+
8101+ t->flags |= PF_NOFREEZE;
8102+
8103+ read_unlock(&tasklist_lock);
8104+ uhd->pid = pid;
8105+
8106+ suspend_send_netlink_message(uhd, NETLINK_MSG_NOFREEZE_ACK, NULL, 0);
8107+
8108+ return 0;
8109+}
8110+
8111+/*
8112+ * Called when the userspace process has informed us that it's ready to roll.
8113+ */
8114+static int nl_ready(struct user_helper_data *uhd, int version)
8115+{
8116+ if (version != uhd->interface_version) {
8117+ printk("%s userspace process using invalid interface version."
8118+ " Trying to continue without it.\n",
8119+ uhd->name);
8120+ if (uhd->not_ready)
8121+ uhd->not_ready();
8122+ return 1;
8123+ }
8124+
8125+ complete(&uhd->wait_for_process);
8126+
8127+ return 0;
8128+}
8129+
8130+static int suspend_nl_gen_rcv_msg(struct user_helper_data *uhd,
8131+ struct sk_buff *skb, struct nlmsghdr *nlh)
8132+{
8133+ int type;
8134+ int *data;
8135+ int err;
8136+
8137+ /* Let the more specific handler go first. It returns
8138+ * 1 for valid messages that it doesn't know. */
8139+ if ((err = uhd->rcv_msg(skb, nlh)) != 1)
8140+ return err;
8141+
8142+ type = nlh->nlmsg_type;
8143+
8144+ /* Only allow one task to receive NOFREEZE privileges */
8145+ if (type == NETLINK_MSG_NOFREEZE_ME && uhd->pid != -1) {
8146+ printk("Received extra nofreeze me requests.\n");
8147+ return -EBUSY;
8148+ }
8149+
8150+ data = (int*)NLMSG_DATA(nlh);
8151+
8152+ switch (type) {
8153+ case NETLINK_MSG_NOFREEZE_ME:
8154+ if ((err = nl_set_nofreeze(uhd, nlh->nlmsg_pid)) != 0)
8155+ return err;
8156+ break;
8157+ case NETLINK_MSG_GET_DEBUGGING:
8158+ send_whether_debugging(uhd);
8159+ break;
8160+ case NETLINK_MSG_READY:
8161+ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(int))) {
8162+ printk("Invalid ready mesage.\n");
8163+ return -EINVAL;
8164+ }
8165+ if ((err = nl_ready(uhd, *data)) != 0)
8166+ return err;
8167+ break;
8168+ }
8169+
8170+ return 0;
8171+}
8172+
8173+static void suspend_user_rcv_skb(struct user_helper_data *uhd,
8174+ struct sk_buff *skb)
8175+{
8176+ int err;
8177+ struct nlmsghdr *nlh;
8178+
8179+ while (skb->len >= NLMSG_SPACE(0)) {
8180+ u32 rlen;
8181+
8182+ nlh = (struct nlmsghdr *) skb->data;
8183+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
8184+ return;
8185+
8186+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
8187+ if (rlen > skb->len)
8188+ rlen = skb->len;
8189+
8190+ if ((err = suspend_nl_gen_rcv_msg(uhd, skb, nlh)) != 0)
8191+ netlink_ack(skb, nlh, err);
8192+ else if (nlh->nlmsg_flags & NLM_F_ACK)
8193+ netlink_ack(skb, nlh, 0);
8194+ skb_pull(skb, rlen);
8195+ }
8196+}
8197+
8198+static void suspend_netlink_input(struct sock *sk, int len)
8199+{
8200+ struct user_helper_data *uhd = uhd_list;
8201+
8202+ while (uhd && uhd->netlink_id != sk->sk_protocol)
8203+ uhd= uhd->next;
8204+
8205+ BUG_ON(!uhd);
8206+
8207+ do {
8208+ struct sk_buff *skb;
8209+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
8210+ suspend_user_rcv_skb(uhd, skb);
8211+ put_skb(uhd, skb);
8212+ }
8213+ } while (uhd->nl && uhd->nl->sk_receive_queue.qlen);
8214+}
8215+
8216+static int netlink_prepare(struct user_helper_data *uhd)
8217+{
8218+ uhd->next = uhd_list;
8219+ uhd_list = uhd;
8220+
8221+ uhd->sock_seq = 0x42c0ffee;
8222+ uhd->nl = netlink_kernel_create(uhd->netlink_id, 0,
8223+ suspend_netlink_input, THIS_MODULE);
8224+ if (!uhd->nl) {
8225+ printk("Failed to allocate netlink socket for %s.\n",
8226+ uhd->name);
8227+ return -ENOMEM;
8228+ }
8229+
8230+ suspend_fill_skb_pool(uhd);
8231+
8232+ return 0;
8233+}
8234+
8235+void suspend_netlink_close(struct user_helper_data *uhd)
8236+{
8237+ if (uhd->nl) {
8238+ sock_release(uhd->nl->sk_socket);
8239+ uhd->nl = NULL;
8240+ }
8241+
8242+ while (uhd->emerg_skbs) {
8243+ struct sk_buff *next = uhd->emerg_skbs->next;
8244+ kfree_skb(uhd->emerg_skbs);
8245+ uhd->emerg_skbs = next;
8246+ }
8247+}
8248+
8249+int suspend2_launch_userspace_program(char *command, int channel_no)
8250+{
8251+ int retval;
8252+ static char *envp[] = {
8253+ "HOME=/",
8254+ "TERM=linux",
8255+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
8256+ NULL };
8257+ static char *argv[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
8258+ char *channel = kmalloc(6, GFP_KERNEL);
8259+ int arg = 0, size;
8260+ char test_read[255];
8261+ char *orig_posn = command;
8262+
8263+ if (!strlen(orig_posn))
8264+ return 1;
8265+
8266+ /* Up to 7 args supported */
8267+ while (arg < 7) {
8268+ sscanf(orig_posn, "%s", test_read);
8269+ size = strlen(test_read);
8270+ if (!(size))
8271+ break;
8272+ argv[arg] = kmalloc(size + 1, GFP_ATOMIC);
8273+ strcpy(argv[arg], test_read);
8274+ orig_posn += size + 1;
8275+ *test_read = 0;
8276+ arg++;
8277+ }
8278+
8279+ if (channel_no) {
8280+ sprintf(channel, "-c%d", channel_no);
8281+ argv[arg] = channel;
8282+ } else
8283+ arg--;
8284+
8285+ retval = call_usermodehelper(argv[0], argv, envp, 0);
8286+
8287+ if (retval)
8288+ printk("Failed to launch userspace program '%s': Error %d\n",
8289+ command, retval);
8290+
8291+ {
8292+ int i;
8293+ for (i = 0; i < arg; i++)
8294+ if (argv[i] && argv[i] != channel)
8295+ kfree(argv[i]);
8296+ }
8297+
8298+ kfree(channel);
8299+
8300+ return retval;
8301+}
8302+
8303+int suspend_netlink_setup(struct user_helper_data *uhd)
8304+{
8305+ if (netlink_prepare(uhd) < 0) {
8306+ printk("Netlink prepare failed.\n");
8307+ return 1;
8308+ }
8309+
8310+ if (suspend2_launch_userspace_program(uhd->program, uhd->netlink_id) < 0) {
8311+ printk("Launch userspace program failed.\n");
8312+ suspend_netlink_close(uhd);
8313+ return 1;
8314+ }
8315+
8316+ /* Wait 2 seconds for the userspace process to make contact */
8317+ wait_for_completion_timeout(&uhd->wait_for_process, 2*HZ);
8318+
8319+ if (uhd->pid == -1) {
8320+ printk("%s: Failed to contact userspace process.\n",
8321+ uhd->name);
8322+ suspend_netlink_close(uhd);
8323+ return 1;
8324+ }
8325+
8326+ return 0;
8327+}
8328+#endif
8329diff --git a/kernel/power/netlink.h b/kernel/power/netlink.h
8330new file mode 100644
8331index 0000000..a5b09de
8332--- /dev/null
8333+++ b/kernel/power/netlink.h
8334@@ -0,0 +1,60 @@
8335+/*
8336+ * kernel/power/netlink.h
8337+ *
8338+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
8339+ * Copyright (C) 2006 Red Hat, inc.
8340+ *
8341+ * This file is released under the GPLv2.
8342+ *
8343+ * Declarations for functions for communicating with a userspace helper
8344+ * via netlink.
8345+ */
8346+
8347+#include <linux/netlink.h>
8348+#include <net/sock.h>
8349+
8350+#define NETLINK_MSG_BASE 0x10
8351+
8352+#define NETLINK_MSG_READY 0x10
8353+#define NETLINK_MSG_NOFREEZE_ME 0x16
8354+#define NETLINK_MSG_GET_DEBUGGING 0x19
8355+#define NETLINK_MSG_CLEANUP 0x24
8356+#define NETLINK_MSG_NOFREEZE_ACK 0x27
8357+#define NETLINK_MSG_IS_DEBUGGING 0x28
8358+
8359+struct user_helper_data {
8360+ int (*rcv_msg) (struct sk_buff *skb, struct nlmsghdr *nlh);
8361+ void (* not_ready) (void);
8362+ struct sock *nl;
8363+ u32 sock_seq;
8364+ pid_t pid;
8365+ char *comm;
8366+ char program[256];
8367+ int pool_level;
8368+ int pool_limit;
8369+ struct sk_buff *emerg_skbs;
8370+ int skb_size;
8371+ int netlink_id;
8372+ char *name;
8373+ struct user_helper_data *next;
8374+ struct completion wait_for_process;
8375+ int interface_version;
8376+ int must_init;
8377+};
8378+
8379+
8380+#ifdef CONFIG_NET
8381+int suspend_netlink_setup(struct user_helper_data *uhd);
8382+void suspend_netlink_close(struct user_helper_data *uhd);
8383+void suspend_send_netlink_message(struct user_helper_data *uhd,
8384+ int type, void* params, size_t len);
8385+#else
8386+static inline int suspend_netlink_setup(struct user_helper_data *uhd)
8387+{
8388+ return 0;
8389+}
8390+
8391+static inline void suspend_netlink_close(struct user_helper_data *uhd) { };
8392+static inline void suspend_send_netlink_message(struct user_helper_data *uhd,
8393+ int type, void* params, size_t len) { };
8394+#endif
8395diff --git a/kernel/power/pagedir.c b/kernel/power/pagedir.c
8396new file mode 100644
8397index 0000000..09867f7
8398--- /dev/null
8399+++ b/kernel/power/pagedir.c
8400@@ -0,0 +1,309 @@
8401+/*
8402+ * kernel/power/pagedir.c
8403+ *
8404+ * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
8405+ * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
8406+ * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr>
8407+ * Copyright (C) 2002-2006 Nigel Cunningham <nigel@suspend2.net>
8408+ * Copyright (C) 2006 Red Hat, inc.
8409+ *
8410+ * This file is released under the GPLv2.
8411+ *
8412+ * Routines for handling pagesets.
8413+ * Note that pbes aren't actually stored as such. They're stored as
8414+ * bitmaps and extents.
8415+ */
8416+
8417+#include <linux/suspend.h>
8418+#include <linux/highmem.h>
8419+#include <linux/bootmem.h>
8420+#include <linux/hardirq.h>
8421+#include <linux/sched.h>
8422+#include <asm/tlbflush.h>
8423+
8424+#include "pageflags.h"
8425+#include "ui.h"
8426+#include "pagedir.h"
8427+
8428+int suspend_protect_pageset2(void)
8429+{
8430+#ifdef CONFIG_DEBUG_PAGEALLOC
8431+ int pfn;
8432+
8433+ BITMAP_FOR_EACH_SET(pageset2_map, pfn) {
8434+ struct page *page = pfn_to_page(pfn);
8435+ if (PageHighMem(page))
8436+ continue;
8437+
8438+ change_page_attr(page, 1, __pgprot(0));
8439+ __flush_tlb_all();
8440+ }
8441+#endif
8442+
8443+ return 0;
8444+}
8445+
8446+void suspend_restore_pageset2_permissions(void)
8447+{
8448+#ifdef CONFIG_DEBUG_PAGEALLOC
8449+ int pfn;
8450+
8451+ BITMAP_FOR_EACH_SET(pageset2_map, pfn) {
8452+ struct page *page = pfn_to_page(pfn);
8453+ if (PageHighMem(page))
8454+ continue;
8455+
8456+ change_page_attr(page, 1, PAGE_KERNEL);
8457+ __flush_tlb_all();
8458+ }
8459+#endif
8460+}
8461+
8462+/*
8463+ * suspend_mark_task_as_pageset1
8464+ * Functionality : Marks all the pages belonging to a given process as
8465+ * pageset 1 pages.
8466+ * Called From : pagedir.c - mark_pages_for_pageset2
8467+ *
8468+ */
8469+extern struct page *suspend2_follow_page(struct mm_struct *mm, unsigned long address);
8470+
8471+static void suspend_mark_task_as_pageset1(struct task_struct *t)
8472+{
8473+ struct vm_area_struct *vma;
8474+ struct mm_struct *mm;
8475+
8476+ mm = t->active_mm;
8477+
8478+ if (!mm || !mm->mmap) return;
8479+
8480+ /* Don't try to take the sem when processes are frozen,
8481+ * drivers are suspended and irqs are disabled. We're
8482+ * not racing with anything anyway. */
8483+ BUG_ON(in_atomic() && !irqs_disabled());
8484+
8485+ if (!irqs_disabled())
8486+ down_read(&mm->mmap_sem);
8487+
8488+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
8489+ if (vma->vm_flags & VM_PFNMAP)
8490+ continue;
8491+ if (vma->vm_start) {
8492+ unsigned long posn;
8493+ for (posn = vma->vm_start; posn < vma->vm_end;
8494+ posn += PAGE_SIZE) {
8495+ struct page *page =
8496+ suspend2_follow_page(mm, posn);
8497+ if (page) {
8498+ ClearPagePageset2(page);
8499+ SetPagePageset1(page);
8500+ }
8501+ }
8502+ }
8503+ }
8504+
8505+ BUG_ON(in_atomic() && !irqs_disabled());
8506+
8507+ if (!irqs_disabled())
8508+ up_read(&mm->mmap_sem);
8509+}
8510+
8511+/*
8512+ * suspend_mark_task_as_pageset2
8513+ * Functionality : Marks all the pages belonging to a given process as
8514+ * pageset 2 pages.
8515+ * Called From :
8516+ *
8517+ */
8518+
8519+static void suspend_mark_task_as_pageset2(struct task_struct *t)
8520+{
8521+ struct vm_area_struct *vma;
8522+ struct mm_struct *mm;
8523+
8524+ mm = t->active_mm;
8525+
8526+ if (!mm || !mm->mmap) return;
8527+
8528+ if (!irqs_disabled())
8529+ down_read(&mm->mmap_sem);
8530+
8531+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
8532+ if (vma->vm_flags & VM_PFNMAP)
8533+ continue;
8534+ if (vma->vm_start) {
8535+ unsigned long posn;
8536+ for (posn = vma->vm_start; posn < vma->vm_end;
8537+ posn += PAGE_SIZE) {
8538+ struct page *page =
8539+ suspend2_follow_page(mm, posn);
8540+ if (page)
8541+ SetPagePageset2(page);
8542+ }
8543+ }
8544+ }
8545+
8546+ if (!irqs_disabled())
8547+ up_read(&mm->mmap_sem);
8548+}
8549+
8550+static void pageset2_full(void)
8551+{
8552+ struct zone *zone;
8553+ unsigned long flags;
8554+
8555+ for_each_zone(zone) {
8556+ spin_lock_irqsave(&zone->lru_lock, flags);
8557+ if (zone->nr_inactive) {
8558+ struct page *page;
8559+ list_for_each_entry(page, &zone->inactive_list, lru)
8560+ SetPagePageset2(page);
8561+ }
8562+ if (zone->nr_active) {
8563+ struct page *page;
8564+ list_for_each_entry(page, &zone->active_list, lru)
8565+ SetPagePageset2(page);
8566+ }
8567+ spin_unlock_irqrestore(&zone->lru_lock, flags);
8568+ }
8569+}
8570+
8571+/* mark_pages_for_pageset2
8572+ *
8573+ * Description: Mark unshared pages in processes not needed for suspend as
8574+ * being able to be written out in a separate pagedir.
8575+ * HighMem pages are simply marked as pageset2. They won't be
8576+ * needed during suspend.
8577+ */
8578+
8579+struct attention_list {
8580+ struct task_struct *task;
8581+ struct attention_list *next;
8582+};
8583+
8584+void suspend_mark_pages_for_pageset2(void)
8585+{
8586+ struct task_struct *p;
8587+ struct attention_list *attention_list = NULL, *last = NULL;
8588+
8589+ BUG_ON(in_atomic() && !irqs_disabled());
8590+
8591+ if (test_action_state(SUSPEND_NO_PAGESET2))
8592+ return;
8593+
8594+ clear_dyn_pageflags(pageset2_map);
8595+
8596+ if (test_action_state(SUSPEND_PAGESET2_FULL))
8597+ pageset2_full();
8598+ else {
8599+ read_lock(&tasklist_lock);
8600+ for_each_process(p) {
8601+ if (!p->mm || (p->flags & PF_BORROWED_MM))
8602+ continue;
8603+
8604+ suspend_mark_task_as_pageset2(p);
8605+ }
8606+ read_unlock(&tasklist_lock);
8607+ }
8608+
8609+ BUG_ON(in_atomic() && !irqs_disabled());
8610+
8611+ /* Now we find all userspace process (with task->mm) marked PF_NOFREEZE
8612+ * and move them into pageset1.
8613+ */
8614+ read_lock(&tasklist_lock);
8615+ for_each_process(p)
8616+ if ((p->flags & PF_NOFREEZE) || p == current) {
8617+ struct attention_list *this = kmalloc(sizeof(struct attention_list), GFP_ATOMIC);
8618+ BUG_ON(!this);
8619+ this->task = p;
8620+ this->next = NULL;
8621+ if (attention_list) {
8622+ last->next = this;
8623+ last = this;
8624+ } else
8625+ attention_list = last = this;
8626+ }
8627+ read_unlock(&tasklist_lock);
8628+
8629+ BUG_ON(in_atomic() && !irqs_disabled());
8630+
8631+ /* Because the tasks in attention_list are ones related to suspending,
8632+ * we know that they won't go away under us.
8633+ */
8634+
8635+ while (attention_list) {
8636+ suspend_mark_task_as_pageset1(attention_list->task);
8637+ last = attention_list;
8638+ attention_list = attention_list->next;
8639+ kfree(last);
8640+ }
8641+
8642+ BUG_ON(in_atomic() && !irqs_disabled());
8643+
8644+}
8645+
8646+/* suspend_get_nonconflicting_page
8647+ *
8648+ * Description: Gets order zero pages that won't be overwritten
8649+ * while copying the original pages.
8650+ */
8651+
8652+unsigned long suspend_get_nonconflicting_page(void)
8653+{
8654+ struct page *page;
8655+
8656+ do {
8657+ page = alloc_pages(GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO, 0);
8658+ BUG_ON(!page);
8659+ } while(PagePageset1(page));
8660+
8661+ return (unsigned long) page_address(page);
8662+}
8663+
8664+/* relocate_page_if_required
8665+ *
8666+ * Description: Given the address of a pointer to a page, we check if the page
8667+ * needs relocating and do so if needs be, adjusting the pointer
8668+ * too.
8669+ */
8670+
8671+void suspend_relocate_if_required(unsigned long *current_value, unsigned int size)
8672+{
8673+ if (PagePageset1(virt_to_page(*current_value))) {
8674+ unsigned long new_page = suspend_get_nonconflicting_page();
8675+ memcpy((char *) new_page, (char *) *current_value, size);
8676+ if (PageSlab(virt_to_page(*current_value)))
8677+ kfree((void *) *current_value);
8678+ else
8679+ free_page((unsigned long) *current_value);
8680+ *current_value = new_page;
8681+ }
8682+}
8683+
8684+/* get_pageset1_load_addresses
8685+ *
8686+ * Description: We check here that pagedir & pages it points to won't collide
8687+ * with pages where we're going to restore from the loaded pages
8688+ * later.
8689+ * Returns: Zero on success, one if couldn't find enough pages (shouldn't
8690+ * happen).
8691+ */
8692+
8693+int suspend_get_pageset1_load_addresses(void)
8694+{
8695+ int i, result = 0;
8696+ void *this;
8697+
8698+ for(i=0; i < pagedir1.size; i++) {
8699+ this = (void *) suspend_get_nonconflicting_page();
8700+ if (!this) {
8701+ abort_suspend("Error: Ran out of memory seeking locations for reloading data.");
8702+ result = 1;
8703+ break;
8704+ }
8705+ SetPagePageset1Copy(virt_to_page(this));
8706+ }
8707+
8708+ return result;
8709+}
8710diff --git a/kernel/power/pagedir.h b/kernel/power/pagedir.h
8711new file mode 100644
8712index 0000000..8350839
8713--- /dev/null
8714+++ b/kernel/power/pagedir.h
8715@@ -0,0 +1,36 @@
8716+/*
8717+ * kernel/power/pagedir.h
8718+ *
8719+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
8720+ * Copyright (C) 2006 Red Hat, inc.
8721+ *
8722+ * This file is released under the GPLv2.
8723+ *
8724+ * Declarations for routines for handling pagesets.
8725+ */
8726+
8727+/* Pagedir
8728+ *
8729+ * Contains the metadata for a set of pages saved in the image.
8730+ */
8731+
8732+struct pagedir {
8733+ int id;
8734+ long size, size_low;
8735+};
8736+
8737+extern struct pagedir pagedir1, pagedir2;
8738+
8739+extern void suspend_copy_pageset1(void);
8740+
8741+extern void suspend_free_extra_pagedir_memory(void);
8742+
8743+extern void suspend_mark_pages_for_pageset2(void);
8744+
8745+extern void suspend_relocate_if_required(unsigned long *current_value, unsigned int size);
8746+extern int suspend_get_pageset1_load_addresses(void);
8747+
8748+extern unsigned long suspend_get_nonconflicting_page(void);
8749+
8750+int suspend_protect_pageset2(void);
8751+void suspend_restore_pageset2_permissions(void);
8752diff --git a/kernel/power/pageflags.c b/kernel/power/pageflags.c
8753new file mode 100644
8754index 0000000..05cdc5e
8755--- /dev/null
8756+++ b/kernel/power/pageflags.c
8757@@ -0,0 +1,169 @@
8758+/*
8759+ * kernel/power/pageflags.c
8760+ *
8761+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
8762+ * Copyright (C) 2006 Red Hat, inc.
8763+ *
8764+ * This file is released under the GPLv2.
8765+ *
8766+ * Routines for serialising and relocating pageflags in which we
8767+ * store our image metadata.
8768+ */
8769+
8770+#include <linux/kernel.h>
8771+#include <linux/mm.h>
8772+#include <linux/module.h>
8773+#include <linux/bitops.h>
8774+#include <linux/list.h>
8775+#include <linux/suspend.h>
8776+#include "pageflags.h"
8777+#include "modules.h"
8778+#include "pagedir.h"
8779+
8780+/* Maps used in copying the image back are in builtin.c */
8781+dyn_pageflags_t pageset1_map;
8782+dyn_pageflags_t pageset1_copy_map;
8783+dyn_pageflags_t pageset2_map;
8784+dyn_pageflags_t pageset2_rw_map;
8785+dyn_pageflags_t in_use_map;
8786+dyn_pageflags_t page_resave_map;
8787+
8788+static int pages_for_zone(struct zone *zone)
8789+{
8790+ return DIV_ROUND_UP(zone->spanned_pages, (PAGE_SIZE << 3));
8791+}
8792+
8793+int suspend_pageflags_space_needed(void)
8794+{
8795+ int total = 0;
8796+ struct zone *zone;
8797+
8798+ for_each_zone(zone)
8799+ if (populated_zone(zone))
8800+ total += sizeof(int) * 2 + pages_for_zone(zone) * PAGE_SIZE;
8801+
8802+ total += sizeof(int);
8803+
8804+ return total;
8805+}
8806+
8807+/* save_dyn_pageflags
8808+ *
8809+ * Description: Save a set of pageflags.
8810+ * Arguments: dyn_pageflags_t *: Pointer to the bitmap being saved.
8811+ */
8812+
8813+void save_dyn_pageflags(dyn_pageflags_t pagemap)
8814+{
8815+ int i, zone_num, size;
8816+ struct zone *zone;
8817+
8818+ if (!*pagemap)
8819+ return;
8820+
8821+ for_each_zone(zone) {
8822+ if (!populated_zone(zone))
8823+ continue;
8824+
8825+ size = pages_for_zone(zone);
8826+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
8827+
8828+ suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
8829+ (char *) &zone_num, sizeof(int));
8830+ suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
8831+ (char *) &size, sizeof(int));
8832+
8833+ for (i = 0; i < size; i++)
8834+ suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
8835+ (char *) pagemap[zone_num][i], PAGE_SIZE);
8836+ }
8837+ zone_num = -1;
8838+ suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
8839+ (char *) &zone_num, sizeof(int));
8840+}
8841+
8842+/* load_dyn_pageflags
8843+ *
8844+ * Description: Load a set of pageflags.
8845+ * Arguments: dyn_pageflags_t *: Pointer to the bitmap being loaded.
8846+ * (It must be allocated before calling this routine).
8847+ */
8848+
8849+void load_dyn_pageflags(dyn_pageflags_t pagemap)
8850+{
8851+ int i, zone_num, zone_check = 0, size;
8852+ struct zone *zone;
8853+
8854+ if (!pagemap)
8855+ return;
8856+
8857+ for_each_zone(zone) {
8858+ if (!populated_zone(zone))
8859+ continue;
8860+
8861+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
8862+
8863+ suspendActiveAllocator->rw_header_chunk(READ, NULL,
8864+ (char *) &zone_check, sizeof(int));
8865+ if (zone_check != zone_num) {
8866+ printk("Zone check (%d) != zone_num (%d).\n",
8867+ zone_check, zone_num);
8868+ BUG();
8869+ }
8870+ suspendActiveAllocator->rw_header_chunk(READ, NULL,
8871+ (char *) &size, sizeof(int));
8872+
8873+ for (i = 0; i < size; i++)
8874+ suspendActiveAllocator->rw_header_chunk(READ, NULL,
8875+ (char *) pagemap[zone_num][i],
8876+ PAGE_SIZE);
8877+ }
8878+ suspendActiveAllocator->rw_header_chunk(READ, NULL, (char *) &zone_check,
8879+ sizeof(int));
8880+ if (zone_check != -1) {
8881+ printk("Didn't read end of dyn pageflag data marker.(%x)\n",
8882+ zone_check);
8883+ BUG();
8884+ }
8885+}
8886+
8887+/* relocate_dyn_pageflags
8888+ *
8889+ * Description: Relocate a set of pageflags to ensure they don't collide with
8890+ * pageset 1 data which will get overwritten on copyback.
8891+ * Arguments: dyn_pageflags_t *: Pointer to the bitmap being relocated.
8892+ */
8893+
8894+void relocate_dyn_pageflags(dyn_pageflags_t *pagemap)
8895+{
8896+ int i, zone_num;
8897+ struct zone *zone;
8898+
8899+ if (!*pagemap)
8900+ return;
8901+
8902+ suspend_relocate_if_required((unsigned long *) pagemap,
8903+ (unsigned int) (sizeof(void *) * (1 << ZONETABLE_SHIFT)));
8904+ BUG_ON(PagePageset1(virt_to_page(*pagemap)));
8905+
8906+ for_each_zone(zone) {
8907+ int pages = pages_for_zone(zone);
8908+
8909+ if (!populated_zone(zone))
8910+ continue;
8911+
8912+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
8913+
8914+ suspend_relocate_if_required((void *) &((*pagemap)[zone_num]),
8915+ sizeof(void *) * pages);
8916+ BUG_ON(PagePageset1(virt_to_page((*pagemap)[zone_num])));
8917+
8918+ for (i = 0; i < pages; i++) {
8919+ suspend_relocate_if_required(
8920+ (void *) &((*pagemap)[zone_num][i]),
8921+ PAGE_SIZE);
8922+ BUG_ON(PagePageset1(virt_to_page(
8923+ (*pagemap)[zone_num][i])));
8924+ }
8925+ }
8926+}
8927diff --git a/kernel/power/pageflags.h b/kernel/power/pageflags.h
8928new file mode 100644
8929index 0000000..ade260d
8930--- /dev/null
8931+++ b/kernel/power/pageflags.h
8932@@ -0,0 +1,63 @@
8933+/*
8934+ * kernel/power/pageflags.h
8935+ *
8936+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
8937+ * Copyright (C) 2006 Red Hat, inc.
8938+ *
8939+ * This file is released under the GPLv2.
8940+ *
8941+ * Suspend2 needs a few pageflags while working that aren't otherwise
8942+ * used. To save the struct page pageflags, we dynamically allocate
8943+ * a bitmap and use that. These are the only non order-0 allocations
8944+ * we do.
8945+ *
8946+ * NOTE!!!
8947+ * We assume that PAGE_SIZE - sizeof(void *) is a multiple of
8948+ * sizeof(unsigned long). Is this ever false?
8949+ */
8950+
8951+#include <linux/dyn_pageflags.h>
8952+#include <linux/suspend.h>
8953+
8954+extern dyn_pageflags_t in_use_map;
8955+extern dyn_pageflags_t pageset2_map;
8956+extern dyn_pageflags_t pageset2_rw_map;
8957+extern dyn_pageflags_t page_resave_map;
8958+
8959+/*
8960+ * inusemap is used in two ways:
8961+ * - During suspend, to tag pages which are not used (to speed up
8962+ * count_data_pages);
8963+ * - During resume, to tag pages which are in pagedir1. This does not tag
8964+ * pagedir2 pages, so !== first use.
8965+ */
8966+
8967+#define PageInUse(page) (test_dynpageflag(&in_use_map, page))
8968+#define SetPageInUse(page) (set_dynpageflag(&in_use_map, page))
8969+#define ClearPageInUse(page) (clear_dynpageflag(&in_use_map, page))
8970+
8971+#define PagePageset1(page) (test_dynpageflag(&pageset1_map, page))
8972+#define SetPagePageset1(page) (set_dynpageflag(&pageset1_map, page))
8973+#define ClearPagePageset1(page) (clear_dynpageflag(&pageset1_map, page))
8974+
8975+#define PagePageset1Copy(page) (test_dynpageflag(&pageset1_copy_map, page))
8976+#define SetPagePageset1Copy(page) (set_dynpageflag(&pageset1_copy_map, page))
8977+#define ClearPagePageset1Copy(page) (clear_dynpageflag(&pageset1_copy_map, page))
8978+
8979+#define PagePageset2(page) (test_dynpageflag(&pageset2_map, page))
8980+#define SetPagePageset2(page) (set_dynpageflag(&pageset2_map, page))
8981+#define ClearPagePageset2(page) (clear_dynpageflag(&pageset2_map, page))
8982+
8983+#define PageWasRW(page) (test_dynpageflag(&pageset2_map, page))
8984+#define SetPageWasRW(page) (set_dynpageflag(&pageset2_map, page))
8985+#define ClearPageWasRW(page) (clear_dynpageflag(&pageset2_map, page))
8986+
8987+#define PageResave(page) (page_resave_map ? test_dynpageflag(&page_resave_map, page) : 0)
8988+#define SetPageResave(page) (set_dynpageflag(&page_resave_map, page))
8989+#define ClearPageResave(page) (clear_dynpageflag(&page_resave_map, page))
8990+
8991+extern void save_dyn_pageflags(dyn_pageflags_t pagemap);
8992+extern void save_dyn_pageflags(dyn_pageflags_t pagemap);
8993+extern void load_dyn_pageflags(dyn_pageflags_t pagemap);
8994+extern void relocate_dyn_pageflags(dyn_pageflags_t *pagemap);
8995+extern int suspend_pageflags_space_needed(void);
8996diff --git a/kernel/power/power.h b/kernel/power/power.h
8997index bfe999f..6bd3a2e 100644
8998--- a/kernel/power/power.h
8999+++ b/kernel/power/power.h
9000@@ -1,5 +1,11 @@
9001+/*
9002+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
9003+ * Copyright (C) 2006 Red Hat, inc.
9004+ */
9005+
9006 #include <linux/suspend.h>
9007 #include <linux/utsname.h>
9008+#include "suspend.h"
9009
9010 struct swsusp_info {
9011 struct new_utsname uts;
9012@@ -19,7 +25,15 @@ extern int pm_suspend_disk(void);
9013 #else
9014 static inline int pm_suspend_disk(void)
9015 {
9016+#ifdef CONFIG_SUSPEND2
9017+ if (suspend_start_anything(1))
9018+ return -EBUSY;
9019+ suspend_main(1);
9020+ suspend_finish_anything(1);
9021+ return 0;
9022+#else
9023 return -EPERM;
9024+#endif
9025 }
9026 #endif
9027 extern struct semaphore pm_sem;
9028@@ -38,6 +52,8 @@ extern struct subsystem power_subsys;
9029 /* References to section boundaries */
9030 extern const void __nosave_begin, __nosave_end;
9031
9032+extern struct pbe *restore_pblist;
9033+
9034 /* Preferred image size in bytes (default 500 MB) */
9035 extern unsigned long image_size;
9036 extern int in_suspend;
9037@@ -153,3 +169,4 @@ extern int swsusp_read(void);
9038 extern int swsusp_write(void);
9039 extern void swsusp_close(void);
9040 extern int suspend_enter(suspend_state_t state);
9041+extern struct page *saveable_page(unsigned long pfn);
9042diff --git a/kernel/power/power_off.c b/kernel/power/power_off.c
9043new file mode 100644
9044index 0000000..c1da456
9045--- /dev/null
9046+++ b/kernel/power/power_off.c
9047@@ -0,0 +1,87 @@
9048+/*
9049+ * kernel/power/power_off.c
9050+ *
9051+ * Copyright (C) 2006 Nigel Cunningham <nigel@suspend2.net>
9052+ * Copyright (C) 2006 Red Hat, inc.
9053+ *
9054+ * This file is released under the GPLv2.
9055+ *
9056+ * Support for powering down.
9057+ */
9058+
9059+#include <linux/device.h>
9060+#include <linux/suspend.h>
9061+#include <linux/mm.h>
9062+#include <linux/pm.h>
9063+#include <linux/reboot.h>
9064+#include "suspend.h"
9065+#include "ui.h"
9066+
9067+unsigned long suspend_powerdown_method = 0; /* 0 - Kernel power off */
9068+
9069+extern struct pm_ops *pm_ops;
9070+
9071+/* Use suspend_enter from main.c */
9072+extern int suspend_enter(suspend_state_t state);
9073+
9074+int try_pm_state_powerdown(void)
9075+{
9076+ if (pm_ops && pm_ops->prepare && suspend_powerdown_method &&
9077+ pm_ops->prepare(suspend_powerdown_method))
9078+ return 0;
9079+
9080+ if (suspend_powerdown_method > 3)
9081+ kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
9082+ else {
9083+ if (device_suspend(PMSG_SUSPEND)) {
9084+ printk(KERN_ERR "Some devices failed to suspend\n");
9085+ return 0;
9086+ }
9087+ }
9088+
9089+ mdelay(1000); /* Give time for devices to power down */
9090+
9091+ if (suspend_enter(suspend_powerdown_method))
9092+ return 0;
9093+
9094+ device_resume();
9095+
9096+ if (pm_ops && pm_ops->finish && suspend_powerdown_method)
9097+ pm_ops->finish(suspend_powerdown_method);
9098+
9099+ return 1;
9100+}
9101+
9102+/*
9103+ * suspend_power_down
9104+ * Functionality : Powers down or reboots the computer once the image
9105+ * has been written to disk.
9106+ * Key Assumptions : Able to reboot/power down via code called or that
9107+ * the warning emitted if the calls fail will be visible
9108+ * to the user (ie printk resumes devices).
9109+ * Called From : do_suspend2_suspend_2
9110+ */
9111+
9112+void suspend_power_down(void)
9113+{
9114+ if (test_action_state(SUSPEND_REBOOT)) {
9115+ suspend_prepare_status(DONT_CLEAR_BAR, "Ready to reboot.");
9116+ kernel_restart(NULL);
9117+ }
9118+
9119+ suspend_prepare_status(DONT_CLEAR_BAR, "Powering down.");
9120+
9121+ if (pm_ops && pm_ops->enter && suspend_powerdown_method && try_pm_state_powerdown())
9122+ return;
9123+
9124+ kernel_shutdown_prepare(SYSTEM_POWER_OFF);
9125+
9126+ mdelay(1000); /* Give time for devices to power down */
9127+
9128+ machine_power_off();
9129+ machine_halt();
9130+ suspend_prepare_status(DONT_CLEAR_BAR, "Powerdown failed");
9131+ while (1)
9132+ cpu_relax();
9133+}
9134+
9135diff --git a/kernel/power/power_off.h b/kernel/power/power_off.h
9136new file mode 100644
9137index 0000000..f71a201
9138--- /dev/null
9139+++ b/kernel/power/power_off.h
9140@@ -0,0 +1,14 @@
9141+/*
9142+ * kernel/power/power_off.h
9143+ *
9144+ * Copyright (C) 2006 Nigel Cunningham <nigel@suspend2.net>
9145+ * Copyright (C) 2006 Red Hat, inc.
9146+ *
9147+ * This file is released under the GPLv2.
9148+ *
9149+ * Support for the powering down.
9150+ */
9151+
9152+int suspend_pm_state_finish(void);
9153+void suspend_power_down(void);
9154+extern unsigned long suspend_powerdown_method;
9155diff --git a/kernel/power/prepare_image.c b/kernel/power/prepare_image.c
9156new file mode 100644
9157index 0000000..cd1c14d
9158--- /dev/null
9159+++ b/kernel/power/prepare_image.c
9160@@ -0,0 +1,745 @@
9161+/*
9162+ * kernel/power/prepare_image.c
9163+ *
9164+ * Copyright (C) 2003-2006 Nigel Cunningham <nigel@suspend.net>
9165+ * Copyright (C) 2006 Red Hat, inc.
9166+ *
9167+ * This file is released under the GPLv2.
9168+ *
9169+ * We need to eat memory until we can:
9170+ * 1. Perform the save without changing anything (RAM_NEEDED < max_pfn)
9171+ * 2. Fit it all in available space (suspendActiveAllocator->available_space() >=
9172+ * storage_needed())
9173+ * 3. Reload the pagedir and pageset1 to places that don't collide with their
9174+ * final destinations, not knowing to what extent the resumed kernel will
9175+ * overlap with the one loaded at boot time. I think the resumed kernel
9176+ * should overlap completely, but I don't want to rely on this as it is
9177+ * an unproven assumption. We therefore assume there will be no overlap at
9178+ * all (worse case).
9179+ * 4. Meet the user's requested limit (if any) on the size of the image.
9180+ * The limit is in MB, so pages/256 (assuming 4K pages).
9181+ *
9182+ */
9183+
9184+#include <linux/highmem.h>
9185+#include <linux/freezer.h>
9186+#include <linux/hardirq.h>
9187+
9188+#include "power.h"
9189+#include "pageflags.h"
9190+#include "modules.h"
9191+#include "io.h"
9192+#include "ui.h"
9193+#include "extent.h"
9194+#include "prepare_image.h"
9195+#include "block_io.h"
9196+#include "suspend.h"
9197+#include "checksum.h"
9198+
9199+static int are_frozen = 0, num_nosave = 0;
9200+static int header_space_allocated = 0;
9201+static int storage_allocated = 0;
9202+static int storage_available = 0;
9203+int extra_pd1_pages_allowance = MIN_EXTRA_PAGES_ALLOWANCE;
9204+
9205+static int extra_pages_allocated;
9206+
9207+struct extras {
9208+ struct page *page;
9209+ int order;
9210+ struct extras *next;
9211+};
9212+
9213+static struct extras *extras_list;
9214+
9215+/*
9216+ * num_pcp_pages: Count pcp pages.
9217+ */
9218+static int num_pcp_pages(void)
9219+{
9220+ struct zone *zone;
9221+ int result = 0, i = 0, cpu;
9222+ struct per_cpu_pageset *pset;
9223+
9224+ /* PCP lists */
9225+ for_each_zone(zone) {
9226+ if (!zone->present_pages)
9227+ continue;
9228+
9229+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
9230+ if (!cpu_possible(cpu))
9231+ continue;
9232+
9233+ pset = zone_pcp(zone, cpu);
9234+
9235+ for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
9236+ struct per_cpu_pages *pcp;
9237+
9238+ pcp = &(pset->pcp[i]);
9239+ result += pcp->count;
9240+ }
9241+ }
9242+ }
9243+ return result;
9244+}
9245+
9246+/*
9247+ * Number of free pages, including pcp pages.
9248+ */
9249+int real_nr_free_pages(void)
9250+{
9251+ return nr_free_pages() + num_pcp_pages();
9252+}
9253+
9254+/*
9255+ * Discover how much extra memory will be required by the drivers
9256+ * when they're asked to suspend. We can then ensure that amount
9257+ * of memory is available when we really want it.
9258+ */
9259+static void get_extra_pd1_allowance(void)
9260+{
9261+ int orig_num_free = real_nr_free_pages(), final;
9262+
9263+ suspend_prepare_status(CLEAR_BAR, "Finding allowance for drivers.");
9264+ device_suspend(PMSG_FREEZE);
9265+ local_irq_disable(); /* irqs might have been re-enabled on us */
9266+ device_power_down(PMSG_FREEZE);
9267+
9268+ final = real_nr_free_pages();
9269+
9270+ device_power_up();
9271+ local_irq_enable();
9272+
9273+ device_resume();
9274+
9275+ extra_pd1_pages_allowance = max(
9276+ orig_num_free - final + MIN_EXTRA_PAGES_ALLOWANCE,
9277+ MIN_EXTRA_PAGES_ALLOWANCE);
9278+}
9279+
9280+/* suspend_free_extra_pagedir_memory
9281+ *
9282+ * Description: Free previously allocated extra pagedir memory.
9283+ */
9284+void suspend_free_extra_pagedir_memory(void)
9285+{
9286+ /* Free allocated pages */
9287+ while (extras_list) {
9288+ struct extras *this = extras_list;
9289+ int i;
9290+
9291+ extras_list = this->next;
9292+
9293+ for (i = 0; i < (1 << this->order); i++)
9294+ ClearPageNosave(this->page + i);
9295+
9296+ __free_pages(this->page, this->order);
9297+ kfree(this);
9298+ }
9299+
9300+ extra_pages_allocated = 0;
9301+}
9302+
9303+/* suspend_allocate_extra_pagedir_memory
9304+ *
9305+ * Description: Allocate memory for making the atomic copy of pagedir1 in the
9306+ * case where it is bigger than pagedir2.
9307+ * Arguments: int num_to_alloc: Number of extra pages needed.
9308+ * Result: int. Zero on success. One if unable to allocate enough memory.
9309+ */
9310+static int suspend_allocate_extra_pagedir_memory(int extra_pages_needed)
9311+{
9312+ int j, order, num_to_alloc = extra_pages_needed - extra_pages_allocated;
9313+
9314+ if (num_to_alloc < 1)
9315+ return 0;
9316+
9317+ order = fls(num_to_alloc);
9318+ if (order >= MAX_ORDER)
9319+ order = MAX_ORDER - 1;
9320+
9321+ while (num_to_alloc) {
9322+ struct page *newpage;
9323+ unsigned long virt;
9324+ struct extras *extras_entry;
9325+
9326+ while ((1 << order) > num_to_alloc)
9327+ order--;
9328+
9329+ virt = __get_free_pages(GFP_ATOMIC | __GFP_NOWARN, order);
9330+ while (!virt && order) {
9331+ order--;
9332+ virt = __get_free_pages(GFP_ATOMIC | __GFP_NOWARN, order);
9333+ }
9334+
9335+ if (!virt)
9336+ return 1;
9337+
9338+ newpage = virt_to_page(virt);
9339+
9340+ extras_entry = (struct extras *) kmalloc(sizeof(struct extras),
9341+ GFP_ATOMIC);
9342+
9343+ if (!extras_entry) {
9344+ __free_pages(newpage, order);
9345+ return 1;
9346+ }
9347+
9348+ extras_entry->page = newpage;
9349+ extras_entry->order = order;
9350+ extras_entry->next = NULL;
9351+
9352+ if (extras_list)
9353+ extras_entry->next = extras_list;
9354+
9355+ extras_list = extras_entry;
9356+
9357+ for (j = 0; j < (1 << order); j++) {
9358+ SetPageNosave(newpage + j);
9359+ SetPagePageset1Copy(newpage + j);
9360+ }
9361+
9362+ extra_pages_allocated += (1 << order);
9363+ num_to_alloc -= (1 << order);
9364+ }
9365+
9366+ return 0;
9367+}
9368+
9369+/*
9370+ * Amount of storage needed, possibly taking into account the
9371+ * expected compression ratio and possibly also ignoring our
9372+ * allowance for extra pages.
9373+ */
9374+static int main_storage_needed(int use_ecr,
9375+ int ignore_extra_pd1_allow)
9376+{
9377+ return ((pagedir1.size + pagedir2.size +
9378+ (ignore_extra_pd1_allow ? 0 : extra_pd1_pages_allowance)) *
9379+ (use_ecr ? suspend_expected_compression_ratio() : 100) / 100);
9380+}
9381+
9382+/*
9383+ * Storage needed for the image header, in bytes until the return.
9384+ */
9385+static int header_storage_needed(void)
9386+{
9387+ int bytes = (int) sizeof(struct suspend_header) +
9388+ suspend_header_storage_for_modules() +
9389+ suspend_pageflags_space_needed();
9390+
9391+ return DIV_ROUND_UP(bytes, PAGE_SIZE);
9392+}
9393+
9394+static void display_stats(int always, int sub_extra_pd1_allow)
9395+{
9396+ char buffer[255];
9397+ snprintf(buffer, 254,
9398+ "Free:%d(%d). Sets:%ld(%ld),%ld(%ld). Header:%d. "
9399+ "Nosave:%d-%d=%d. Storage:%u/%u(%u). Needed:%d|%d|%d.\n",
9400+
9401+ /* Free */
9402+ nr_free_pages(), nr_free_pages() - nr_free_highpages(),
9403+
9404+ /* Sets */
9405+ pagedir1.size, pagedir1.size_low,
9406+ pagedir2.size, pagedir2.size_low,
9407+
9408+ /* Header */
9409+ header_storage_needed(),
9410+
9411+ /* Nosave */
9412+ num_nosave, extra_pages_allocated,
9413+ num_nosave - extra_pages_allocated,
9414+
9415+ /* Storage - converted to pages for comparison */
9416+ storage_allocated,
9417+ storage_needed(1, sub_extra_pd1_allow),
9418+ storage_available,
9419+
9420+ /* Needed */
9421+ ram_to_suspend() - nr_free_pages() + nr_free_highpages(),
9422+ storage_needed(1, sub_extra_pd1_allow) - storage_available,
9423+ (image_size_limit > 0) ? (storage_needed(1, sub_extra_pd1_allow) - (image_size_limit << 8)) : 0);
9424+
9425+ if (always)
9426+ printk(buffer);
9427+ else
9428+ suspend_message(SUSPEND_EAT_MEMORY, SUSPEND_MEDIUM, 1, buffer);
9429+}
9430+
9431+/* generate_free_page_map
9432+ *
9433+ * Description: This routine generates a bitmap of free pages from the
9434+ * lists used by the memory manager. We then use the bitmap
9435+ * to quickly calculate which pages to save and in which
9436+ * pagesets.
9437+ */
9438+static void generate_free_page_map(void)
9439+{
9440+ int order, loop, cpu;
9441+ struct page *page;
9442+ unsigned long flags, i;
9443+ struct zone *zone;
9444+ struct per_cpu_pageset *pset;
9445+
9446+ for_each_zone(zone) {
9447+ if (!zone->present_pages)
9448+ continue;
9449+
9450+ spin_lock_irqsave(&zone->lock, flags);
9451+
9452+ for(i=0; i < zone->spanned_pages; i++)
9453+ ClearPageNosaveFree(pfn_to_page(zone->zone_start_pfn + i));
9454+
9455+ for (order = MAX_ORDER - 1; order >= 0; --order)
9456+ list_for_each_entry(page, &zone->free_area[order].free_list, lru)
9457+ for(loop=0; loop < (1 << order); loop++)
9458+ SetPageNosaveFree(page+loop);
9459+
9460+
9461+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
9462+ if (!cpu_possible(cpu))
9463+ continue;
9464+
9465+ pset = zone_pcp(zone, cpu);
9466+
9467+ for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
9468+ struct per_cpu_pages *pcp;
9469+ struct page *page;
9470+
9471+ pcp = &pset->pcp[i];
9472+ list_for_each_entry(page, &pcp->list, lru)
9473+ SetPageNosaveFree(page);
9474+ }
9475+ }
9476+
9477+ spin_unlock_irqrestore(&zone->lock, flags);
9478+ }
9479+}
9480+
9481+/* size_of_free_region
9482+ *
9483+ * Description: Return the number of pages that are free, beginning with and
9484+ * including this one.
9485+ */
9486+static int size_of_free_region(struct page *page)
9487+{
9488+ struct zone *zone = page_zone(page);
9489+ struct page *posn = page, *last_in_zone =
9490+ pfn_to_page(zone->zone_start_pfn) + zone->spanned_pages - 1;
9491+
9492+ while (posn <= last_in_zone && PageNosaveFree(posn)) {
9493+ BUG_ON(PagePageset2(posn));
9494+ posn++;
9495+ }
9496+ return (posn - page);
9497+}
9498+
9499+/* flag_image_pages
9500+ *
9501+ * This routine generates our lists of pages to be stored in each
9502+ * pageset. Since we store the data using extents, and adding new
9503+ * extents might allocate a new extent page, this routine may well
9504+ * be called more than once.
9505+ */
9506+static void flag_image_pages(void)
9507+{
9508+ int num_free = 0;
9509+ unsigned long loop;
9510+ struct zone *zone;
9511+
9512+ pagedir1.size = 0;
9513+ pagedir1.size_low = 0;
9514+ pagedir2.size = 0;
9515+ pagedir2.size_low = 0;
9516+
9517+ num_nosave = 0;
9518+
9519+ clear_dyn_pageflags(pageset1_map);
9520+
9521+ generate_free_page_map();
9522+
9523+ /*
9524+ * Pages not to be saved are marked Nosave irrespective of being reserved
9525+ */
9526+ for_each_zone(zone) {
9527+ if (!populated_zone(zone))
9528+ continue;
9529+
9530+ for (loop = 0; loop < zone->spanned_pages; loop++) {
9531+ unsigned long pfn = zone->zone_start_pfn + loop;
9532+ struct page *page;
9533+ int chunk_size;
9534+
9535+ if (!pfn_valid(pfn))
9536+ continue;
9537+
9538+ page = pfn_to_page(pfn);
9539+
9540+ chunk_size = size_of_free_region(page);
9541+ if (chunk_size) {
9542+ num_free += chunk_size;
9543+ loop += chunk_size - 1;
9544+ continue;
9545+ }
9546+
9547+ page = saveable_page(pfn);
9548+
9549+ if (!page) {
9550+ num_nosave++;
9551+ continue;
9552+ }
9553+
9554+ if (PagePageset2(page)) {
9555+ pagedir2.size++;
9556+ if (!PageHighMem(page)) {
9557+ pagedir2.size_low++;
9558+ SetPagePageset1Copy(page);
9559+ }
9560+ if (PageResave(page)) {
9561+ SetPagePageset1(page);
9562+ pagedir1.size++;
9563+ if (!PageHighMem(page))
9564+ pagedir1.size_low++;
9565+ }
9566+ } else {
9567+ pagedir1.size++;
9568+ SetPagePageset1(page);
9569+ if (!PageHighMem(page))
9570+ pagedir1.size_low++;
9571+ }
9572+ }
9573+ }
9574+
9575+ suspend_message(SUSPEND_EAT_MEMORY, SUSPEND_MEDIUM, 0,
9576+ "Count data pages: Set1 (%d) + Set2 (%d) + Nosave (%d) + "
9577+ "NumFree (%d) = %d.\n",
9578+ pagedir1.size, pagedir2.size, num_nosave, num_free,
9579+ pagedir1.size + pagedir2.size + num_nosave + num_free);
9580+}
9581+
9582+/* amount_needed
9583+ *
9584+ * Calculates the amount by which the image size needs to be reduced to meet
9585+ * our constraints.
9586+ */
9587+static int amount_needed(int use_image_size_limit)
9588+{
9589+ int max1 = max(ram_to_suspend() - real_nr_free_pages() +
9590+ (int) nr_free_highpages(),
9591+ storage_needed(1, 0) - storage_available);
9592+
9593+ if (!use_image_size_limit || image_size_limit < 1)
9594+ return max1;
9595+
9596+ return max(max1, storage_needed(1, 0) - (image_size_limit << 8));
9597+}
9598+
9599+void suspend_recalculate_image_contents(int atomic_copy)
9600+{
9601+ clear_dyn_pageflags(pageset1_map);
9602+ if (!atomic_copy) {
9603+ int pfn;
9604+ BITMAP_FOR_EACH_SET(pageset2_map, pfn)
9605+ ClearPagePageset1Copy(pfn_to_page(pfn));
9606+ /* Need to call this before getting pageset1_size! */
9607+ suspend_mark_pages_for_pageset2();
9608+ }
9609+ BUG_ON(in_atomic() && !irqs_disabled());
9610+ flag_image_pages();
9611+
9612+ if (!atomic_copy) {
9613+ storage_available = suspendActiveAllocator->storage_available();
9614+ display_stats(1, 0);
9615+ }
9616+ BUG_ON(in_atomic() && !irqs_disabled());
9617+ return;
9618+}
9619+
9620+/* update_image
9621+ *
9622+ * Allocate [more] memory and storage for the image.
9623+ */
9624+static int update_image(void)
9625+{
9626+ int result2, param_used;
9627+
9628+ suspend_recalculate_image_contents(0);
9629+
9630+ /* Include allowance for growth in pagedir1 while writing pagedir 2 */
9631+ if (suspend_allocate_extra_pagedir_memory(pagedir1.size +
9632+ extra_pd1_pages_allowance - pagedir2.size_low)) {
9633+ suspend_message(SUSPEND_EAT_MEMORY, SUSPEND_LOW, 1,
9634+ "Still need to get more pages for pagedir 1.\n");
9635+ return 1;
9636+ }
9637+
9638+ thaw_kernel_threads();
9639+
9640+ param_used = main_storage_needed(1, 0);
9641+ if ((result2 = suspendActiveAllocator->allocate_storage(param_used))) {
9642+ suspend_message(SUSPEND_EAT_MEMORY, SUSPEND_LOW, 1,
9643+ "Allocate storage returned %d. Still need to get more"
9644+ " storage space for the image proper.\n",
9645+ result2);
9646+ storage_allocated = suspendActiveAllocator->storage_allocated();
9647+ if (freeze_processes()) {
9648+ set_result_state(SUSPEND_FREEZING_FAILED);
9649+ set_result_state(SUSPEND_ABORTED);
9650+ }
9651+ return 1;
9652+ }
9653+
9654+ /*
9655+ * Allocate remaining storage space, if possible, up to the
9656+ * maximum we know we'll need. It's okay to allocate the
9657+ * maximum if the writer is the swapwriter, but
9658+ * we don't want to grab all available space on an NFS share.
9659+ * We therefore ignore the expected compression ratio here,
9660+ * thereby trying to allocate the maximum image size we could
9661+ * need (assuming compression doesn't expand the image), but
9662+ * don't complain if we can't get the full amount we're after.
9663+ */
9664+
9665+ suspendActiveAllocator->allocate_storage(
9666+ min(storage_available, main_storage_needed(0, 1)));
9667+
9668+ storage_allocated = suspendActiveAllocator->storage_allocated();
9669+
9670+ /* Allocate the header storage after allocating main storage
9671+ * so that the overhead for metadata doesn't change the amount
9672+ * of storage needed for the header itself.
9673+ */
9674+
9675+ param_used = header_storage_needed();
9676+
9677+ result2 = suspendActiveAllocator->allocate_header_space(param_used);
9678+
9679+ if (freeze_processes()) {
9680+ set_result_state(SUSPEND_FREEZING_FAILED);
9681+ set_result_state(SUSPEND_ABORTED);
9682+ }
9683+
9684+ if (result2) {
9685+ suspend_message(SUSPEND_EAT_MEMORY, SUSPEND_LOW, 1,
9686+ "Still need to get more storage space for header.\n");
9687+ return 1;
9688+ }
9689+
9690+ header_space_allocated = param_used;
9691+
9692+ allocate_checksum_pages();
9693+
9694+ suspend_recalculate_image_contents(0);
9695+
9696+ suspend_message(SUSPEND_EAT_MEMORY, SUSPEND_LOW, 1,
9697+ "Amount still needed (%d) > 0:%d. Header: %d < %d: %d,"
9698+ " Storage allocd: %d < %d + %d: %d.\n",
9699+ amount_needed(0),
9700+ (amount_needed(0) > 0),
9701+ header_space_allocated, header_storage_needed(),
9702+ header_space_allocated < header_storage_needed(),
9703+ storage_allocated,
9704+ header_storage_needed(), main_storage_needed(1, 1),
9705+ storage_allocated <
9706+ (header_storage_needed() + main_storage_needed(1, 1)));
9707+
9708+ suspend_cond_pause(0, NULL);
9709+
9710+ return ((amount_needed(0) > 0) ||
9711+ header_space_allocated < header_storage_needed() ||
9712+ storage_allocated <
9713+ (header_storage_needed() + main_storage_needed(1, 1)));
9714+}
9715+
9716+/* attempt_to_freeze
9717+ *
9718+ * Try to freeze processes.
9719+ */
9720+
9721+static int attempt_to_freeze(void)
9722+{
9723+ int result;
9724+
9725+ /* Stop processes before checking again */
9726+ thaw_processes();
9727+ suspend_prepare_status(CLEAR_BAR, "Freezing processes");
9728+ result = freeze_processes();
9729+
9730+ if (result) {
9731+ set_result_state(SUSPEND_ABORTED);
9732+ set_result_state(SUSPEND_FREEZING_FAILED);
9733+ } else
9734+ are_frozen = 1;
9735+
9736+ return result;
9737+}
9738+
9739+int storage_needed(int use_ecr, int ignore_extra_pd1_allow)
9740+{
9741+ return (main_storage_needed(use_ecr, ignore_extra_pd1_allow)
9742+ + header_storage_needed());
9743+}
9744+
9745+int ram_to_suspend(void)
9746+{
9747+ return (1 + max_t(int, (pagedir1.size + extra_pd1_pages_allowance -
9748+ pagedir2.size_low - extra_pages_allocated) / 2, 0) +
9749+ MIN_FREE_RAM + suspend_memory_for_modules());
9750+}
9751+
9752+/* eat_memory
9753+ *
9754+ * Try to free some memory, either to meet hard or soft constraints on the image
9755+ * characteristics.
9756+ *
9757+ * Hard constraints:
9758+ * - Pageset1 must be < half of memory;
9759+ * - We must have enough memory free at resume time to have pageset1
9760+ * be able to be loaded in pages that don't conflict with where it has to
9761+ * be restored.
9762+ * Soft constraints
9763+ * - User specificied image size limit.
9764+ */
9765+static int eat_memory(void)
9766+{
9767+ int amount_wanted = 0;
9768+ int free_flags = 0, did_eat_memory = 0;
9769+
9770+ /*
9771+ * Note that if we have enough storage space and enough free memory, we
9772+ * may exit without eating anything. We give up when the last 10
9773+ * iterations ate no extra pages because we're not going to get much
9774+ * more anyway, but the few pages we get will take a lot of time.
9775+ *
9776+ * We freeze processes before beginning, and then unfreeze them if we
9777+ * need to eat memory until we think we have enough. If our attempts
9778+ * to freeze fail, we give up and abort.
9779+ */
9780+
9781+ suspend_recalculate_image_contents(0);
9782+ amount_wanted = amount_needed(1);
9783+
9784+ thaw_kernel_threads();
9785+
9786+ switch (image_size_limit) {
9787+ case -1: /* Don't eat any memory */
9788+ if (amount_wanted > 0) {
9789+ set_result_state(SUSPEND_ABORTED);
9790+ set_result_state(SUSPEND_WOULD_EAT_MEMORY);
9791+ }
9792+ break;
9793+ case -2: /* Free caches only */
9794+ drop_pagecache();
9795+ suspend_recalculate_image_contents(0);
9796+ amount_wanted = amount_needed(1);
9797+ did_eat_memory = 1;
9798+ break;
9799+ default:
9800+ free_flags = GFP_ATOMIC | __GFP_HIGHMEM;
9801+ }
9802+
9803+ if (amount_wanted > 0 && !test_result_state(SUSPEND_ABORTED) &&
9804+ image_size_limit != -1) {
9805+
9806+ suspend_prepare_status(CLEAR_BAR, "Seeking to free %dMB of memory.", MB(amount_wanted));
9807+
9808+ shrink_all_memory(amount_wanted);
9809+ suspend_recalculate_image_contents(0);
9810+
9811+ did_eat_memory = 1;
9812+
9813+ suspend_cond_pause(0, NULL);
9814+ }
9815+
9816+ if (freeze_processes()) {
9817+ set_result_state(SUSPEND_FREEZING_FAILED);
9818+ set_result_state(SUSPEND_ABORTED);
9819+ }
9820+
9821+ if (did_eat_memory) {
9822+ unsigned long orig_state = get_suspend_state();
9823+ /* Freeze_processes will call sys_sync too */
9824+ restore_suspend_state(orig_state);
9825+ suspend_recalculate_image_contents(0);
9826+ }
9827+
9828+ /* Blank out image size display */
9829+ suspend_update_status(100, 100, NULL);
9830+
9831+ if (!test_result_state(SUSPEND_ABORTED) &&
9832+ (amount_needed(0) - extra_pd1_pages_allowance > 0)) {
9833+ printk("Unable to free sufficient memory to suspend. Still need %d pages.\n",
9834+ amount_needed(1));
9835+ display_stats(1, 1);
9836+ set_result_state(SUSPEND_ABORTED);
9837+ set_result_state(SUSPEND_UNABLE_TO_FREE_ENOUGH_MEMORY);
9838+ }
9839+
9840+ return 0;
9841+}
9842+
9843+/* suspend_prepare_image
9844+ *
9845+ * Entry point to the whole image preparation section.
9846+ *
9847+ * We do four things:
9848+ * - Freeze processes;
9849+ * - Ensure image size constraints are met;
9850+ * - Complete all the preparation for saving the image,
9851+ * including allocation of storage. The only memory
9852+ * that should be needed when we're finished is that
9853+ * for actually storing the image (and we know how
9854+ * much is needed for that because the modules tell
9855+ * us).
9856+ * - Make sure that all dirty buffers are written out.
9857+ */
9858+#define MAX_TRIES 4
9859+int suspend_prepare_image(void)
9860+{
9861+ int result = 1, tries = 0;
9862+
9863+ are_frozen = 0;
9864+
9865+ header_space_allocated = 0;
9866+
9867+ if (attempt_to_freeze())
9868+ return 1;
9869+
9870+ if (!extra_pd1_pages_allowance)
9871+ get_extra_pd1_allowance();
9872+
9873+ storage_available = suspendActiveAllocator->storage_available();
9874+
9875+ if (!storage_available) {
9876+ printk(KERN_ERR "You need some storage available to be able to suspend.\n");
9877+ set_result_state(SUSPEND_ABORTED);
9878+ set_result_state(SUSPEND_NOSTORAGE_AVAILABLE);
9879+ return 1;
9880+ }
9881+
9882+ do {
9883+ suspend_prepare_status(CLEAR_BAR, "Preparing Image.");
9884+
9885+ if (eat_memory() || test_result_state(SUSPEND_ABORTED))
9886+ break;
9887+
9888+ result = update_image();
9889+
9890+ suspend_cond_pause(0, NULL);
9891+
9892+ tries++;
9893+
9894+ } while ((result) && (tries < MAX_TRIES) && (!test_result_state(SUSPEND_ABORTED)) &&
9895+ (!test_result_state(SUSPEND_UNABLE_TO_FREE_ENOUGH_MEMORY)));
9896+
9897+ if (tries == MAX_TRIES) {
9898+ abort_suspend("Unable to successfully prepare the image.\n");
9899+ display_stats(1, 0);
9900+ }
9901+
9902+ suspend_cond_pause(1, "Image preparation complete.");
9903+
9904+ return result;
9905+}
9906diff --git a/kernel/power/prepare_image.h b/kernel/power/prepare_image.h
9907new file mode 100644
9908index 0000000..b68a4cd
9909--- /dev/null
9910+++ b/kernel/power/prepare_image.h
9911@@ -0,0 +1,33 @@
9912+/*
9913+ * kernel/power/prepare_image.h
9914+ *
9915+ * Copyright (C) 2003-2006 Nigel Cunningham <nigel@suspend.net>
9916+ * Copyright (C) 2006 Red Hat, inc.
9917+ *
9918+ * This file is released under the GPLv2.
9919+ *
9920+ */
9921+
9922+#include <asm/sections.h>
9923+
9924+extern int suspend_prepare_image(void);
9925+extern void suspend_recalculate_image_contents(int storage_available);
9926+extern int real_nr_free_pages(void);
9927+extern int image_size_limit;
9928+
9929+#ifdef CONFIG_CRYPTO
9930+extern int suspend_expected_compression_ratio(void);
9931+#else
9932+static inline int suspend_expected_compression_ratio(void)
9933+{
9934+ return 0;
9935+};
9936+#endif
9937+
9938+#define MIN_FREE_RAM 2000
9939+#define MIN_EXTRA_PAGES_ALLOWANCE 500
9940+
9941+extern int extra_pd1_pages_allowance;
9942+extern int storage_needed(int use_ecr, int ignore_extra_p1_allowance);
9943+extern int ram_to_suspend(void);
9944+
9945diff --git a/kernel/power/process.c b/kernel/power/process.c
9946index 72e72d2..c2cdc6d 100644
9947--- a/kernel/power/process.c
9948+++ b/kernel/power/process.c
9949@@ -13,13 +13,16 @@ #include <linux/interrupt.h>
9950 #include <linux/suspend.h>
9951 #include <linux/module.h>
9952 #include <linux/syscalls.h>
9953+#include <linux/buffer_head.h>
9954+#include <linux/freezer.h>
9955+
9956+int freezer_state;
9957
9958 /*
9959 * Timeout for stopping processes
9960 */
9961 #define TIMEOUT (20 * HZ)
9962
9963-
9964 static inline int freezeable(struct task_struct * p)
9965 {
9966 if ((p == current) ||
9967@@ -39,7 +42,6 @@ void refrigerator(void)
9968 long save;
9969 save = current->state;
9970 pr_debug("%s entered refrigerator\n", current->comm);
9971- printk("=");
9972
9973 frozen_process(current);
9974 spin_lock_irq(&current->sighand->siglock);
9975@@ -86,7 +88,7 @@ int freeze_processes(void)
9976 unsigned long start_time;
9977 struct task_struct *g, *p;
9978
9979- printk( "Stopping tasks: " );
9980+ printk("Stopping tasks... ");
9981 start_time = jiffies;
9982 user_frozen = 0;
9983 do {
9984@@ -120,6 +122,7 @@ int freeze_processes(void)
9985 todo += nr_user;
9986 if (!user_frozen && !nr_user) {
9987 sys_sync();
9988+ freezer_state = USERSPACE_FROZEN;
9989 start_time = jiffies;
9990 }
9991 user_frozen = !nr_user;
9992@@ -134,41 +137,75 @@ int freeze_processes(void)
9993 * but it cleans up leftover PF_FREEZE requests.
9994 */
9995 if (todo) {
9996- printk( "\n" );
9997- printk(KERN_ERR " stopping tasks timed out "
9998+ printk("\n");
9999+ printk(KERN_ERR " Stopping tasks timed out "
10000 "after %d seconds (%d tasks remaining):\n",
10001 TIMEOUT / HZ, todo);
10002 read_lock(&tasklist_lock);
10003 do_each_thread(g, p) {
10004 if (freezeable(p) && !frozen(p))
10005- printk(KERN_ERR " %s\n", p->comm);
10006+ printk(KERN_ERR " %s\n", p->comm);
10007 cancel_freezing(p);
10008 } while_each_thread(g, p);
10009 read_unlock(&tasklist_lock);
10010+ freezer_state = FREEZING_COMPLETE;
10011 return todo;
10012 }
10013
10014- printk( "|\n" );
10015+ printk("done.\n");
10016+ freezer_state = FREEZING_COMPLETE;
10017 BUG_ON(in_atomic());
10018 return 0;
10019 }
10020
10021-void thaw_processes(void)
10022+void thaw_some_processes(int all)
10023 {
10024 struct task_struct *g, *p;
10025+ int pass = 0; /* Pass 0 = Kernel space, 1 = Userspace */
10026+
10027+ if (!freezer_state)
10028+ return;
10029+
10030+ /* Skip kernel threads if already thawed */
10031+ if (freezer_state == USERSPACE_FROZEN) {
10032+ pass = 1;
10033+ if (!all)
10034+ return;
10035+ }
10036+
10037+ printk("Restarting tasks... ");
10038
10039- printk( "Restarting tasks..." );
10040 read_lock(&tasklist_lock);
10041- do_each_thread(g, p) {
10042- if (!freezeable(p))
10043- continue;
10044- if (!thaw_process(p))
10045- printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
10046- } while_each_thread(g, p);
10047+ do {
10048+ /*
10049+ * Without freezing bdevs, fs threads can run as soon as
10050+ * they're thawed.
10051+ */
10052+ if (!pass)
10053+ freezer_state = USERSPACE_FROZEN;
10054+
10055+ do_each_thread(g, p) {
10056+ /*
10057+ * is_user = 0 if kernel thread or borrowed mm,
10058+ * 1 otherwise.
10059+ */
10060+ int is_user = !!(p->mm && !(p->flags & PF_BORROWED_MM));
10061+ if (!freezeable(p) || (is_user != pass))
10062+ continue;
10063+ if (!thaw_process(p))
10064+ printk(KERN_INFO
10065+ "Strange, %s not stopped\n", p->comm );
10066+ } while_each_thread(g, p);
10067+
10068+ if (pass)
10069+ freezer_state--;
10070+
10071+ pass++;
10072+ } while(pass < 2 && all);
10073
10074 read_unlock(&tasklist_lock);
10075 schedule();
10076- printk( " done\n" );
10077+ printk("done.\n");
10078 }
10079
10080 EXPORT_SYMBOL(refrigerator);
10081diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
10082index 99f9b7d..70fe122 100644
10083--- a/kernel/power/snapshot.c
10084+++ b/kernel/power/snapshot.c
10085@@ -37,6 +37,13 @@ #include "power.h"
10086 /* List of PBEs used for creating and restoring the suspend image */
10087 struct pbe *restore_pblist;
10088
10089+#ifdef CONFIG_SUSPEND2
10090+#include "pagedir.h"
10091+
10092+extern int suspend2_running;
10093+int suspend_post_context_save(void);
10094+#endif
10095+
10096 static unsigned int nr_copy_pages;
10097 static unsigned int nr_meta_pages;
10098 static void *buffer;
10099@@ -195,6 +202,11 @@ static void *alloc_image_page(gfp_t gfp_
10100
10101 unsigned long get_safe_page(gfp_t gfp_mask)
10102 {
10103+#ifdef CONFIG_SUSPEND2
10104+ if (suspend2_running)
10105+ return suspend_get_nonconflicting_page();
10106+#endif
10107+
10108 return (unsigned long)alloc_image_page(gfp_mask, PG_SAFE);
10109 }
10110
10111@@ -692,7 +704,7 @@ static inline int pfn_is_nosave(unsigned
10112 * isn't a part of a free chunk of pages.
10113 */
10114
10115-static struct page *saveable_page(unsigned long pfn)
10116+struct page *saveable_page(unsigned long pfn)
10117 {
10118 struct page *page;
10119
10120@@ -868,6 +880,11 @@ asmlinkage int swsusp_save(void)
10121 {
10122 unsigned int nr_pages;
10123
10124+#ifdef CONFIG_SUSPEND2
10125+ if (suspend2_running)
10126+ return suspend_post_context_save();
10127+#endif
10128+
10129 pr_debug("swsusp: critical section: \n");
10130
10131 drain_local_pages();
10132diff --git a/kernel/power/storage.c b/kernel/power/storage.c
10133new file mode 100644
10134index 0000000..e3de1ac
10135--- /dev/null
10136+++ b/kernel/power/storage.c
10137@@ -0,0 +1,299 @@
10138+/*
10139+ * kernel/power/storage.c
10140+ *
10141+ * Copyright (C) 2005-2006 Nigel Cunningham <nigel@suspend2.net>
10142+ * Copyright (C) 2006 Red Hat, inc.
10143+ *
10144+ * This file is released under the GPLv2.
10145+ *
10146+ * Routines for talking to a userspace program that manages storage.
10147+ *
10148+ * The kernel side:
10149+ * - starts the userspace program;
10150+ * - sends messages telling it when to open and close the connection;
10151+ * - tells it when to quit;
10152+ *
10153+ * The user space side:
10154+ * - passes messages regarding status;
10155+ *
10156+ */
10157+
10158+#include <linux/suspend.h>
10159+#include <linux/freezer.h>
10160+
10161+#include "sysfs.h"
10162+#include "modules.h"
10163+#include "netlink.h"
10164+#include "storage.h"
10165+#include "ui.h"
10166+
10167+static struct user_helper_data usm_helper_data;
10168+static struct suspend_module_ops usm_ops;
10169+static int message_received = 0;
10170+static int usm_prepare_count = 0;
10171+static int storage_manager_last_action = 0;
10172+static int storage_manager_action = 0;
10173+
10174+static int usm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
10175+{
10176+ int type;
10177+ int *data;
10178+
10179+ type = nlh->nlmsg_type;
10180+
10181+ /* A control message: ignore them */
10182+ if (type < NETLINK_MSG_BASE)
10183+ return 0;
10184+
10185+ /* Unknown message: reply with EINVAL */
10186+ if (type >= USM_MSG_MAX)
10187+ return -EINVAL;
10188+
10189+ /* All operations require privileges, even GET */
10190+ if (security_netlink_recv(skb, CAP_NET_ADMIN))
10191+ return -EPERM;
10192+
10193+ /* Only allow one task to receive NOFREEZE privileges */
10194+ if (type == NETLINK_MSG_NOFREEZE_ME && usm_helper_data.pid != -1)
10195+ return -EBUSY;
10196+
10197+ data = (int*)NLMSG_DATA(nlh);
10198+
10199+ switch (type) {
10200+ case USM_MSG_SUCCESS:
10201+ case USM_MSG_FAILED:
10202+ message_received = type;
10203+ complete(&usm_helper_data.wait_for_process);
10204+ break;
10205+ default:
10206+ printk("Storage manager doesn't recognise message %d.\n", type);
10207+ }
10208+
10209+ return 1;
10210+}
10211+
10212+#ifdef CONFIG_NET
10213+static int activations = 0;
10214+
10215+int suspend_activate_storage(int force)
10216+{
10217+ int tries = 1;
10218+
10219+ if (usm_helper_data.pid == -1 || !usm_ops.enabled)
10220+ return 0;
10221+
10222+ message_received = 0;
10223+ activations++;
10224+
10225+ if (activations > 1 && !force)
10226+ return 0;
10227+
10228+ while ((!message_received || message_received == USM_MSG_FAILED) && tries < 2) {
10229+ suspend_prepare_status(DONT_CLEAR_BAR, "Activate storage attempt %d.\n", tries);
10230+
10231+ init_completion(&usm_helper_data.wait_for_process);
10232+
10233+ suspend_send_netlink_message(&usm_helper_data,
10234+ USM_MSG_CONNECT,
10235+ NULL, 0);
10236+
10237+ /* Wait 2 seconds for the userspace process to make contact */
10238+ wait_for_completion_timeout(&usm_helper_data.wait_for_process, 2*HZ);
10239+
10240+ tries++;
10241+ }
10242+
10243+ return 0;
10244+}
10245+
10246+int suspend_deactivate_storage(int force)
10247+{
10248+ if (usm_helper_data.pid == -1 || !usm_ops.enabled)
10249+ return 0;
10250+
10251+ message_received = 0;
10252+ activations--;
10253+
10254+ if (activations && !force)
10255+ return 0;
10256+
10257+ init_completion(&usm_helper_data.wait_for_process);
10258+
10259+ suspend_send_netlink_message(&usm_helper_data,
10260+ USM_MSG_DISCONNECT,
10261+ NULL, 0);
10262+
10263+ wait_for_completion_timeout(&usm_helper_data.wait_for_process, 2*HZ);
10264+
10265+ if (!message_received || message_received == USM_MSG_FAILED) {
10266+ printk("Returning failure disconnecting storage.\n");
10267+ return 1;
10268+ }
10269+
10270+ return 0;
10271+}
10272+#endif
10273+
10274+static void storage_manager_simulate(void)
10275+{
10276+ printk("--- Storage manager simulate ---\n");
10277+ suspend_prepare_usm();
10278+ schedule();
10279+ printk("--- Activate storage 1 ---\n");
10280+ suspend_activate_storage(1);
10281+ schedule();
10282+ printk("--- Deactivate storage 1 ---\n");
10283+ suspend_deactivate_storage(1);
10284+ schedule();
10285+ printk("--- Cleanup usm ---\n");
10286+ suspend_cleanup_usm();
10287+ schedule();
10288+ printk("--- Storage manager simulate ends ---\n");
10289+}
10290+
10291+static int usm_storage_needed(void)
10292+{
10293+ return strlen(usm_helper_data.program);
10294+}
10295+
10296+static int usm_save_config_info(char *buf)
10297+{
10298+ int len = strlen(usm_helper_data.program);
10299+ memcpy(buf, usm_helper_data.program, len);
10300+ return len;
10301+}
10302+
10303+static void usm_load_config_info(char *buf, int size)
10304+{
10305+ /* Don't load the saved path if one has already been set */
10306+ if (usm_helper_data.program[0])
10307+ return;
10308+
10309+ memcpy(usm_helper_data.program, buf, size);
10310+}
10311+
10312+static int usm_memory_needed(void)
10313+{
10314+ /* ball park figure of 32 pages */
10315+ return (32 * PAGE_SIZE);
10316+}
10317+
10318+/* suspend_prepare_usm
10319+ */
10320+int suspend_prepare_usm(void)
10321+{
10322+ usm_prepare_count++;
10323+
10324+ if (usm_prepare_count > 1 || !usm_ops.enabled)
10325+ return 0;
10326+
10327+ usm_helper_data.pid = -1;
10328+
10329+ if (!*usm_helper_data.program)
10330+ return 0;
10331+
10332+ suspend_netlink_setup(&usm_helper_data);
10333+
10334+ if (usm_helper_data.pid == -1)
10335+ printk("Suspend2 Storage Manager wanted, but couldn't start it.\n");
10336+
10337+ suspend_activate_storage(0);
10338+
10339+ return (usm_helper_data.pid != -1);
10340+}
10341+
10342+void suspend_cleanup_usm(void)
10343+{
10344+ usm_prepare_count--;
10345+
10346+ if (usm_helper_data.pid > -1 && !usm_prepare_count) {
10347+ struct task_struct *t;
10348+
10349+ suspend_deactivate_storage(0);
10350+
10351+ suspend_send_netlink_message(&usm_helper_data,
10352+ NETLINK_MSG_CLEANUP, NULL, 0);
10353+
10354+ read_lock(&tasklist_lock);
10355+ if ((t = find_task_by_pid(usm_helper_data.pid)))
10356+ t->flags &= ~PF_NOFREEZE;
10357+ read_unlock(&tasklist_lock);
10358+
10359+ suspend_netlink_close(&usm_helper_data);
10360+
10361+ usm_helper_data.pid = -1;
10362+ }
10363+}
10364+
10365+static void storage_manager_activate(void)
10366+{
10367+ if (storage_manager_action == storage_manager_last_action)
10368+ return;
10369+
10370+ if (storage_manager_action)
10371+ suspend_prepare_usm();
10372+ else
10373+ suspend_cleanup_usm();
10374+
10375+ storage_manager_last_action = storage_manager_action;
10376+}
10377+
10378+/*
10379+ * User interface specific /sys/power/suspend2 entries.
10380+ */
10381+
10382+static struct suspend_sysfs_data sysfs_params[] = {
10383+ { SUSPEND2_ATTR("simulate_atomic_copy", SYSFS_RW),
10384+ .type = SUSPEND_SYSFS_DATA_NONE,
10385+ .write_side_effect = storage_manager_simulate,
10386+ },
10387+
10388+ { SUSPEND2_ATTR("enabled", SYSFS_RW),
10389+ SYSFS_INT(&usm_ops.enabled, 0, 1)
10390+ },
10391+
10392+ { SUSPEND2_ATTR("program", SYSFS_RW),
10393+ SYSFS_STRING(usm_helper_data.program, 254, SYSFS_SM_NOT_NEEDED)
10394+ },
10395+
10396+ { SUSPEND2_ATTR("activate_storage", SYSFS_RW),
10397+ SYSFS_INT(&storage_manager_action, 0, 1),
10398+ .write_side_effect = storage_manager_activate,
10399+ }
10400+};
10401+
10402+static struct suspend_module_ops usm_ops = {
10403+ .type = MISC_MODULE,
10404+ .name = "Userspace Storage Manager",
10405+ .directory = "storage_manager",
10406+ .module = THIS_MODULE,
10407+ .storage_needed = usm_storage_needed,
10408+ .save_config_info = usm_save_config_info,
10409+ .load_config_info = usm_load_config_info,
10410+ .memory_needed = usm_memory_needed,
10411+
10412+ .sysfs_data = sysfs_params,
10413+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
10414+};
10415+
10416+/* suspend_usm_sysfs_init
10417+ * Description: Boot time initialisation for user interface.
10418+ */
10419+static __init int suspend_usm_sysfs_init(void)
10420+{
10421+ usm_helper_data.nl = NULL;
10422+ usm_helper_data.program[0] = '\0';
10423+ usm_helper_data.pid = -1;
10424+ usm_helper_data.skb_size = 0;
10425+ usm_helper_data.pool_limit = 6;
10426+ usm_helper_data.netlink_id = NETLINK_SUSPEND2_USM;
10427+ usm_helper_data.name = "userspace storage manager";
10428+ usm_helper_data.rcv_msg = usm_user_rcv_msg;
10429+ usm_helper_data.interface_version = 1;
10430+ usm_helper_data.must_init = 0;
10431+ init_completion(&usm_helper_data.wait_for_process);
10432+
10433+ return suspend_register_module(&usm_ops);
10434+}
10435+
10436+late_initcall(suspend_usm_sysfs_init);
10437diff --git a/kernel/power/storage.h b/kernel/power/storage.h
10438new file mode 100644
10439index 0000000..8573fea
10440--- /dev/null
10441+++ b/kernel/power/storage.h
10442@@ -0,0 +1,38 @@
10443+/*
10444+ * kernel/power/storage.h
10445+ *
10446+ * Copyright (C) 2005-2006 Nigel Cunningham <nigel@suspend2.net>
10447+ * Copyright (C) 2006 Red Hat, inc.
10448+ *
10449+ * This file is released under the GPLv2.
10450+ */
10451+
10452+int suspend_prepare_usm(void);
10453+void suspend_cleanup_usm(void);
10454+
10455+#ifdef CONFIG_NET
10456+int suspend_activate_storage(int force);
10457+int suspend_deactivate_storage(int force);
10458+#else
10459+static inline int suspend_activate_storage(int force)
10460+{
10461+ return 0;
10462+}
10463+
10464+static inline int suspend_deactivate_storage(int force)
10465+{
10466+ return 0;
10467+}
10468+#endif
10469+
10470+enum {
10471+ USM_MSG_BASE = 0x10,
10472+
10473+ /* Kernel -> Userspace */
10474+ USM_MSG_CONNECT = 0x30,
10475+ USM_MSG_DISCONNECT = 0x31,
10476+ USM_MSG_SUCCESS = 0x40,
10477+ USM_MSG_FAILED = 0x41,
10478+
10479+ USM_MSG_MAX,
10480+};
10481diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
10482new file mode 100644
10483index 0000000..09d8b50
10484--- /dev/null
10485+++ b/kernel/power/suspend.c
10486@@ -0,0 +1,953 @@
10487+/*
10488+ * kernel/power/suspend.c
10489+ */
10490+/** \mainpage Suspend2.
10491+ *
10492+ * Suspend2 provides support for saving and restoring an image of
10493+ * system memory to an arbitrary storage device, either on the local computer,
10494+ * or across some network. The support is entirely OS based, so Suspend2
10495+ * works without requiring BIOS, APM or ACPI support. The vast majority of the
10496+ * code is also architecture independant, so it should be very easy to port
10497+ * the code to new architectures. Suspend includes support for SMP, 4G HighMem
10498+ * and preemption. Initramfses and initrds are also supported.
10499+ *
10500+ * Suspend2 uses a modular design, in which the method of storing the image is
10501+ * completely abstracted from the core code, as are transformations on the data
10502+ * such as compression and/or encryption (multiple 'modules' can be used to
10503+ * provide arbitrary combinations of functionality). The user interface is also
10504+ * modular, so that arbitrarily simple or complex interfaces can be used to
10505+ * provide anything from debugging information through to eye candy.
10506+ *
10507+ * \section Copyright
10508+ *
10509+ * Suspend2 is released under the GPLv2.
10510+ *
10511+ * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu><BR>
10512+ * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz><BR>
10513+ * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr><BR>
10514+ * Copyright (C) 2002-2006 Nigel Cunningham <nigel@suspend2.net><BR>
10515+ * Copyright (C) 2006 Red Hat, inc.
10516+ *
10517+ * \section Credits
10518+ *
10519+ * Nigel would like to thank the following people for their work:
10520+ *
10521+ * Pavel Machek <pavel@ucw.cz><BR>
10522+ * Modifications, defectiveness pointing, being with Gabor at the very beginning,
10523+ * suspend to swap space, stop all tasks. Port to 2.4.18-ac and 2.5.17.
10524+ *
10525+ * Steve Doddi <dirk@loth.demon.co.uk><BR>
10526+ * Support the possibility of hardware state restoring.
10527+ *
10528+ * Raph <grey.havens@earthling.net><BR>
10529+ * Support for preserving states of network devices and virtual console
10530+ * (including X and svgatextmode)
10531+ *
10532+ * Kurt Garloff <garloff@suse.de><BR>
10533+ * Straightened the critical function in order to prevent compilers from
10534+ * playing tricks with local variables.
10535+ *
10536+ * Andreas Mohr <a.mohr@mailto.de>
10537+ *
10538+ * Alex Badea <vampire@go.ro><BR>
10539+ * Fixed runaway init
10540+ *
10541+ * Jeff Snyder <je4d@pobox.com><BR>
10542+ * ACPI patch
10543+ *
10544+ * Nathan Friess <natmanz@shaw.ca><BR>
10545+ * Some patches.
10546+ *
10547+ * Michael Frank <mhf@linuxmail.org><BR>
10548+ * Extensive testing and help with improving stability. Nigel was constantly
10549+ * amazed by the quality and quantity of Michael's help.
10550+ *
10551+ * Bernard Blackham <bernard@blackham.com.au><BR>
10552+ * Web page & Wiki administration, some coding. Another person without whom
10553+ * Suspend would not be where it is.
10554+ *
10555+ * ..and of course the myriads of Suspend2 users who have helped diagnose
10556+ * and fix bugs, made suggestions on how to improve the code, proofread
10557+ * documentation, and donated time and money.
10558+ *
10559+ * Thanks also to corporate sponsors:
10560+ *
10561+ * <B>Cyclades.com.</B> Nigel's employers from Dec 2004, who allow him to work on
10562+ * Suspend and PM related issues on company time.
10563+ *
10564+ * <B>LinuxFund.org.</B> Sponsored Nigel's work on Suspend for four months Oct 2003
10565+ * to Jan 2004.
10566+ *
10567+ * <B>LAC Linux.</B> Donated P4 hardware that enabled development and ongoing
10568+ * maintenance of SMP and Highmem support.
10569+ *
10570+ * <B>OSDL.</B> Provided access to various hardware configurations, make occasional
10571+ * small donations to the project.
10572+ */
10573+
10574+#define SUSPEND_MAIN_C
10575+
10576+#include <linux/suspend.h>
10577+#include <linux/module.h>
10578+#include <linux/console.h>
10579+#include <linux/version.h>
10580+#include <linux/reboot.h>
10581+#include <linux/mm.h>
10582+#include <linux/highmem.h>
10583+#include <linux/freezer.h>
10584+#include <linux/utsrelease.h>
10585+#include <linux/swap.h> /* For LRU unlinking prototypes */
10586+#include <linux/cpu.h>
10587+#include <asm/uaccess.h>
10588+#include <asm/setup.h>
10589+
10590+#include "modules.h"
10591+#include "sysfs.h"
10592+#include "pageflags.h"
10593+#include "prepare_image.h"
10594+#include "io.h"
10595+#include "ui.h"
10596+#include "extent.h"
10597+#include "power_off.h"
10598+#include "storage.h"
10599+#include "checksum.h"
10600+
10601+#ifdef CONFIG_X86
10602+#include <asm/i387.h> /* for kernel_fpu_end */
10603+#endif
10604+
10605+int suspend2_running;
10606+
10607+/* Variables to be preserved over suspend */
10608+int image_size_limit = 0;
10609+unsigned long suspend_orig_mem_free = 0;
10610+
10611+extern __nosavedata char suspend_resume_commandline[COMMAND_LINE_SIZE];
10612+
10613+#ifdef CONFIG_SUSPEND2_REPLACE_SWSUSP
10614+unsigned long suspend_action = 1 << SUSPEND_REPLACE_SWSUSP;
10615+#else
10616+unsigned long suspend_action = 0;
10617+#endif
10618+unsigned long suspend_result = 0;
10619+unsigned long suspend_debug_state = 0;
10620+
10621+int suspend2_in_suspend __nosavedata;
10622+
10623+static int orig_system_state;
10624+
10625+/*
10626+ * --- Variables -----
10627+ *
10628+ * The following are used by the arch specific low level routines
10629+ * and only needed if suspend2 is compiled in. Other variables,
10630+ * used by the freezer even if suspend2 is not compiled in, are
10631+ * found in process.c
10632+ */
10633+
10634+/*! How long I/O took. */
10635+int suspend_io_time[2][2];
10636+
10637+/*! Pageset metadata. */
10638+struct pagedir pagedir1 = {1, 0, 0}, pagedir2 = {2, 0, 0};
10639+
10640+/* The number of suspends we have started (some may have been cancelled) */
10641+unsigned int nr_suspends = 0;
10642+
10643+/*
10644+ * For resume2= kernel option. It's pointless to compile
10645+ * suspend2 without any allocators, but compilation shouldn't
10646+ * fail if you do.
10647+ */
10648+
10649+unsigned long suspend_state = ((1 << SUSPEND_BOOT_TIME) |
10650+ (1 << SUSPEND_RESUME_NOT_DONE) | (1 << SUSPEND_IGNORE_LOGLEVEL));
10651+
10652+static mm_segment_t oldfs;
10653+
10654+char resume2_file[256] = CONFIG_SUSPEND2_DEFAULT_RESUME2;
10655+#ifdef CONFIG_SOFTWARE_SUSPEND
10656+extern char resume_file[256];
10657+#endif
10658+
10659+static atomic_t actions_running;
10660+
10661+extern int block_dump;
10662+int block_dump_save;
10663+
10664+/*
10665+ * Basic clean-up routine.
10666+ */
10667+void suspend_finish_anything(int finishing_cycle)
10668+{
10669+ if (atomic_dec_and_test(&actions_running)) {
10670+ suspend_cleanup_modules(finishing_cycle);
10671+ suspend_put_modules();
10672+ clear_suspend_state(SUSPEND_RUNNING);
10673+ }
10674+
10675+ set_fs(oldfs);
10676+
10677+ if (finishing_cycle)
10678+ block_dump = block_dump_save;
10679+}
10680+
10681+/*
10682+ * Basic set-up routine.
10683+ */
10684+int suspend_start_anything(int starting_cycle)
10685+{
10686+ oldfs = get_fs();
10687+
10688+ if (atomic_add_return(1, &actions_running) == 1) {
10689+ set_fs(KERNEL_DS);
10690+
10691+ set_suspend_state(SUSPEND_RUNNING);
10692+
10693+ if (suspend_get_modules()) {
10694+ printk(name_suspend "Get modules failed!\n");
10695+ clear_suspend_state(SUSPEND_RUNNING);
10696+ set_fs(oldfs);
10697+ return -EBUSY;
10698+ }
10699+
10700+ if (suspend_initialise_modules(starting_cycle)) {
10701+ printk(name_suspend "Initialise modules failed!\n");
10702+ suspend_finish_anything(starting_cycle);
10703+ return -EBUSY;
10704+ }
10705+
10706+ if (starting_cycle) {
10707+ block_dump_save = block_dump;
10708+ block_dump = 0;
10709+ }
10710+ }
10711+
10712+ return 0;
10713+}
10714+
10715+/*
10716+ * save_image
10717+ * Functionality : High level routine which performs the steps necessary
10718+ * to prepare and save the image after preparatory steps
10719+ * have been taken.
10720+ * Key Assumptions : Processes frozen, sufficient memory available, drivers
10721+ * suspended.
10722+ * Called from : suspend_suspend_2
10723+ */
10724+static void save_image(void)
10725+{
10726+ int temp_result;
10727+
10728+ suspend_message(SUSPEND_ANY_SECTION, SUSPEND_LOW, 1,
10729+ " - Final values: %d and %d.\n",
10730+ pagedir1.size, pagedir2.size);
10731+
10732+ suspend_cond_pause(1, "About to write pagedir2.");
10733+
10734+ calculate_check_checksums(0);
10735+
10736+ temp_result = write_pageset(&pagedir2);
10737+
10738+ if (temp_result == -1 || test_result_state(SUSPEND_ABORTED))
10739+ return;
10740+
10741+ suspend_cond_pause(1, "About to copy pageset 1.");
10742+
10743+ if (test_result_state(SUSPEND_ABORTED))
10744+ return;
10745+
10746+ suspend_deactivate_storage(1);
10747+
10748+ suspend_prepare_status(DONT_CLEAR_BAR, "Doing atomic copy.");
10749+
10750+ suspend2_running = 1; /* For the swsusp code we use :< */
10751+
10752+ suspend2_in_suspend = 1;
10753+
10754+ if (device_suspend(PMSG_FREEZE)) {
10755+ set_result_state(SUSPEND_DEVICE_REFUSED);
10756+ set_result_state(SUSPEND_ABORTED);
10757+ return;
10758+ }
10759+
10760+ if (suspend2_suspend()) {
10761+ device_resume();
10762+ return;
10763+ }
10764+
10765+ suspend2_running = 0;
10766+
10767+ device_resume();
10768+
10769+ /* Resume time? */
10770+ if (!suspend2_in_suspend) {
10771+ copyback_post();
10772+ return;
10773+ }
10774+
10775+ /* Nope. Suspending. So, see if we can save the image... */
10776+ if (!save_image_part1()) {
10777+ suspend_power_down();
10778+
10779+ if (read_pageset2(1))
10780+ panic("Attempt to reload pagedir 2 failed. Try rebooting.");
10781+
10782+ if (!test_result_state(SUSPEND_ABORT_REQUESTED) &&
10783+ !test_action_state(SUSPEND_TEST_FILTER_SPEED) &&
10784+ !test_action_state(SUSPEND_TEST_BIO) &&
10785+ suspend_powerdown_method != PM_SUSPEND_MEM)
10786+ printk(KERN_EMERG name_suspend
10787+ "Suspend failed, trying to recover...\n");
10788+ barrier();
10789+ mb();
10790+ }
10791+
10792+ return;
10793+}
10794+
10795+/*
10796+ * Save the second part of the image.
10797+ */
10798+int save_image_part1(void)
10799+{
10800+ int temp_result;
10801+
10802+ if (suspend_activate_storage(1))
10803+ panic("Failed to reactivate our storage.");
10804+
10805+ suspend_update_status(pagedir2.size,
10806+ pagedir1.size + pagedir2.size,
10807+ NULL);
10808+
10809+ if (test_result_state(SUSPEND_ABORTED))
10810+ goto abort_reloading_pagedir_two;
10811+
10812+ suspend_cond_pause(1, "About to write pageset1.");
10813+
10814+ /*
10815+ * End of critical section.
10816+ */
10817+
10818+ suspend_message(SUSPEND_ANY_SECTION, SUSPEND_LOW, 1,
10819+ "-- Writing pageset1\n");
10820+
10821+ temp_result = write_pageset(&pagedir1);
10822+
10823+ /* We didn't overwrite any memory, so no reread needs to be done. */
10824+ if (test_action_state(SUSPEND_TEST_FILTER_SPEED))
10825+ return -1;
10826+
10827+ if (temp_result == -1 || test_result_state(SUSPEND_ABORTED))
10828+ goto abort_reloading_pagedir_two;
10829+
10830+ suspend_cond_pause(1, "About to write header.");
10831+
10832+ if (test_result_state(SUSPEND_ABORTED))
10833+ goto abort_reloading_pagedir_two;
10834+
10835+ temp_result = write_image_header();
10836+
10837+ if (test_action_state(SUSPEND_TEST_BIO))
10838+ return -1;
10839+
10840+ if (temp_result || test_result_state(SUSPEND_ABORTED))
10841+ goto abort_reloading_pagedir_two;
10842+
10843+ suspend_cond_pause(1, "About to power down or reboot.");
10844+
10845+ return 0;
10846+
10847+abort_reloading_pagedir_two:
10848+ temp_result = read_pageset2(1);
10849+
10850+ /* If that failed, we're sunk. Panic! */
10851+ if (temp_result)
10852+ panic("Attempt to reload pagedir 2 while aborting "
10853+ "a suspend failed.");
10854+
10855+ return -1;
10856+
10857+}
10858+
10859+static int io_MB_per_second(int read_write)
10860+{
10861+ return (suspend_io_time[read_write][1]) ?
10862+ MB((unsigned long) suspend_io_time[read_write][0]) * HZ /
10863+ suspend_io_time[read_write][1] : 0;
10864+}
10865+
10866+/* get_debug_info
10867+ * Functionality: Store debug info in a buffer.
10868+ * Called from: suspend2_try_suspend.
10869+ */
10870+#define SNPRINTF(a...) len += snprintf_used(((char *)buffer) + len, \
10871+ count - len - 1, ## a)
10872+static int get_suspend_debug_info(const char *buffer, int count)
10873+{
10874+ int len = 0;
10875+
10876+ SNPRINTF("Suspend2 debugging info:\n");
10877+ SNPRINTF("- SUSPEND core : %s\n", SUSPEND_CORE_VERSION);
10878+ SNPRINTF("- Kernel Version : %s\n", UTS_RELEASE);
10879+ SNPRINTF("- Compiler vers. : %d.%d\n", __GNUC__, __GNUC_MINOR__);
10880+ SNPRINTF("- Attempt number : %d\n", nr_suspends);
10881+ SNPRINTF("- Parameters : %ld %ld %ld %d %d %ld\n",
10882+ suspend_result,
10883+ suspend_action,
10884+ suspend_debug_state,
10885+ suspend_default_console_level,
10886+ image_size_limit,
10887+ suspend_powerdown_method);
10888+ SNPRINTF("- Overall expected compression percentage: %d.\n",
10889+ 100 - suspend_expected_compression_ratio());
10890+ len+= suspend_print_module_debug_info(((char *) buffer) + len,
10891+ PAGE_SIZE - len - 1);
10892+ if (suspend_io_time[0][1]) {
10893+ if ((io_MB_per_second(0) < 5) || (io_MB_per_second(1) < 5)) {
10894+ SNPRINTF("- I/O speed: Write %d KB/s",
10895+ (KB((unsigned long) suspend_io_time[0][0]) * HZ /
10896+ suspend_io_time[0][1]));
10897+ if (suspend_io_time[1][1])
10898+ SNPRINTF(", Read %d KB/s",
10899+ (KB((unsigned long) suspend_io_time[1][0]) * HZ /
10900+ suspend_io_time[1][1]));
10901+ } else {
10902+ SNPRINTF("- I/O speed: Write %d MB/s",
10903+ (MB((unsigned long) suspend_io_time[0][0]) * HZ /
10904+ suspend_io_time[0][1]));
10905+ if (suspend_io_time[1][1])
10906+ SNPRINTF(", Read %d MB/s",
10907+ (MB((unsigned long) suspend_io_time[1][0]) * HZ /
10908+ suspend_io_time[1][1]));
10909+ }
10910+ SNPRINTF(".\n");
10911+ }
10912+ else
10913+ SNPRINTF("- No I/O speed stats available.\n");
10914+ SNPRINTF("- Extra pages : %d used/%d.\n",
10915+ extra_pd1_pages_used, extra_pd1_pages_allowance);
10916+
10917+ return len;
10918+}
10919+
10920+static int allocate_bitmaps(void)
10921+{
10922+ if (allocate_dyn_pageflags(&in_use_map) ||
10923+ allocate_dyn_pageflags(&pageset1_map) ||
10924+ allocate_dyn_pageflags(&pageset1_copy_map) ||
10925+ allocate_dyn_pageflags(&pageset2_map) ||
10926+ allocate_dyn_pageflags(&page_resave_map) ||
10927+ allocate_dyn_pageflags(&pageset2_rw_map))
10928+ return 1;
10929+
10930+ return 0;
10931+}
10932+
10933+static void free_metadata(void)
10934+{
10935+ free_dyn_pageflags(&pageset1_map);
10936+ free_dyn_pageflags(&pageset1_copy_map);
10937+ free_dyn_pageflags(&pageset2_map);
10938+ free_dyn_pageflags(&page_resave_map);
10939+ free_dyn_pageflags(&pageset2_rw_map);
10940+ free_dyn_pageflags(&in_use_map);
10941+}
10942+
10943+static int check_still_keeping_image(void)
10944+{
10945+ if (test_action_state(SUSPEND_KEEP_IMAGE)) {
10946+ printk("Image already stored: powering down immediately.");
10947+ suspend_power_down();
10948+ return 1; /* Just in case we're using S3 */
10949+ }
10950+
10951+ printk("Invalidating previous image.\n");
10952+ suspendActiveAllocator->invalidate_image();
10953+
10954+ return 0;
10955+}
10956+
10957+static int suspend_init(void)
10958+{
10959+ suspend_result = 0;
10960+
10961+ printk(KERN_INFO name_suspend "Initiating a software suspend cycle.\n");
10962+
10963+ nr_suspends++;
10964+ clear_suspend_state(SUSPEND_NOW_RESUMING);
10965+
10966+ orig_system_state = system_state;
10967+
10968+ suspend_io_time[0][0] = suspend_io_time[0][1] =
10969+ suspend_io_time[1][0] = suspend_io_time[1][1] = 0;
10970+
10971+ free_metadata(); /* We might have kept it */
10972+
10973+ if (!test_suspend_state(SUSPEND_CAN_SUSPEND) ||
10974+ allocate_bitmaps())
10975+ return 0;
10976+
10977+ suspend_prepare_console();
10978+ disable_nonboot_cpus();
10979+
10980+ return 1;
10981+}
10982+
10983+void suspend_cleanup(int had_pmsem)
10984+{
10985+ int i = 0;
10986+ char *buffer;;
10987+
10988+ free_checksum_pages();
10989+
10990+ buffer = (char *) get_zeroed_page(GFP_ATOMIC);
10991+
10992+ if (buffer)
10993+ i = get_suspend_debug_info(buffer, PAGE_SIZE);
10994+
10995+ suspend_free_extra_pagedir_memory();
10996+
10997+ pagedir1.size = pagedir2.size = 0;
10998+
10999+ system_state = orig_system_state;
11000+
11001+ thaw_processes();
11002+
11003+#ifdef CONFIG_SUSPEND2_KEEP_IMAGE
11004+ if (test_action_state(SUSPEND_KEEP_IMAGE) &&
11005+ !test_result_state(SUSPEND_ABORTED)) {
11006+ suspend_message(SUSPEND_ANY_SECTION, SUSPEND_LOW, 1,
11007+ name_suspend "Not invalidating the image due "
11008+ "to Keep Image being enabled.\n");
11009+ set_result_state(SUSPEND_KEPT_IMAGE);
11010+ } else
11011+#endif
11012+ if (suspendActiveAllocator)
11013+ suspendActiveAllocator->invalidate_image();
11014+
11015+ free_metadata();
11016+
11017+ if (buffer && i) {
11018+ /* Printk can only handle 1023 bytes, including
11019+ * its level mangling. */
11020+ for (i = 0; i < 3; i++)
11021+ printk("%s", buffer + (1023 * i));
11022+ free_page((unsigned long) buffer);
11023+ buffer = NULL;
11024+ }
11025+
11026+ enable_nonboot_cpus();
11027+ suspend_cleanup_console();
11028+ suspend2_running = 0;
11029+ if (!had_pmsem)
11030+ up(&pm_sem);
11031+}
11032+
11033+static int can_suspend(int had_pmsem)
11034+{
11035+ if (!had_pmsem && down_trylock(&pm_sem)) {
11036+ set_result_state(SUSPEND_ABORTED);
11037+ set_result_state(SUSPEND_PM_SEM);
11038+ return 0;
11039+ }
11040+
11041+ if (!test_suspend_state(SUSPEND_CAN_SUSPEND))
11042+ suspend_attempt_to_parse_resume_device();
11043+
11044+ if (!test_suspend_state(SUSPEND_CAN_SUSPEND)) {
11045+ printk(name_suspend "Software suspend is disabled.\n"
11046+ "This may be because you haven't put something along "
11047+ "the lines of\n\nresume2=swap:/dev/hda1\n\n"
11048+ "in lilo.conf or equivalent. (Where /dev/hda1 is your "
11049+ "swap partition).\n");
11050+ set_result_state(SUSPEND_ABORTED);
11051+ if (!had_pmsem)
11052+ up(&pm_sem);
11053+ return 0;
11054+ }
11055+
11056+ return 1;
11057+}
11058+
11059+/*
11060+ * suspend_main
11061+ * Functionality : First level of code for software suspend invocations.
11062+ * Stores and restores load averages (to avoid a spike),
11063+ * allocates bitmaps, freezes processes and eats memory
11064+ * as required before suspending drivers and invoking
11065+ * the 'low level' code to save the state to disk.
11066+ * By the time we return from do_suspend2_suspend, we
11067+ * have either failed to save the image or successfully
11068+ * suspended and reloaded the image. The difference can
11069+ * be discerned by checking SUSPEND_ABORTED.
11070+ * Called From :
11071+ */
11072+void suspend_main(int had_pmsem)
11073+{
11074+ if (suspend_activate_storage(0))
11075+ return;
11076+
11077+ if (!can_suspend(had_pmsem))
11078+ goto cleanup_deactivate_storage;
11079+
11080+ /*
11081+ * If kept image and still keeping image and suspending to RAM, we will
11082+ * return 1 after suspending and resuming (provided the power doesn't
11083+ * run out.
11084+ */
11085+ if (test_result_state(SUSPEND_KEPT_IMAGE) && check_still_keeping_image())
11086+ goto cleanup;
11087+
11088+
11089+ if (suspend_init() && !suspend_prepare_image() && !test_result_state(SUSPEND_ABORTED) &&
11090+ !test_action_state(SUSPEND_FREEZER_TEST)) {
11091+ suspend_prepare_status(DONT_CLEAR_BAR, "Starting to save the image..");
11092+ unlink_lru_lists();
11093+ save_image();
11094+ relink_lru_lists();
11095+ }
11096+
11097+cleanup:
11098+ suspend_cleanup(had_pmsem);
11099+cleanup_deactivate_storage:
11100+ suspend_deactivate_storage(0);
11101+}
11102+
11103+/* image_exists_read
11104+ *
11105+ * Return 0 or 1, depending on whether an image is found.
11106+ * Incoming buffer is PAGE_SIZE and result is guaranteed
11107+ * to be far less than that, so we don't worry about
11108+ * overflow.
11109+ */
11110+static int image_exists_read(const char *page, int count)
11111+{
11112+ int len = 0;
11113+ char *result;
11114+
11115+ if (suspend_activate_storage(0))
11116+ return count;
11117+
11118+ if (!test_suspend_state(SUSPEND_RESUME_DEVICE_OK))
11119+ suspend_attempt_to_parse_resume_device();
11120+
11121+ if (!suspendActiveAllocator) {
11122+ len = sprintf((char *) page, "-1\n");
11123+ } else {
11124+ result = get_have_image_data();
11125+ if (result) {
11126+ len = sprintf((char *) page, "%s", result);
11127+ free_page((unsigned long) result);
11128+ }
11129+ }
11130+
11131+ suspend_deactivate_storage(0);
11132+
11133+ return len;
11134+}
11135+
11136+/* image_exists_write
11137+ *
11138+ * Invalidate an image if one exists.
11139+ */
11140+static int image_exists_write(const char *buffer, int count)
11141+{
11142+ if (suspend_activate_storage(0))
11143+ return count;
11144+
11145+ if (suspendActiveAllocator && suspendActiveAllocator->image_exists())
11146+ suspendActiveAllocator->invalidate_image();
11147+
11148+ suspend_deactivate_storage(0);
11149+
11150+ return count;
11151+}
11152+
11153+/*
11154+ * Core sysfs entries that aren't built in.
11155+ *
11156+ * This array contains entries that are automatically registered at
11157+ * boot. Modules and the console code register their own entries separately.
11158+ */
11159+static struct suspend_sysfs_data sysfs_params[] = {
11160+ { SUSPEND2_ATTR("debug_info", SYSFS_READONLY),
11161+ SYSFS_CUSTOM(get_suspend_debug_info, NULL, SYSFS_SM_NOT_NEEDED)
11162+ },
11163+
11164+ { SUSPEND2_ATTR("extra_pages_allowance", SYSFS_RW),
11165+ SYSFS_INT(&extra_pd1_pages_allowance, 0, INT_MAX)
11166+ },
11167+
11168+ { SUSPEND2_ATTR("ignore_rootfs", SYSFS_RW),
11169+ SYSFS_BIT(&suspend_action, SUSPEND_IGNORE_ROOTFS)
11170+ },
11171+
11172+ { SUSPEND2_ATTR("image_exists", SYSFS_RW),
11173+ SYSFS_CUSTOM(image_exists_read, image_exists_write,
11174+ SYSFS_NEEDS_FOR_BOTH)
11175+ },
11176+
11177+ { SUSPEND2_ATTR("image_size_limit", SYSFS_RW),
11178+ SYSFS_INT(&image_size_limit, -2, INT_MAX)
11179+ },
11180+
11181+ { SUSPEND2_ATTR("last_result", SYSFS_READONLY),
11182+ SYSFS_UL(&suspend_result, 0, 0)
11183+ },
11184+
11185+ { SUSPEND2_ATTR("full_pageset2", SYSFS_RW),
11186+ SYSFS_BIT(&suspend_action, SUSPEND_PAGESET2_FULL)
11187+ },
11188+
11189+ { SUSPEND2_ATTR("reboot", SYSFS_RW),
11190+ SYSFS_BIT(&suspend_action, SUSPEND_REBOOT)
11191+ },
11192+
11193+#ifdef CONFIG_SOFTWARE_SUSPEND
11194+ { SUSPEND2_ATTR("replace_swsusp", SYSFS_RW),
11195+ SYSFS_BIT(&suspend_action, SUSPEND_REPLACE_SWSUSP)
11196+ },
11197+#endif
11198+
11199+ { SUSPEND2_ATTR("resume2", SYSFS_RW),
11200+ SYSFS_STRING(resume2_file, 255, SYSFS_NEEDS_FOR_WRITE),
11201+ .write_side_effect = attempt_to_parse_resume_device2,
11202+ },
11203+
11204+ { SUSPEND2_ATTR("resume_commandline", SYSFS_RW),
11205+ SYSFS_STRING(suspend_resume_commandline, COMMAND_LINE_SIZE,
11206+ SYSFS_SM_NOT_NEEDED)
11207+ },
11208+
11209+ { SUSPEND2_ATTR("version", SYSFS_READONLY),
11210+ SYSFS_STRING(SUSPEND_CORE_VERSION, 0, SYSFS_SM_NOT_NEEDED)
11211+ },
11212+
11213+ { SUSPEND2_ATTR("freezer_test", SYSFS_RW),
11214+ SYSFS_BIT(&suspend_action, SUSPEND_FREEZER_TEST)
11215+ },
11216+
11217+ { SUSPEND2_ATTR("test_bio", SYSFS_RW),
11218+ SYSFS_BIT(&suspend_action, SUSPEND_TEST_BIO)
11219+ },
11220+
11221+ { SUSPEND2_ATTR("test_filter_speed", SYSFS_RW),
11222+ SYSFS_BIT(&suspend_action, SUSPEND_TEST_FILTER_SPEED)
11223+ },
11224+
11225+ { SUSPEND2_ATTR("slow", SYSFS_RW),
11226+ SYSFS_BIT(&suspend_action, SUSPEND_SLOW)
11227+ },
11228+
11229+ { SUSPEND2_ATTR("no_pageset2", SYSFS_RW),
11230+ SYSFS_BIT(&suspend_action, SUSPEND_NO_PAGESET2)
11231+ },
11232+
11233+#if defined(CONFIG_ACPI)
11234+ { SUSPEND2_ATTR("powerdown_method", SYSFS_RW),
11235+ SYSFS_UL(&suspend_powerdown_method, 0, 5)
11236+ },
11237+#endif
11238+
11239+#ifdef CONFIG_SUSPEND2_KEEP_IMAGE
11240+ { SUSPEND2_ATTR("keep_image", SYSFS_RW),
11241+ SYSFS_BIT(&suspend_action, SUSPEND_KEEP_IMAGE)
11242+ },
11243+#endif
11244+};
11245+
11246+static __init int core_load(void)
11247+{
11248+ int i,
11249+ numfiles = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data);
11250+
11251+ printk("Suspend2 Core.\n");
11252+
11253+ suspend_initialise_module_lists();
11254+
11255+ for (i=0; i< numfiles; i++)
11256+ suspend_register_sysfs_file(&suspend2_subsys.kset.kobj,
11257+ &sysfs_params[i]);
11258+
11259+#ifdef CONFIG_SOFTWARE_SUSPEND
11260+ /* Overriding resume2= with resume=? */
11261+ if (test_action_state(SUSPEND_REPLACE_SWSUSP) && resume_file[0])
11262+ strncpy(resume2_file, resume_file, 256);
11263+#endif
11264+
11265+ return 0;
11266+}
11267+
11268+/*
11269+ * Called from init kernel_thread.
11270+ * We check if we have an image and if so we try to resume.
11271+ * We also start ksuspendd if configuration looks right.
11272+ */
11273+int suspend_resume(void)
11274+{
11275+ int read_image_result = 0;
11276+
11277+ if (sizeof(swp_entry_t) != sizeof(long)) {
11278+ printk(KERN_WARNING name_suspend
11279+ "The size of swp_entry_t != size of long. "
11280+ "Please report this!\n");
11281+ return 1;
11282+ }
11283+
11284+ if (!resume2_file[0])
11285+ printk(KERN_WARNING name_suspend
11286+ "You need to use a resume2= command line parameter to "
11287+ "tell Suspend2 where to look for an image.\n");
11288+
11289+ suspend_activate_storage(0);
11290+
11291+ if (!(test_suspend_state(SUSPEND_RESUME_DEVICE_OK)) &&
11292+ !suspend_attempt_to_parse_resume_device()) {
11293+ /*
11294+ * Without a usable storage device we can do nothing -
11295+ * even if noresume is given
11296+ */
11297+
11298+ if (!suspendNumAllocators)
11299+ printk(KERN_ALERT name_suspend
11300+ "No storage allocators have been registered.\n");
11301+ else
11302+ printk(KERN_ALERT name_suspend
11303+ "Missing or invalid storage location "
11304+ "(resume2= parameter). Please correct and "
11305+ "rerun lilo (or equivalent) before "
11306+ "suspending.\n");
11307+ suspend_deactivate_storage(0);
11308+ return 1;
11309+ }
11310+
11311+ suspend_orig_mem_free = real_nr_free_pages();
11312+
11313+ read_image_result = read_pageset1(); /* non fatal error ignored */
11314+
11315+ if (test_suspend_state(SUSPEND_NORESUME_SPECIFIED))
11316+ printk(KERN_WARNING name_suspend "Resuming disabled as requested.\n");
11317+
11318+ suspend_deactivate_storage(0);
11319+
11320+ if (read_image_result)
11321+ return 1;
11322+
11323+ suspend2_running = 1;
11324+
11325+ suspend_atomic_restore();
11326+
11327+ BUG();
11328+
11329+ return 0;
11330+}
11331+
11332+/* -- Functions for kickstarting a suspend or resume --- */
11333+
11334+/*
11335+ * Check if we have an image and if so try to resume.
11336+ */
11337+void __suspend_try_resume(void)
11338+{
11339+ set_suspend_state(SUSPEND_TRYING_TO_RESUME);
11340+ clear_suspend_state(SUSPEND_RESUME_NOT_DONE);
11341+
11342+ suspend_resume();
11343+
11344+ clear_suspend_state(SUSPEND_IGNORE_LOGLEVEL);
11345+ clear_suspend_state(SUSPEND_TRYING_TO_RESUME);
11346+}
11347+
11348+/* Wrapper for when called from init/do_mounts.c */
11349+void suspend2_try_resume(void)
11350+{
11351+ if (suspend_start_anything(0))
11352+ return;
11353+
11354+ down(&pm_sem);
11355+ __suspend_try_resume();
11356+
11357+ /*
11358+ * For initramfs, we have to clear the boot time
11359+ * flag after trying to resume
11360+ */
11361+ clear_suspend_state(SUSPEND_BOOT_TIME);
11362+
11363+ up(&pm_sem);
11364+
11365+ suspend_finish_anything(0);
11366+}
11367+
11368+/*
11369+ * suspend2_try_suspend
11370+ * Functionality : Wrapper around suspend_main.
11371+ * Called From : drivers/acpi/sleep/main.c
11372+ * kernel/reboot.c
11373+ */
11374+void suspend2_try_suspend(int have_pmsem)
11375+{
11376+ if (suspend_start_anything(0))
11377+ return;
11378+
11379+ suspend_main(0);
11380+
11381+ suspend_finish_anything(0);
11382+}
11383+
11384+/* -- Commandline Parameter Handling ---
11385+ *
11386+ * Resume setup: obtain the storage device.
11387+ */
11388+static int __init resume2_setup(char *str)
11389+{
11390+ if (!*str)
11391+ return 0;
11392+
11393+ strncpy(resume2_file, str, 255);
11394+ return 0;
11395+}
11396+
11397+/*
11398+ * Allow the user to specify that we should ignore any image found and
11399+ * invalidate the image if necesssary. This is equivalent to running
11400+ * the task queue and a sync and then turning off the power. The same
11401+ * precautions should be taken: fsck if you're not journalled.
11402+ */
11403+static int __init noresume2_setup(char *str)
11404+{
11405+ set_suspend_state(SUSPEND_NORESUME_SPECIFIED);
11406+ return 0;
11407+}
11408+
11409+static int __init suspend_retry_resume_setup(char *str)
11410+{
11411+ set_suspend_state(SUSPEND_RETRY_RESUME);
11412+ return 0;
11413+}
11414+
11415+#ifndef CONFIG_SOFTWARE_SUSPEND
11416+static int __init resume_setup(char *str)
11417+{
11418+ if (!*str)
11419+ return 0;
11420+
11421+ strncpy(resume2_file, str, 255);
11422+ return 0;
11423+}
11424+
11425+static int __init noresume_setup(char *str)
11426+{
11427+ set_suspend_state(SUSPEND_NORESUME_SPECIFIED);
11428+ return 0;
11429+}
11430+__setup("noresume", noresume_setup);
11431+__setup("resume=", resume_setup);
11432+#endif
11433+
11434+__setup("noresume2", noresume2_setup);
11435+__setup("resume2=", resume2_setup);
11436+__setup("suspend_retry_resume", suspend_retry_resume_setup);
11437+
11438+late_initcall(core_load);
11439+EXPORT_SYMBOL(suspend_state);
11440diff --git a/kernel/power/suspend.h b/kernel/power/suspend.h
11441new file mode 100644
11442index 0000000..7504a45
11443--- /dev/null
11444+++ b/kernel/power/suspend.h
11445@@ -0,0 +1,69 @@
11446+/*
11447+ * kernel/power/suspend.h
11448+ *
11449+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
11450+ * Copyright (C) 2006 Red Hat, inc.
11451+ *
11452+ * This file is released under the GPLv2.
11453+ *
11454+ * It contains declarations used throughout swsusp.
11455+ *
11456+ */
11457+
11458+#ifndef KERNEL_POWER_SUSPEND_H
11459+#define KERNEL_POWER_SUSPEND_H
11460+
11461+#include <linux/delay.h>
11462+#include <linux/bootmem.h>
11463+
11464+#define SUSPEND_CORE_VERSION "2.2.9"
11465+#define name_suspend "Suspend2 " SUSPEND_CORE_VERSION ": "
11466+
11467+extern __nosavedata struct pbe *restore_pblist;
11468+extern int save_image_part1(void);
11469+extern int suspend_atomic_restore(void);
11470+extern void suspend_main(int had_pmsem);
11471+
11472+extern unsigned long suspend_orig_mem_free;
11473+
11474+#define KB(x) ((x) << (PAGE_SHIFT - 10))
11475+#define MB(x) ((x) >> (20 - PAGE_SHIFT))
11476+
11477+extern int suspend_start_anything(int starting_cycle);
11478+extern void suspend_finish_anything(int finishing_cycle);
11479+
11480+//#ifdef CONFIG_PM_DEBUG
11481+#if 1
11482+#define set_debug_state(bit) (test_and_set_bit(bit, &suspend_debug_state))
11483+#define clear_debug_state(bit) (test_and_clear_bit(bit, &suspend_debug_state))
11484+#else
11485+#define set_debug_state(bit) (0)
11486+#define clear_debug_state(bit) (0)
11487+#endif
11488+
11489+#define set_result_state(bit) (test_and_set_bit(bit, &suspend_result))
11490+#define clear_result_state(bit) (test_and_clear_bit(bit, &suspend_result))
11491+
11492+enum {
11493+ SUSPEND_ABORTED,
11494+ SUSPEND_ABORT_REQUESTED,
11495+ SUSPEND_NOSTORAGE_AVAILABLE,
11496+ SUSPEND_INSUFFICIENT_STORAGE,
11497+ SUSPEND_FREEZING_FAILED,
11498+ SUSPEND_UNEXPECTED_ALLOC,
11499+ SUSPEND_KEPT_IMAGE,
11500+ SUSPEND_WOULD_EAT_MEMORY,
11501+ SUSPEND_UNABLE_TO_FREE_ENOUGH_MEMORY,
11502+ SUSPEND_ENCRYPTION_SETUP_FAILED,
11503+ SUSPEND_PM_SEM,
11504+ SUSPEND_DEVICE_REFUSED,
11505+ SUSPEND_EXTRA_PAGES_ALLOW_TOO_SMALL,
11506+};
11507+
11508+extern unsigned int nr_suspends;
11509+extern char resume2_file[256];
11510+
11511+extern void copyback_post(void);
11512+extern int suspend2_suspend(void);
11513+extern int extra_pd1_pages_used;
11514+#endif
11515diff --git a/kernel/power/suspend_block_io.c b/kernel/power/suspend_block_io.c
11516new file mode 100644
11517index 0000000..d8480d2
11518--- /dev/null
11519+++ b/kernel/power/suspend_block_io.c
11520@@ -0,0 +1,865 @@
11521+/*
11522+ * kernel/power/suspend_block_io.c
11523+ *
11524+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
11525+ * Copyright (C) 2006 Red Hat, inc.
11526+ *
11527+ * Distributed under GPLv2.
11528+ *
11529+ * This file contains block io functions for suspend2. These are
11530+ * used by the swapwriter and it is planned that they will also
11531+ * be used by the NFSwriter.
11532+ *
11533+ */
11534+
11535+#include <linux/blkdev.h>
11536+#include <linux/syscalls.h>
11537+#include <linux/suspend.h>
11538+
11539+#include "suspend.h"
11540+#include "sysfs.h"
11541+#include "modules.h"
11542+#include "prepare_image.h"
11543+#include "block_io.h"
11544+#include "ui.h"
11545+
11546+#define MAX_OUTSTANDING_IO 2048
11547+#define SUBMIT_BATCH_SIZE 64
11548+
11549+struct io_info {
11550+ struct bio *sys_struct;
11551+ sector_t first_block;
11552+ struct page *bio_page, *dest_page;
11553+ int rw, readahead_index;
11554+ struct block_device *dev;
11555+ struct list_head list;
11556+};
11557+
11558+static LIST_HEAD(ioinfo_ready_for_cleanup);
11559+static DEFINE_SPINLOCK(ioinfo_ready_lock);
11560+
11561+static LIST_HEAD(ioinfo_submit_batch);
11562+static DEFINE_SPINLOCK(ioinfo_submit_lock);
11563+
11564+static LIST_HEAD(ioinfo_busy);
11565+static DEFINE_SPINLOCK(ioinfo_busy_lock);
11566+
11567+static struct io_info *waiting_on;
11568+
11569+static atomic_t submit_batch;
11570+static int submit_batched(void);
11571+
11572+/* [Max] number of I/O operations pending */
11573+static atomic_t outstanding_io;
11574+static int max_outstanding_io = 0;
11575+
11576+static int extra_page_forward = 0;
11577+
11578+static volatile unsigned long suspend_readahead_flags[
11579+ DIV_ROUND_UP(MAX_OUTSTANDING_IO, BITS_PER_LONG)];
11580+static spinlock_t suspend_readahead_flags_lock = SPIN_LOCK_UNLOCKED;
11581+static struct page *suspend_readahead_pages[MAX_OUTSTANDING_IO];
11582+static int readahead_index, readahead_submit_index;
11583+
11584+static int current_stream;
11585+/* 0 = Header, 1 = Pageset1, 2 = Pageset2 */
11586+struct extent_iterate_saved_state suspend_writer_posn_save[3];
11587+
11588+/* Pointer to current entry being loaded/saved. */
11589+struct extent_iterate_state suspend_writer_posn;
11590+
11591+/* Not static, so that the allocators can setup and complete
11592+ * writing the header */
11593+char *suspend_writer_buffer;
11594+int suspend_writer_buffer_posn;
11595+
11596+int suspend_read_fd;
11597+
11598+#define SCH_NUM 6
11599+static unsigned long nr_schedule_calls[SCH_NUM];
11600+
11601+static char *sch_caller[] = {
11602+ "suspend_finish_all_io ",
11603+ "suspend_wait_on_readahead",
11604+ "submit ",
11605+ "get_io_info_struct ",
11606+ "start_one ",
11607+ "wait_on_one_page ",
11608+};
11609+
11610+static struct suspend_bdev_info *suspend_devinfo;
11611+
11612+int suspend_header_bytes_used = 0;
11613+
11614+/*
11615+ * suspend_reset_io_stats
11616+ *
11617+ * Description: Reset all our sanity-checking statistics.
11618+ */
11619+static void suspend_reset_io_stats(void)
11620+{
11621+ int i;
11622+
11623+ max_outstanding_io = 0;
11624+
11625+ for (i = 0; i < SCH_NUM; i++)
11626+ nr_schedule_calls[i] = 0;
11627+}
11628+
11629+/*
11630+ * suspend_check_io_stats
11631+ *
11632+ * Description: Check that our statistics look right and print
11633+ * any debugging info wanted.
11634+ */
11635+static void suspend_check_io_stats(void)
11636+{
11637+ int i;
11638+
11639+ BUG_ON(atomic_read(&outstanding_io));
11640+ BUG_ON(!list_empty(&ioinfo_submit_batch));
11641+ BUG_ON(!list_empty(&ioinfo_busy));
11642+ BUG_ON(!list_empty(&ioinfo_ready_for_cleanup));
11643+
11644+ suspend_message(SUSPEND_WRITER, SUSPEND_LOW, 0,
11645+ "Maximum outstanding_io was %d.\n",
11646+ max_outstanding_io);
11647+ for(i = 0; i < SCH_NUM; i++)
11648+ suspend_message(SUSPEND_WRITER, SUSPEND_MEDIUM, 0,
11649+ "Nr schedule calls %s: %lu.\n", sch_caller[i],
11650+ nr_schedule_calls[i]);
11651+}
11652+
11653+/*
11654+ * __suspend_bio_cleanup_one
11655+ *
11656+ * Description: Clean up after completing I/O on a page.
11657+ * Arguments: struct io_info: Data for I/O to be completed.
11658+ */
11659+static void __suspend_bio_cleanup_one(struct io_info *io_info)
11660+{
11661+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 0,
11662+ "Cleanup IO: [%p]\n", io_info);
11663+
11664+ if (io_info->rw == READ && io_info->readahead_index == -1) {
11665+ char *from, *to;
11666+ /*
11667+ * Copy the page we read into the buffer our caller provided.
11668+ */
11669+ to = (char *) kmap(io_info->dest_page);
11670+ from = (char *) kmap(io_info->bio_page);
11671+ memcpy(to, from, PAGE_SIZE);
11672+ kunmap(io_info->dest_page);
11673+ kunmap(io_info->bio_page);
11674+ }
11675+
11676+ if (io_info->rw == WRITE || io_info->readahead_index == -1) {
11677+ /* Sanity check */
11678+ if (page_count(io_info->bio_page) != 2)
11679+ printk(KERN_EMERG "Cleanup IO: Page count on page %p"
11680+ " is %d. Not good!\n",
11681+ io_info->bio_page,
11682+ page_count(io_info->bio_page));
11683+ put_page(io_info->bio_page);
11684+ __free_page(io_info->bio_page);
11685+ } else
11686+ put_page(io_info->bio_page);
11687+
11688+ bio_put(io_info->sys_struct);
11689+ io_info->sys_struct = NULL;
11690+}
11691+
11692+/* __suspend_io_cleanup
11693+ */
11694+
11695+static void suspend_bio_cleanup_one(void *data)
11696+{
11697+ struct io_info *io_info = (struct io_info *) data;
11698+ int readahead_index;
11699+ unsigned long flags;
11700+
11701+ readahead_index = io_info->readahead_index;
11702+ list_del_init(&io_info->list);
11703+ __suspend_bio_cleanup_one(io_info);
11704+
11705+ if (readahead_index > -1) {
11706+ int index = readahead_index/BITS_PER_LONG;
11707+ int bit = readahead_index - (index * BITS_PER_LONG);
11708+ spin_lock_irqsave(&suspend_readahead_flags_lock, flags);
11709+ set_bit(bit, &suspend_readahead_flags[index]);
11710+ spin_unlock_irqrestore(&suspend_readahead_flags_lock, flags);
11711+ }
11712+
11713+ if (waiting_on == io_info)
11714+ waiting_on = NULL;
11715+ kfree(io_info);
11716+ atomic_dec(&outstanding_io);
11717+}
11718+
11719+/* suspend_cleanup_some_completed_io
11720+ *
11721+ * NB: This is designed so that multiple callers can be in here simultaneously.
11722+ */
11723+
11724+static void suspend_cleanup_some_completed_io(void)
11725+{
11726+ int num_cleaned = 0;
11727+ struct io_info *first;
11728+ unsigned long flags;
11729+
11730+ spin_lock_irqsave(&ioinfo_ready_lock, flags);
11731+ while(!list_empty(&ioinfo_ready_for_cleanup)) {
11732+ first = list_entry(ioinfo_ready_for_cleanup.next,
11733+ struct io_info, list);
11734+
11735+ list_del_init(&first->list);
11736+
11737+ spin_unlock_irqrestore(&ioinfo_ready_lock, flags);
11738+ suspend_bio_cleanup_one((void *) first);
11739+ spin_lock_irqsave(&ioinfo_ready_lock, flags);
11740+
11741+ num_cleaned++;
11742+ if (num_cleaned == SUBMIT_BATCH_SIZE)
11743+ break;
11744+ }
11745+ spin_unlock_irqrestore(&ioinfo_ready_lock, flags);
11746+}
11747+
11748+/* do_bio_wait
11749+ *
11750+ * Actions taken when we want some I/O to get run.
11751+ *
11752+ * Submit any I/O that's batched up (if we're not already doing
11753+ * that, unplug queues, schedule and clean up whatever we can.
11754+ */
11755+static void do_bio_wait(int caller)
11756+{
11757+ int num_submitted = 0;
11758+
11759+ nr_schedule_calls[caller]++;
11760+
11761+ /* Don't want to wait on I/O we haven't submitted! */
11762+ num_submitted = submit_batched();
11763+
11764+ kblockd_flush();
11765+
11766+ io_schedule();
11767+
11768+ suspend_cleanup_some_completed_io();
11769+}
11770+
11771+/*
11772+ * suspend_finish_all_io
11773+ *
11774+ * Description: Finishes all IO and frees all IO info struct pages.
11775+ */
11776+static void suspend_finish_all_io(void)
11777+{
11778+ /* Wait for all I/O to complete. */
11779+ while (atomic_read(&outstanding_io))
11780+ do_bio_wait(0);
11781+}
11782+
11783+/*
11784+ * wait_on_readahead
11785+ *
11786+ * Wait until a particular readahead is ready.
11787+ */
11788+static void suspend_wait_on_readahead(int readahead_index)
11789+{
11790+ int index = readahead_index / BITS_PER_LONG;
11791+ int bit = readahead_index - index * BITS_PER_LONG;
11792+
11793+ /* read_ahead_index is the one we want to return */
11794+ while (!test_bit(bit, &suspend_readahead_flags[index]))
11795+ do_bio_wait(1);
11796+}
11797+
11798+/*
11799+ * readahead_done
11800+ *
11801+ * Returns whether the readahead requested is ready.
11802+ */
11803+
11804+static int suspend_readahead_ready(int readahead_index)
11805+{
11806+ int index = readahead_index / BITS_PER_LONG;
11807+ int bit = readahead_index - (index * BITS_PER_LONG);
11808+
11809+ return test_bit(bit, &suspend_readahead_flags[index]);
11810+}
11811+
11812+/* suspend_readahead_prepare
11813+ * Set up for doing readahead on an image */
11814+static int suspend_prepare_readahead(int index)
11815+{
11816+ unsigned long new_page = get_zeroed_page(GFP_ATOMIC);
11817+
11818+ if(!new_page)
11819+ return -ENOMEM;
11820+
11821+ suspend_readahead_pages[index] = virt_to_page(new_page);
11822+ return 0;
11823+}
11824+
11825+/* suspend_readahead_cleanup
11826+ * Clean up structures used for readahead */
11827+static void suspend_cleanup_readahead(int page)
11828+{
11829+ __free_page(suspend_readahead_pages[page]);
11830+ suspend_readahead_pages[page] = 0;
11831+ return;
11832+}
11833+
11834+/*
11835+ * suspend_end_bio
11836+ *
11837+ * Description: Function called by block driver from interrupt context when I/O
11838+ * is completed. This is the reason we use spinlocks in
11839+ * manipulating the io_info lists.
11840+ * Nearly the fs/buffer.c version, but we want to mark the page as
11841+ * done in our own structures too.
11842+ */
11843+
11844+static int suspend_end_bio(struct bio *bio, unsigned int num, int err)
11845+{
11846+ struct io_info *io_info = bio->bi_private;
11847+ unsigned long flags;
11848+
11849+ spin_lock_irqsave(&ioinfo_busy_lock, flags);
11850+ list_del_init(&io_info->list);
11851+ spin_unlock_irqrestore(&ioinfo_busy_lock, flags);
11852+
11853+ spin_lock_irqsave(&ioinfo_ready_lock, flags);
11854+ list_add_tail(&io_info->list, &ioinfo_ready_for_cleanup);
11855+ spin_unlock_irqrestore(&ioinfo_ready_lock, flags);
11856+ return 0;
11857+}
11858+
11859+/**
11860+ * submit - submit BIO request.
11861+ * @rw: READ or WRITE.
11862+ * @io_info: IO info structure.
11863+ *
11864+ * Based on Patrick's pmdisk code from long ago:
11865+ * "Straight from the textbook - allocate and initialize the bio.
11866+ * If we're writing, make sure the page is marked as dirty.
11867+ * Then submit it and carry on."
11868+ *
11869+ * With a twist, though - we handle block_size != PAGE_SIZE.
11870+ * Caller has already checked that our page is not fragmented.
11871+ */
11872+
11873+static int submit(struct io_info *io_info)
11874+{
11875+ struct bio *bio = NULL;
11876+ unsigned long flags;
11877+
11878+ while (!bio) {
11879+ bio = bio_alloc(GFP_ATOMIC,1);
11880+ if (!bio)
11881+ do_bio_wait(2);
11882+ }
11883+
11884+ bio->bi_bdev = io_info->dev;
11885+ bio->bi_sector = io_info->first_block;
11886+ bio->bi_private = io_info;
11887+ bio->bi_end_io = suspend_end_bio;
11888+ bio->bi_flags |= (1 << BIO_SUSPEND_DATA);
11889+ io_info->sys_struct = bio;
11890+
11891+ if (bio_add_page(bio, io_info->bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
11892+ printk("ERROR: adding page to bio at %lld\n",
11893+ (unsigned long long) io_info->first_block);
11894+ bio_put(bio);
11895+ return -EFAULT;
11896+ }
11897+
11898+ if (io_info->rw == WRITE)
11899+ bio_set_pages_dirty(bio);
11900+
11901+ spin_lock_irqsave(&ioinfo_busy_lock, flags);
11902+ list_add_tail(&io_info->list, &ioinfo_busy);
11903+ spin_unlock_irqrestore(&ioinfo_busy_lock, flags);
11904+
11905+ submit_bio(io_info->rw, bio);
11906+
11907+ return 0;
11908+}
11909+
11910+/*
11911+ * submit a batch. The submit function can wait on I/O, so we have
11912+ * simple locking to avoid infinite recursion.
11913+ */
11914+static int submit_batched(void)
11915+{
11916+ static int running_already = 0;
11917+ struct io_info *first;
11918+ unsigned long flags;
11919+ int num_submitted = 0;
11920+
11921+ if (running_already)
11922+ return 0;
11923+
11924+ running_already = 1;
11925+ spin_lock_irqsave(&ioinfo_submit_lock, flags);
11926+ while(!list_empty(&ioinfo_submit_batch)) {
11927+ first = list_entry(ioinfo_submit_batch.next, struct io_info,
11928+ list);
11929+ list_del_init(&first->list);
11930+ atomic_dec(&submit_batch);
11931+ spin_unlock_irqrestore(&ioinfo_submit_lock, flags);
11932+ submit(first);
11933+ spin_lock_irqsave(&ioinfo_submit_lock, flags);
11934+ num_submitted++;
11935+ if (num_submitted == SUBMIT_BATCH_SIZE)
11936+ break;
11937+ }
11938+ spin_unlock_irqrestore(&ioinfo_submit_lock, flags);
11939+ running_already = 0;
11940+
11941+ return num_submitted;
11942+}
11943+
11944+static void add_to_batch(struct io_info *io_info)
11945+{
11946+ unsigned long flags;
11947+ int waiting;
11948+
11949+ /* Put our prepared I/O struct on the batch list. */
11950+ spin_lock_irqsave(&ioinfo_submit_lock, flags);
11951+ list_add_tail(&io_info->list, &ioinfo_submit_batch);
11952+ waiting = atomic_add_return(1, &submit_batch);
11953+ spin_unlock_irqrestore(&ioinfo_submit_lock, flags);
11954+
11955+ if (waiting >= SUBMIT_BATCH_SIZE)
11956+ submit_batched();
11957+}
11958+
11959+/*
11960+ * get_io_info_struct
11961+ *
11962+ * Description: Get an I/O struct.
11963+ * Returns: Pointer to the struct prepared for use.
11964+ */
11965+static struct io_info *get_io_info_struct(void)
11966+{
11967+ struct io_info *this = NULL;
11968+
11969+ do {
11970+ while (atomic_read(&outstanding_io) >= MAX_OUTSTANDING_IO)
11971+ do_bio_wait(3);
11972+
11973+ this = kmalloc(sizeof(struct io_info), GFP_ATOMIC);
11974+ } while (!this);
11975+
11976+ INIT_LIST_HEAD(&this->list);
11977+ return this;
11978+}
11979+
11980+/*
11981+ * suspend_do_io
11982+ *
11983+ * Description: Prepare and start a read or write operation.
11984+ * Note that we use our own buffer for reading or writing.
11985+ * This simplifies doing readahead and asynchronous writing.
11986+ * We can begin a read without knowing the location into which
11987+ * the data will eventually be placed, and the buffer passed
11988+ * for a write can be reused immediately (essential for the
11989+ * modules system).
11990+ * Failure? What's that?
11991+ * Returns: The io_info struct created.
11992+ */
11993+static int suspend_do_io(int rw, struct block_device *bdev, long block0,
11994+ struct page *page, int readahead_index, int syncio)
11995+{
11996+ struct io_info *io_info;
11997+ unsigned long buffer_virt = 0;
11998+ char *to, *from;
11999+
12000+ BUG_ON(!bdev);
12001+
12002+ io_info = get_io_info_struct();
12003+
12004+ /* Done before submitting to avoid races. */
12005+ if (syncio)
12006+ waiting_on = io_info;
12007+
12008+ /* Get our local buffer */
12009+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 1,
12010+ "Start_IO: [%p]", io_info);
12011+
12012+ /* Copy settings to the io_info struct */
12013+ io_info->rw = rw;
12014+ io_info->dev = bdev;
12015+ io_info->first_block = block0;
12016+ io_info->dest_page = page;
12017+ io_info->readahead_index = readahead_index;
12018+
12019+ if (io_info->readahead_index == -1) {
12020+ while (!(buffer_virt = get_zeroed_page(GFP_ATOMIC)))
12021+ do_bio_wait(4);
12022+
12023+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 0,
12024+ "[ALLOC BUFFER]->%d",
12025+ real_nr_free_pages());
12026+ io_info->bio_page = virt_to_page(buffer_virt);
12027+ } else {
12028+ unsigned long flags;
12029+ int index = io_info->readahead_index / BITS_PER_LONG;
12030+ int bit = io_info->readahead_index - index * BITS_PER_LONG;
12031+
12032+ spin_lock_irqsave(&suspend_readahead_flags_lock, flags);
12033+ clear_bit(bit, &suspend_readahead_flags[index]);
12034+ spin_unlock_irqrestore(&suspend_readahead_flags_lock, flags);
12035+
12036+ io_info->bio_page = page;
12037+ }
12038+
12039+ /* If writing, copy our data. The data is probably in
12040+ * lowmem, but we cannot be certain. If there is no
12041+ * compression/encryption, we might be passed the
12042+ * actual source page's address. */
12043+ if (rw == WRITE) {
12044+ to = (char *) buffer_virt;
12045+ from = kmap_atomic(io_info->dest_page, KM_USER1);
12046+ memcpy(to, from, PAGE_SIZE);
12047+ kunmap_atomic(from, KM_USER1);
12048+ }
12049+
12050+ /* Submit the page */
12051+ get_page(io_info->bio_page);
12052+
12053+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 1,
12054+ "-> (PRE BRW) %d\n", real_nr_free_pages());
12055+
12056+ if (syncio)
12057+ submit(io_info);
12058+ else
12059+ add_to_batch(io_info);
12060+
12061+ atomic_inc(&outstanding_io);
12062+
12063+ /* No locking because doesn't matter if !perfectly accurate -
12064+ * just for user interest/tuning. */
12065+ if (atomic_read(&outstanding_io) > max_outstanding_io)
12066+ max_outstanding_io++;
12067+
12068+ if (syncio)
12069+ do { do_bio_wait(5); } while (waiting_on);
12070+
12071+ return 0;
12072+}
12073+
12074+/* We used to use bread here, but it doesn't correctly handle
12075+ * blocksize != PAGE_SIZE. Now we create a submit_info to get the data we
12076+ * want and use our normal routines (synchronously).
12077+ */
12078+
12079+static int suspend_bdev_page_io(int rw, struct block_device *bdev, long pos,
12080+ struct page *page)
12081+{
12082+ return suspend_do_io(rw, bdev, pos, page, -1, 1);
12083+}
12084+
12085+static int suspend_bio_memory_needed(void)
12086+{
12087+ /* We want to have at least enough memory so as to have
12088+ * MAX_OUTSTANDING_IO transactions on the fly at once. If we
12089+ * can do more, fine. */
12090+ return (MAX_OUTSTANDING_IO * (PAGE_SIZE + sizeof(struct request) +
12091+ sizeof(struct bio) + sizeof(struct io_info)));
12092+}
12093+
12094+static void suspend_set_devinfo(struct suspend_bdev_info *info)
12095+{
12096+ suspend_devinfo = info;
12097+}
12098+
12099+static int forward_extra_blocks(void)
12100+{
12101+ int i;
12102+
12103+ for (i = 1; i < suspend_devinfo[suspend_writer_posn.current_chain].
12104+ blocks_per_page; i++)
12105+ suspend_extent_state_next(&suspend_writer_posn);
12106+
12107+ if (suspend_extent_state_eof(&suspend_writer_posn)) {
12108+ printk("Extent state eof.\n");
12109+ return -ENODATA;
12110+ }
12111+
12112+ return 0;
12113+}
12114+
12115+static int forward_one_page(void)
12116+{
12117+ int at_start = (suspend_writer_posn.current_chain == -1);
12118+
12119+ /* Have to go forward one to ensure we're on the right chain,
12120+ * before we can know how many more blocks to skip.*/
12121+ suspend_extent_state_next(&suspend_writer_posn);
12122+
12123+ if (!at_start)
12124+ if (forward_extra_blocks())
12125+ return -ENODATA;
12126+
12127+ if (extra_page_forward) {
12128+ extra_page_forward = 0;
12129+ return forward_one_page();
12130+ }
12131+
12132+ return 0;
12133+}
12134+
12135+/* Used in reading header, to jump to 2nd page after getting 1st page
12136+ * direct from image header. */
12137+static void set_extra_page_forward(void)
12138+{
12139+ extra_page_forward = 1;
12140+}
12141+
12142+static int suspend_rw_page(int rw, struct page *page,
12143+ int readahead_index, int sync)
12144+{
12145+ struct suspend_bdev_info *dev_info;
12146+
12147+ if (test_action_state(SUSPEND_TEST_FILTER_SPEED))
12148+ return 0;
12149+
12150+ if (forward_one_page()) {
12151+ printk("Failed to advance a page in the extent data.\n");
12152+ return -ENODATA;
12153+ }
12154+
12155+ dev_info = &suspend_devinfo[suspend_writer_posn.current_chain];
12156+
12157+ return suspend_do_io(rw, dev_info->bdev,
12158+ suspend_writer_posn.current_offset <<
12159+ dev_info->bmap_shift,
12160+ page, readahead_index, sync);
12161+}
12162+
12163+static int suspend_bio_read_chunk(struct page *buffer_page, int sync)
12164+{
12165+ static int last_result;
12166+ unsigned long *virt;
12167+
12168+ if (sync == SUSPEND_ASYNC)
12169+ return suspend_rw_page(READ, buffer_page, -1, sync);
12170+
12171+ /* Start new readahead while we wait for our page */
12172+ if (readahead_index == -1) {
12173+ last_result = 0;
12174+ readahead_index = readahead_submit_index = 0;
12175+ }
12176+
12177+ /* Start a new readahead? */
12178+ if (last_result) {
12179+ /* We failed to submit a read, and have cleaned up
12180+ * all the readahead previously submitted */
12181+ if (readahead_submit_index == readahead_index)
12182+ return -EPERM;
12183+ goto wait;
12184+ }
12185+
12186+ do {
12187+ if (suspend_prepare_readahead(readahead_submit_index))
12188+ break;
12189+
12190+ last_result = suspend_rw_page(READ,
12191+ suspend_readahead_pages[readahead_submit_index],
12192+ readahead_submit_index, SUSPEND_ASYNC);
12193+ if (last_result) {
12194+ printk("Begin read chunk for page %d returned %d.\n",
12195+ readahead_submit_index, last_result);
12196+ suspend_cleanup_readahead(readahead_submit_index);
12197+ break;
12198+ }
12199+
12200+ readahead_submit_index++;
12201+
12202+ if (readahead_submit_index == MAX_OUTSTANDING_IO)
12203+ readahead_submit_index = 0;
12204+
12205+ } while((!last_result) && (readahead_submit_index != readahead_index) &&
12206+ (!suspend_readahead_ready(readahead_index)));
12207+
12208+wait:
12209+ suspend_wait_on_readahead(readahead_index);
12210+
12211+ virt = kmap_atomic(buffer_page, KM_USER1);
12212+ memcpy(virt, page_address(suspend_readahead_pages[readahead_index]),
12213+ PAGE_SIZE);
12214+ kunmap_atomic(virt, KM_USER1);
12215+
12216+ suspend_cleanup_readahead(readahead_index);
12217+
12218+ readahead_index++;
12219+ if (readahead_index == MAX_OUTSTANDING_IO)
12220+ readahead_index = 0;
12221+
12222+ return 0;
12223+}
12224+
12225+static int suspend_rw_init(int rw, int stream_number)
12226+{
12227+ suspend_extent_state_restore(&suspend_writer_posn,
12228+ &suspend_writer_posn_save[stream_number]);
12229+ current_stream = stream_number;
12230+
12231+ BUG_ON(!suspend_writer_posn.current_extent);
12232+
12233+ suspend_reset_io_stats();
12234+
12235+ readahead_index = readahead_submit_index = -1;
12236+
12237+ return 0;
12238+}
12239+
12240+static int suspend_rw_cleanup(int rw)
12241+{
12242+ if (rw == WRITE && current_stream == 2)
12243+ suspend_extent_state_save(&suspend_writer_posn,
12244+ &suspend_writer_posn_save[1]);
12245+
12246+ suspend_finish_all_io();
12247+
12248+ if (rw == READ)
12249+ while (readahead_index != readahead_submit_index) {
12250+ suspend_cleanup_readahead(readahead_index);
12251+ readahead_index++;
12252+ if (readahead_index == MAX_OUTSTANDING_IO)
12253+ readahead_index = 0;
12254+ }
12255+
12256+ suspend_check_io_stats();
12257+
12258+ return 0;
12259+}
12260+
12261+static int suspend_write_chunk(struct page *buffer_page)
12262+{
12263+ return suspend_rw_page(WRITE, buffer_page, -1, 0);
12264+}
12265+
12266+static int suspend_rw_header_chunk(int rw, struct suspend_module_ops *owner,
12267+ char *buffer, int buffer_size)
12268+{
12269+ int bytes_left = buffer_size;
12270+
12271+ if (owner) {
12272+ owner->header_used += buffer_size;
12273+ if (owner->header_used > owner->header_requested) {
12274+ printk(KERN_EMERG "Suspend2 module %s is using more"
12275+ "header space (%u) than it requested (%u).\n",
12276+ owner->name,
12277+ owner->header_used,
12278+ owner->header_requested);
12279+ BUG();
12280+ }
12281+ }
12282+
12283+ /* Read a chunk of the header */
12284+ while (bytes_left) {
12285+ char *source_start = buffer + buffer_size - bytes_left;
12286+ char *dest_start = suspend_writer_buffer + suspend_writer_buffer_posn;
12287+ int capacity = PAGE_SIZE - suspend_writer_buffer_posn;
12288+ char *to = rw ? dest_start : source_start;
12289+ char *from = rw ? source_start : dest_start;
12290+
12291+ if (bytes_left <= capacity) {
12292+ if (test_debug_state(SUSPEND_HEADER))
12293+ printk("Copy %d bytes %d-%d from %p to %p.\n",
12294+ bytes_left,
12295+ suspend_header_bytes_used,
12296+ suspend_header_bytes_used + bytes_left,
12297+ from, to);
12298+ memcpy(to, from, bytes_left);
12299+ suspend_writer_buffer_posn += bytes_left;
12300+ suspend_header_bytes_used += bytes_left;
12301+ return rw ? 0 : buffer_size;
12302+ }
12303+
12304+ /* Next to read the next page */
12305+ if (test_debug_state(SUSPEND_HEADER))
12306+ printk("Copy %d bytes (%d-%d) from %p to %p.\n",
12307+ capacity,
12308+ suspend_header_bytes_used,
12309+ suspend_header_bytes_used + capacity,
12310+ from, to);
12311+ memcpy(to, from, capacity);
12312+ bytes_left -= capacity;
12313+ suspend_header_bytes_used += capacity;
12314+
12315+ if (rw == READ && test_suspend_state(SUSPEND_TRY_RESUME_RD))
12316+ sys_read(suspend_read_fd,
12317+ suspend_writer_buffer, BLOCK_SIZE);
12318+ else {
12319+ if (suspend_rw_page(rw,
12320+ virt_to_page(suspend_writer_buffer),
12321+ -1, !rw))
12322+ return -EIO;
12323+ }
12324+
12325+ suspend_writer_buffer_posn = 0;
12326+ suspend_cond_pause(0, NULL);
12327+ }
12328+
12329+ return rw ? 0 : buffer_size;
12330+}
12331+
12332+static int write_header_chunk_finish(void)
12333+{
12334+ return suspend_rw_page(WRITE,
12335+ virt_to_page(suspend_writer_buffer),
12336+ -1, 0) ? -EIO : 0;
12337+}
12338+
12339+struct suspend_bio_ops suspend_bio_ops = {
12340+ .bdev_page_io = suspend_bdev_page_io,
12341+ .check_io_stats = suspend_check_io_stats,
12342+ .reset_io_stats = suspend_reset_io_stats,
12343+ .finish_all_io = suspend_finish_all_io,
12344+ .prepare_readahead = suspend_prepare_readahead,
12345+ .cleanup_readahead = suspend_cleanup_readahead,
12346+ .readahead_pages = suspend_readahead_pages,
12347+ .readahead_ready = suspend_readahead_ready,
12348+ .forward_one_page = forward_one_page,
12349+ .set_extra_page_forward = set_extra_page_forward,
12350+ .set_devinfo = suspend_set_devinfo,
12351+ .read_chunk = suspend_bio_read_chunk,
12352+ .write_chunk = suspend_write_chunk,
12353+ .rw_init = suspend_rw_init,
12354+ .rw_cleanup = suspend_rw_cleanup,
12355+ .rw_header_chunk = suspend_rw_header_chunk,
12356+ .write_header_chunk_finish = write_header_chunk_finish,
12357+};
12358+
12359+static struct suspend_module_ops suspend_blockwriter_ops =
12360+{
12361+ .name = "Block I/O",
12362+ .type = MISC_MODULE,
12363+ .module = THIS_MODULE,
12364+ .memory_needed = suspend_bio_memory_needed,
12365+};
12366+
12367+static __init int suspend_block_io_load(void)
12368+{
12369+ return suspend_register_module(&suspend_blockwriter_ops);
12370+}
12371+
12372+#ifdef MODULE
12373+static __exit void suspend_block_io_unload(void)
12374+{
12375+ suspend_unregister_module(&suspend_blockwriter_ops);
12376+}
12377+
12378+module_init(suspend_block_io_load);
12379+module_exit(suspend_block_io_unload);
12380+MODULE_LICENSE("GPL");
12381+MODULE_AUTHOR("Nigel Cunningham");
12382+MODULE_DESCRIPTION("Suspend2 block io functions");
12383+#else
12384+late_initcall(suspend_block_io_load);
12385+#endif
12386diff --git a/kernel/power/suspend_file.c b/kernel/power/suspend_file.c
12387new file mode 100644
12388index 0000000..cf5bede
12389--- /dev/null
12390+++ b/kernel/power/suspend_file.c
12391@@ -0,0 +1,1108 @@
12392+/*
12393+ * kernel/power/suspend_file.c
12394+ *
12395+ * Copyright 2005-2006 Nigel Cunningham <nigel@suspend2.net>
12396+ * Copyright (C) 2006 Red Hat, inc.
12397+ *
12398+ * Distributed under GPLv2.
12399+ *
12400+ * This file encapsulates functions for usage of a simple file as a
12401+ * backing store. It is based upon the swapallocator, and shares the
12402+ * same basic working. Here, though, we have nothing to do with
12403+ * swapspace, and only one device to worry about.
12404+ *
12405+ * The user can just
12406+ *
12407+ * echo Suspend2 > /path/to/my_file
12408+ *
12409+ * and
12410+ *
12411+ * echo /path/to/my_file > /sys/power/suspend2/suspend_file/target
12412+ *
12413+ * then put what they find in /sys/power/suspend2/resume2
12414+ * as their resume2= parameter in lilo.conf (and rerun lilo if using it).
12415+ *
12416+ * Having done this, they're ready to suspend and resume.
12417+ *
12418+ * TODO:
12419+ * - File resizing.
12420+ */
12421+
12422+#include <linux/suspend.h>
12423+#include <linux/module.h>
12424+#include <linux/blkdev.h>
12425+#include <linux/file.h>
12426+#include <linux/stat.h>
12427+#include <linux/mount.h>
12428+#include <linux/statfs.h>
12429+#include <linux/syscalls.h>
12430+#include <linux/namei.h>
12431+#include <linux/fs.h>
12432+
12433+#include "suspend.h"
12434+#include "sysfs.h"
12435+#include "modules.h"
12436+#include "ui.h"
12437+#include "extent.h"
12438+#include "io.h"
12439+#include "storage.h"
12440+#include "block_io.h"
12441+
12442+static struct suspend_module_ops suspend_fileops;
12443+
12444+/* Details of our target. */
12445+
12446+char suspend_file_target[256];
12447+static struct inode *target_inode;
12448+static struct file *target_file;
12449+static struct block_device *suspend_file_target_bdev;
12450+static dev_t resume_dev_t;
12451+static int used_devt = 0;
12452+static int setting_suspend_file_target = 0;
12453+static sector_t target_firstblock = 0, target_header_start = 0;
12454+static int target_storage_available = 0;
12455+static int target_claim = 0;
12456+
12457+static char HaveImage[] = "HaveImage\n";
12458+static char NoImage[] = "Suspend2\n";
12459+#define sig_size (sizeof(HaveImage) + 1)
12460+
12461+struct suspend_file_header {
12462+ char sig[sig_size];
12463+ int resumed_before;
12464+ unsigned long first_header_block;
12465+};
12466+
12467+extern dev_t ROOT_DEV;
12468+extern char *__initdata root_device_name;
12469+
12470+/* Header_pages must be big enough for signature */
12471+static int header_pages, main_pages;
12472+
12473+#define target_is_normal_file() (S_ISREG(target_inode->i_mode))
12474+
12475+static struct suspend_bdev_info devinfo;
12476+
12477+/* Extent chain for blocks */
12478+static struct extent_chain block_chain;
12479+
12480+/* Signature operations */
12481+enum {
12482+ GET_IMAGE_EXISTS,
12483+ INVALIDATE,
12484+ MARK_RESUME_ATTEMPTED,
12485+};
12486+
12487+static void set_devinfo(struct block_device *bdev, int target_blkbits)
12488+{
12489+ devinfo.bdev = bdev;
12490+ if (!target_blkbits) {
12491+ devinfo.bmap_shift = devinfo.blocks_per_page = 0;
12492+ } else {
12493+ devinfo.bmap_shift = target_blkbits - 9;
12494+ devinfo.blocks_per_page = (1 << (PAGE_SHIFT - target_blkbits));
12495+ }
12496+}
12497+
12498+static int suspend_file_storage_available(void)
12499+{
12500+ int result = 0;
12501+ struct block_device *bdev=suspend_file_target_bdev;
12502+
12503+ if (!target_inode)
12504+ return 0;
12505+
12506+ switch (target_inode->i_mode & S_IFMT) {
12507+ case S_IFSOCK:
12508+ case S_IFCHR:
12509+ case S_IFIFO: /* Socket, Char, Fifo */
12510+ return -1;
12511+ case S_IFREG: /* Regular file: current size - holes + free
12512+ space on part */
12513+ result = target_storage_available;
12514+ break;
12515+ case S_IFBLK: /* Block device */
12516+ if (!bdev->bd_disk) {
12517+ printk("bdev->bd_disk null.\n");
12518+ return 0;
12519+ }
12520+
12521+ result = (bdev->bd_part ?
12522+ bdev->bd_part->nr_sects :
12523+ bdev->bd_disk->capacity) >> (PAGE_SHIFT - 9);
12524+ }
12525+
12526+ return result;
12527+}
12528+
12529+static int has_contiguous_blocks(int page_num)
12530+{
12531+ int j;
12532+ sector_t last = 0;
12533+
12534+ for (j = 0; j < devinfo.blocks_per_page; j++) {
12535+ sector_t this = bmap(target_inode,
12536+ page_num * devinfo.blocks_per_page + j);
12537+
12538+ if (!this || (last && (last + 1) != this))
12539+ break;
12540+
12541+ last = this;
12542+ }
12543+
12544+ return (j == devinfo.blocks_per_page);
12545+}
12546+
12547+static int size_ignoring_ignored_pages(void)
12548+{
12549+ int mappable = 0, i;
12550+
12551+ if (target_is_normal_file()) {
12552+ for (i = 0; i < (target_inode->i_size >> PAGE_SHIFT) ; i++)
12553+ if (has_contiguous_blocks(i))
12554+ mappable++;
12555+
12556+ return mappable;
12557+ } else
12558+ return suspend_file_storage_available();
12559+}
12560+
12561+static void __populate_block_list(int min, int max)
12562+{
12563+ if (test_action_state(SUSPEND_TEST_BIO))
12564+ printk("Adding extent %d-%d.\n", min << devinfo.bmap_shift,
12565+ ((max + 1) << devinfo.bmap_shift) - 1);
12566+
12567+ suspend_add_to_extent_chain(&block_chain, min, max);
12568+}
12569+
12570+static void populate_block_list(void)
12571+{
12572+ int i;
12573+
12574+ if (block_chain.first)
12575+ suspend_put_extent_chain(&block_chain);
12576+
12577+ if (target_is_normal_file()) {
12578+ int extent_min = -1, extent_max = -1, got_header = 0;
12579+
12580+ for (i = 0;
12581+ i < (target_inode->i_size >> PAGE_SHIFT);
12582+ i++) {
12583+ sector_t new_sector;
12584+
12585+ if (!has_contiguous_blocks(i))
12586+ continue;
12587+
12588+ new_sector = bmap(target_inode,
12589+ (i * devinfo.blocks_per_page));
12590+
12591+ /*
12592+ * Ignore the first block in the file.
12593+ * It gets the header.
12594+ */
12595+ if (new_sector == target_firstblock >> devinfo.bmap_shift) {
12596+ got_header = 1;
12597+ continue;
12598+ }
12599+
12600+ /*
12601+ * I'd love to be able to fill in holes and resize
12602+ * files, but not yet...
12603+ */
12604+
12605+ if (new_sector == extent_max + 1)
12606+ extent_max+= devinfo.blocks_per_page;
12607+ else {
12608+ if (extent_min > -1)
12609+ __populate_block_list(extent_min,
12610+ extent_max);
12611+
12612+ extent_min = new_sector;
12613+ extent_max = extent_min +
12614+ devinfo.blocks_per_page - 1;
12615+ }
12616+ }
12617+ if (extent_min > -1)
12618+ __populate_block_list(extent_min, extent_max);
12619+
12620+ BUG_ON(!got_header);
12621+ } else
12622+ if (target_storage_available > 0)
12623+ __populate_block_list(devinfo.blocks_per_page,
12624+ (min(main_pages, target_storage_available) + 1) *
12625+ devinfo.blocks_per_page - 1);
12626+}
12627+
12628+static void suspend_file_cleanup(int finishing_cycle)
12629+{
12630+ if (suspend_file_target_bdev) {
12631+ if (target_claim) {
12632+ bd_release(suspend_file_target_bdev);
12633+ target_claim = 0;
12634+ }
12635+
12636+ if (used_devt) {
12637+ blkdev_put(suspend_file_target_bdev);
12638+ used_devt = 0;
12639+ }
12640+ suspend_file_target_bdev = NULL;
12641+ target_inode = NULL;
12642+ set_devinfo(NULL, 0);
12643+ target_storage_available = 0;
12644+ }
12645+
12646+ if (target_file > 0) {
12647+ filp_close(target_file, NULL);
12648+ target_file = NULL;
12649+ }
12650+}
12651+
12652+/*
12653+ * reopen_resume_devt
12654+ *
12655+ * Having opened resume2= once, we remember the major and
12656+ * minor nodes and use them to reopen the bdev for checking
12657+ * whether an image exists (possibly when starting a resume).
12658+ */
12659+static void reopen_resume_devt(void)
12660+{
12661+ suspend_file_target_bdev = open_by_devnum(resume_dev_t, FMODE_READ);
12662+ if (IS_ERR(suspend_file_target_bdev)) {
12663+ printk("Got a dev_num (%lx) but failed to open it.\n",
12664+ (unsigned long) resume_dev_t);
12665+ return;
12666+ }
12667+ target_inode = suspend_file_target_bdev->bd_inode;
12668+ set_devinfo(suspend_file_target_bdev, target_inode->i_blkbits);
12669+}
12670+
12671+static void suspend_file_get_target_info(char *target, int get_size,
12672+ int resume2)
12673+{
12674+ if (target_file)
12675+ suspend_file_cleanup(0);
12676+
12677+ if (!target || !strlen(target))
12678+ return;
12679+
12680+ target_file = filp_open(target, O_RDWR, 0);
12681+
12682+ if (IS_ERR(target_file) || !target_file) {
12683+
12684+ if (!resume2) {
12685+ printk("Open file %s returned %p.\n",
12686+ target, target_file);
12687+ target_file = NULL;
12688+ return;
12689+ }
12690+
12691+ target_file = NULL;
12692+ resume_dev_t = name_to_dev_t(target);
12693+ if (!resume_dev_t) {
12694+ printk("Open file %s returned %p and name_to_devt "
12695+ "failed.\n",
12696+ target, target_file);
12697+ if (!resume_dev_t) {
12698+ struct kstat stat;
12699+ int error = vfs_stat(target, &stat);
12700+ if (error) {
12701+ printk("Stating the file also failed."
12702+ " Nothing more we can do.\n");
12703+ return;
12704+ }
12705+ resume_dev_t = stat.rdev;
12706+ }
12707+ return;
12708+ }
12709+ suspend_file_target_bdev = open_by_devnum(resume_dev_t, FMODE_READ);
12710+ if (IS_ERR(suspend_file_target_bdev)) {
12711+ printk("Got a dev_num (%lx) but failed to open it.\n",
12712+ (unsigned long) resume_dev_t);
12713+ return;
12714+ }
12715+ used_devt = 1;
12716+ target_inode = suspend_file_target_bdev->bd_inode;
12717+ } else
12718+ target_inode = target_file->f_mapping->host;
12719+
12720+ if (S_ISLNK(target_inode->i_mode) ||
12721+ S_ISDIR(target_inode->i_mode) ||
12722+ S_ISSOCK(target_inode->i_mode) ||
12723+ S_ISFIFO(target_inode->i_mode)) {
12724+ printk("The suspend_file works with regular files, character "
12725+ "files and block devices.\n");
12726+ goto cleanup;
12727+ }
12728+
12729+ if (!used_devt) {
12730+ if (S_ISBLK(target_inode->i_mode)) {
12731+ suspend_file_target_bdev = I_BDEV(target_inode);
12732+ if (!bd_claim(suspend_file_target_bdev, &suspend_fileops))
12733+ target_claim = 1;
12734+ } else
12735+ suspend_file_target_bdev = target_inode->i_sb->s_bdev;
12736+ resume_dev_t = suspend_file_target_bdev->bd_dev;
12737+ }
12738+
12739+ set_devinfo(suspend_file_target_bdev, target_inode->i_blkbits);
12740+
12741+ if (get_size)
12742+ target_storage_available = size_ignoring_ignored_pages();
12743+
12744+ if (!resume2)
12745+ target_firstblock = bmap(target_inode, 0) << devinfo.bmap_shift;
12746+
12747+ return;
12748+cleanup:
12749+ target_inode = NULL;
12750+ if (target_file) {
12751+ filp_close(target_file, NULL);
12752+ target_file = NULL;
12753+ }
12754+ set_devinfo(NULL, 0);
12755+ target_storage_available = 0;
12756+}
12757+
12758+static int parse_signature(struct suspend_file_header *header)
12759+{
12760+ int have_image = !memcmp(HaveImage, header->sig, sizeof(HaveImage) - 1);
12761+ int no_image_header = !memcmp(NoImage, header->sig, sizeof(NoImage) - 1);
12762+
12763+ if (no_image_header)
12764+ return 0;
12765+
12766+ if (!have_image)
12767+ return -1;
12768+
12769+ if (header->resumed_before)
12770+ set_suspend_state(SUSPEND_RESUMED_BEFORE);
12771+ else
12772+ clear_suspend_state(SUSPEND_RESUMED_BEFORE);
12773+
12774+ target_header_start = header->first_header_block;
12775+ return 1;
12776+}
12777+
12778+/* prepare_signature */
12779+
12780+static int prepare_signature(struct suspend_file_header *current_header,
12781+ unsigned long first_header_block)
12782+{
12783+ strncpy(current_header->sig, HaveImage, sizeof(HaveImage));
12784+ current_header->resumed_before = 0;
12785+ current_header->first_header_block = first_header_block;
12786+ return 0;
12787+}
12788+
12789+static int suspend_file_storage_allocated(void)
12790+{
12791+ int result;
12792+
12793+ if (!target_inode)
12794+ return 0;
12795+
12796+ if (target_is_normal_file()) {
12797+ result = (int) target_storage_available;
12798+ } else
12799+ result = header_pages + main_pages;
12800+
12801+ return result;
12802+}
12803+
12804+static int suspend_file_release_storage(void)
12805+{
12806+ if ((test_action_state(SUSPEND_KEEP_IMAGE)) &&
12807+ test_suspend_state(SUSPEND_NOW_RESUMING))
12808+ return 0;
12809+
12810+ suspend_put_extent_chain(&block_chain);
12811+
12812+ header_pages = main_pages = 0;
12813+ return 0;
12814+}
12815+
12816+static int suspend_file_allocate_header_space(int space_requested)
12817+{
12818+ int i;
12819+
12820+ if (!block_chain.first)
12821+ return 0;
12822+
12823+ suspend_extent_state_goto_start(&suspend_writer_posn);
12824+ suspend_bio_ops.forward_one_page(); /* To first page */
12825+
12826+ for (i = 0; i < space_requested; i++)
12827+ if (suspend_bio_ops.forward_one_page())
12828+ return -ENOSPC;
12829+
12830+ /* The end of header pages will be the start of pageset 2 */
12831+ suspend_extent_state_save(&suspend_writer_posn,
12832+ &suspend_writer_posn_save[2]);
12833+ header_pages = space_requested;
12834+ return 0;
12835+}
12836+
12837+static int suspend_file_allocate_storage(int space_requested)
12838+{
12839+ int result = 0, prev_header_pages;
12840+ int blocks_to_get = (space_requested << devinfo.bmap_shift) -
12841+ block_chain.size;
12842+
12843+ /* Only release_storage reduces the size */
12844+ if (blocks_to_get < 1)
12845+ return 0;
12846+
12847+ main_pages = space_requested;
12848+
12849+ populate_block_list();
12850+
12851+ suspend_message(SUSPEND_WRITER, SUSPEND_MEDIUM, 0,
12852+ "Finished with block_chain.size == %d.\n",
12853+ block_chain.size);
12854+
12855+ if (block_chain.size < (header_pages + main_pages)) {
12856+ printk("Block chain size (%d) < header pages (%d) + main pages (%d) (=%d).\n",
12857+ block_chain.size,
12858+ header_pages, main_pages,
12859+ header_pages + main_pages);
12860+ result = -ENOSPC;
12861+ }
12862+
12863+ prev_header_pages = header_pages;
12864+ header_pages = 0;
12865+ suspend_file_allocate_header_space(prev_header_pages);
12866+ return result;
12867+}
12868+
12869+static int suspend_file_write_header_init(void)
12870+{
12871+ suspend_extent_state_goto_start(&suspend_writer_posn);
12872+
12873+ suspend_writer_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
12874+ suspend_writer_buffer_posn = suspend_header_bytes_used = 0;
12875+
12876+ /* Info needed to bootstrap goes at the start of the header.
12877+ * First we save the basic info needed for reading, including the number
12878+ * of header pages. Then we save the structs containing data needed
12879+ * for reading the header pages back.
12880+ * Note that even if header pages take more than one page, when we
12881+ * read back the info, we will have restored the location of the
12882+ * next header page by the time we go to use it.
12883+ */
12884+
12885+ suspend_bio_ops.rw_header_chunk(WRITE, &suspend_fileops,
12886+ (char *) &suspend_writer_posn_save,
12887+ sizeof(suspend_writer_posn_save));
12888+
12889+ suspend_bio_ops.rw_header_chunk(WRITE, &suspend_fileops,
12890+ (char *) &devinfo, sizeof(devinfo));
12891+
12892+ suspend_serialise_extent_chain(&suspend_fileops, &block_chain);
12893+
12894+ return 0;
12895+}
12896+
12897+static int suspend_file_write_header_cleanup(void)
12898+{
12899+ struct suspend_file_header *header;
12900+
12901+ /* Write any unsaved data */
12902+ if (suspend_writer_buffer_posn)
12903+ suspend_bio_ops.write_header_chunk_finish();
12904+
12905+ suspend_bio_ops.finish_all_io();
12906+
12907+ suspend_extent_state_goto_start(&suspend_writer_posn);
12908+ suspend_bio_ops.forward_one_page();
12909+
12910+ /* Adjust image header */
12911+ suspend_bio_ops.bdev_page_io(READ, suspend_file_target_bdev,
12912+ target_firstblock,
12913+ virt_to_page(suspend_writer_buffer));
12914+
12915+ header = (struct suspend_file_header *) suspend_writer_buffer;
12916+
12917+ prepare_signature(header,
12918+ suspend_writer_posn.current_offset <<
12919+ devinfo.bmap_shift);
12920+
12921+ suspend_bio_ops.bdev_page_io(WRITE, suspend_file_target_bdev,
12922+ target_firstblock,
12923+ virt_to_page(suspend_writer_buffer));
12924+
12925+ free_page((unsigned long) suspend_writer_buffer);
12926+ suspend_writer_buffer = NULL;
12927+
12928+ suspend_bio_ops.finish_all_io();
12929+
12930+ return 0;
12931+}
12932+
12933+/* HEADER READING */
12934+
12935+#ifdef CONFIG_DEVFS_FS
12936+int create_dev(char *name, dev_t dev, char *devfs_name);
12937+#else
12938+static int create_dev(char *name, dev_t dev, char *devfs_name)
12939+{
12940+ sys_unlink(name);
12941+ return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
12942+}
12943+#endif
12944+
12945+static int rd_init(void)
12946+{
12947+ suspend_writer_buffer_posn = 0;
12948+
12949+ create_dev("/dev/root", ROOT_DEV, root_device_name);
12950+ create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL);
12951+
12952+ suspend_read_fd = sys_open("/dev/root", O_RDONLY, 0);
12953+ if (suspend_read_fd < 0)
12954+ goto out;
12955+
12956+ sys_read(suspend_read_fd, suspend_writer_buffer, BLOCK_SIZE);
12957+
12958+ memcpy(&suspend_writer_posn_save,
12959+ suspend_writer_buffer + suspend_writer_buffer_posn,
12960+ sizeof(suspend_writer_posn_save));
12961+
12962+ suspend_writer_buffer_posn += sizeof(suspend_writer_posn_save);
12963+
12964+ return 0;
12965+out:
12966+ sys_unlink("/dev/ram");
12967+ sys_unlink("/dev/root");
12968+ return -EIO;
12969+}
12970+
12971+static int file_init(void)
12972+{
12973+ suspend_writer_buffer_posn = 0;
12974+
12975+ /* Read suspend_file configuration */
12976+ suspend_bio_ops.bdev_page_io(READ, suspend_file_target_bdev,
12977+ target_header_start,
12978+ virt_to_page((unsigned long) suspend_writer_buffer));
12979+
12980+ return 0;
12981+}
12982+
12983+/*
12984+ * read_header_init()
12985+ *
12986+ * Ramdisk support based heavily on init/do_mounts_rd.c
12987+ *
12988+ * Description:
12989+ * 1. Attempt to read the device specified with resume2=.
12990+ * 2. Check the contents of the header for our signature.
12991+ * 3. Warn, ignore, reset and/or continue as appropriate.
12992+ * 4. If continuing, read the suspend_file configuration section
12993+ * of the header and set up block device info so we can read
12994+ * the rest of the header & image.
12995+ *
12996+ * Returns:
12997+ * May not return if user choose to reboot at a warning.
12998+ * -EINVAL if cannot resume at this time. Booting should continue
12999+ * normally.
13000+ */
13001+
13002+static int suspend_file_read_header_init(void)
13003+{
13004+ int result;
13005+ struct block_device *tmp;
13006+
13007+ suspend_writer_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
13008+
13009+ if (test_suspend_state(SUSPEND_TRY_RESUME_RD))
13010+ result = rd_init();
13011+ else
13012+ result = file_init();
13013+
13014+ if (result) {
13015+ printk("FileAllocator read header init: Failed to initialise "
13016+ "reading the first page of data.\n");
13017+ return result;
13018+ }
13019+
13020+ memcpy(&suspend_writer_posn_save,
13021+ suspend_writer_buffer + suspend_writer_buffer_posn,
13022+ sizeof(suspend_writer_posn_save));
13023+
13024+ suspend_writer_buffer_posn += sizeof(suspend_writer_posn_save);
13025+
13026+ tmp = devinfo.bdev;
13027+
13028+ memcpy(&devinfo,
13029+ suspend_writer_buffer + suspend_writer_buffer_posn,
13030+ sizeof(devinfo));
13031+
13032+ devinfo.bdev = tmp;
13033+ suspend_writer_buffer_posn += sizeof(devinfo);
13034+
13035+ suspend_extent_state_goto_start(&suspend_writer_posn);
13036+ suspend_bio_ops.set_extra_page_forward();
13037+
13038+ suspend_header_bytes_used = suspend_writer_buffer_posn;
13039+
13040+ suspend_load_extent_chain(&block_chain);
13041+
13042+ return 0;
13043+}
13044+
13045+static int suspend_file_read_header_cleanup(void)
13046+{
13047+ free_page((unsigned long) suspend_writer_buffer);
13048+ suspend_writer_buffer = NULL;
13049+ return 0;
13050+}
13051+
13052+static int suspend_file_signature_op(int op)
13053+{
13054+ char *cur;
13055+ int result = 0, changed = 0;
13056+ struct suspend_file_header *header;
13057+
13058+ if(suspend_file_target_bdev <= 0)
13059+ return -1;
13060+
13061+ cur = (char *) get_zeroed_page(GFP_ATOMIC);
13062+ if (!cur) {
13063+ printk("Unable to allocate a page for reading the image "
13064+ "signature.\n");
13065+ return -ENOMEM;
13066+ }
13067+
13068+ suspend_bio_ops.bdev_page_io(READ, suspend_file_target_bdev,
13069+ target_firstblock,
13070+ virt_to_page(cur));
13071+
13072+ header = (struct suspend_file_header *) cur;
13073+ result = parse_signature(header);
13074+
13075+ switch (op) {
13076+ case INVALIDATE:
13077+ if (result == -1)
13078+ goto out;
13079+
13080+ strcpy(header->sig, NoImage);
13081+ header->resumed_before = 0;
13082+ result = changed = 1;
13083+ break;
13084+ case MARK_RESUME_ATTEMPTED:
13085+ if (result == 1) {
13086+ header->resumed_before = 1;
13087+ changed = 1;
13088+ }
13089+ break;
13090+ }
13091+
13092+ if (changed)
13093+ suspend_bio_ops.bdev_page_io(WRITE, suspend_file_target_bdev,
13094+ target_firstblock,
13095+ virt_to_page(cur));
13096+
13097+out:
13098+ suspend_bio_ops.finish_all_io();
13099+ free_page((unsigned long) cur);
13100+ return result;
13101+}
13102+
13103+/* Print debug info
13104+ *
13105+ * Description:
13106+ */
13107+
13108+static int suspend_file_print_debug_stats(char *buffer, int size)
13109+{
13110+ int len = 0;
13111+
13112+ if (suspendActiveAllocator != &suspend_fileops) {
13113+ len = snprintf_used(buffer, size, "- FileAllocator inactive.\n");
13114+ return len;
13115+ }
13116+
13117+ len = snprintf_used(buffer, size, "- FileAllocator active.\n");
13118+
13119+ len+= snprintf_used(buffer+len, size-len, " Storage available for image: "
13120+ "%ld pages.\n",
13121+ suspend_file_storage_allocated());
13122+
13123+ return len;
13124+}
13125+
13126+/*
13127+ * Storage needed
13128+ *
13129+ * Returns amount of space in the image header required
13130+ * for the suspend_file's data.
13131+ *
13132+ * We ensure the space is allocated, but actually save the
13133+ * data from write_header_init and therefore don't also define a
13134+ * save_config_info routine.
13135+ */
13136+static int suspend_file_storage_needed(void)
13137+{
13138+ return sig_size + strlen(suspend_file_target) + 1 +
13139+ 3 * sizeof(struct extent_iterate_saved_state) +
13140+ sizeof(devinfo) +
13141+ sizeof(struct extent_chain) - 2 * sizeof(void *) +
13142+ (2 * sizeof(unsigned long) * block_chain.num_extents);
13143+}
13144+
13145+/*
13146+ * suspend_file_invalidate_image
13147+ *
13148+ */
13149+static int suspend_file_invalidate_image(void)
13150+{
13151+ int result;
13152+
13153+ if (nr_suspends > 0)
13154+ suspend_file_release_storage();
13155+
13156+ result = suspend_file_signature_op(INVALIDATE);
13157+ if (result == 1 && !nr_suspends)
13158+ printk(KERN_WARNING name_suspend "Image invalidated.\n");
13159+
13160+ return result;
13161+}
13162+
13163+/*
13164+ * Image_exists
13165+ *
13166+ */
13167+
13168+static int suspend_file_image_exists(void)
13169+{
13170+ if (!suspend_file_target_bdev)
13171+ reopen_resume_devt();
13172+
13173+ return suspend_file_signature_op(GET_IMAGE_EXISTS);
13174+}
13175+
13176+/*
13177+ * Mark resume attempted.
13178+ *
13179+ * Record that we tried to resume from this image.
13180+ */
13181+
13182+static void suspend_file_mark_resume_attempted(void)
13183+{
13184+ suspend_file_signature_op(MARK_RESUME_ATTEMPTED);
13185+}
13186+
13187+static void suspend_file_set_resume2(void)
13188+{
13189+ char *buffer = (char *) get_zeroed_page(GFP_ATOMIC);
13190+ char *buffer2 = (char *) get_zeroed_page(GFP_ATOMIC);
13191+ unsigned long sector = bmap(target_inode, 0);
13192+ int offset = 0;
13193+
13194+ if (suspend_file_target_bdev) {
13195+ set_devinfo(suspend_file_target_bdev, target_inode->i_blkbits);
13196+
13197+ bdevname(suspend_file_target_bdev, buffer2);
13198+ offset += snprintf(buffer + offset, PAGE_SIZE - offset,
13199+ "/dev/%s", buffer2);
13200+
13201+ if (sector)
13202+ offset += snprintf(buffer + offset, PAGE_SIZE - offset,
13203+ ":0x%lx", sector << devinfo.bmap_shift);
13204+ } else
13205+ offset += snprintf(buffer + offset, PAGE_SIZE - offset,
13206+ "%s is not a valid target.", suspend_file_target);
13207+
13208+ sprintf(resume2_file, "file:%s", buffer);
13209+
13210+ free_page((unsigned long) buffer);
13211+ free_page((unsigned long) buffer2);
13212+
13213+ suspend_attempt_to_parse_resume_device();
13214+}
13215+
13216+static int __test_suspend_file_target(char *target, int resume_time)
13217+{
13218+ suspend_file_get_target_info(target, 0, resume_time);
13219+ if (suspend_file_signature_op(GET_IMAGE_EXISTS) > -1) {
13220+ printk(name_suspend "FileAllocator: File signature found.\n");
13221+ if (!resume_time)
13222+ suspend_file_set_resume2();
13223+
13224+ suspend_bio_ops.set_devinfo(&devinfo);
13225+ suspend_writer_posn.chains = &block_chain;
13226+ suspend_writer_posn.num_chains = 1;
13227+
13228+ set_suspend_state(SUSPEND_CAN_SUSPEND);
13229+ return 0;
13230+ }
13231+
13232+ clear_suspend_state(SUSPEND_CAN_SUSPEND);
13233+
13234+ if (*target)
13235+ printk(name_suspend
13236+ "FileAllocator: Sorry. No signature found at %s.\n",
13237+ target);
13238+ else
13239+ if (!resume_time)
13240+ printk(name_suspend
13241+ "FileAllocator: Sorry. Target is not set for suspending.\n");
13242+
13243+ return 1;
13244+}
13245+
13246+static void test_suspend_file_target(void)
13247+{
13248+ int cant_suspend;
13249+
13250+ setting_suspend_file_target = 1;
13251+
13252+ printk(name_suspend "FileAllocator: Testing whether you can suspend:\n");
13253+ cant_suspend =__test_suspend_file_target(suspend_file_target, 0);
13254+
13255+ printk(name_suspend "Suspending %sabled.\n", cant_suspend ? "dis" : "en");
13256+
13257+ setting_suspend_file_target = 0;
13258+}
13259+
13260+/*
13261+ * Parse Image Location
13262+ *
13263+ * Attempt to parse a resume2= parameter.
13264+ * Swap Writer accepts:
13265+ * resume2=file:DEVNAME[:FIRSTBLOCK]
13266+ *
13267+ * Where:
13268+ * DEVNAME is convertable to a dev_t by name_to_dev_t
13269+ * FIRSTBLOCK is the location of the first block in the file.
13270+ * BLOCKSIZE is the logical blocksize >= SECTOR_SIZE & <= PAGE_SIZE,
13271+ * mod SECTOR_SIZE == 0 of the device.
13272+ * Data is validated by attempting to read a header from the
13273+ * location given. Failure will result in suspend_file refusing to
13274+ * save an image, and a reboot with correct parameters will be
13275+ * necessary.
13276+ */
13277+
13278+static int suspend_file_parse_sig_location(char *commandline, int only_writer)
13279+{
13280+ char *thischar, *devstart = NULL, *colon = NULL, *at_symbol = NULL;
13281+ int result = -EINVAL, target_blocksize = 0;
13282+
13283+ if (strncmp(commandline, "file:", 5)) {
13284+ if (!only_writer)
13285+ return 1;
13286+ } else
13287+ commandline += 5;
13288+
13289+ /*
13290+ * Don't check signature again if we're beginning a cycle. If we already
13291+ * did the initialisation successfully, assume we'll be okay when it comes
13292+ * to resuming.
13293+ */
13294+ if (suspend_file_target_bdev)
13295+ return 0;
13296+
13297+ devstart = thischar = commandline;
13298+ while ((*thischar != ':') && (*thischar != '@') &&
13299+ ((thischar - commandline) < 250) && (*thischar))
13300+ thischar++;
13301+
13302+ if (*thischar == ':') {
13303+ colon = thischar;
13304+ *colon = 0;
13305+ thischar++;
13306+ }
13307+
13308+ while ((*thischar != '@') && ((thischar - commandline) < 250) && (*thischar))
13309+ thischar++;
13310+
13311+ if (*thischar == '@') {
13312+ at_symbol = thischar;
13313+ *at_symbol = 0;
13314+ }
13315+
13316+ /*
13317+ * For the suspend_file, you can be able to resume, but not suspend,
13318+ * because the resume2= is set correctly, but the suspend_file_target
13319+ * isn't.
13320+ *
13321+ * We may have come here as a result of setting resume2 or
13322+ * suspend_file_target. We only test the suspend_file target in the
13323+ * former case (it's already done in the later), and we do it before
13324+ * setting the block number ourselves. It will overwrite the values
13325+ * given on the command line if we don't.
13326+ */
13327+
13328+ if (!setting_suspend_file_target)
13329+ __test_suspend_file_target(suspend_file_target, 1);
13330+
13331+ if (colon)
13332+ target_firstblock = (int) simple_strtoul(colon + 1, NULL, 0);
13333+ else
13334+ target_firstblock = 0;
13335+
13336+ if (at_symbol) {
13337+ target_blocksize = (int) simple_strtoul(at_symbol + 1, NULL, 0);
13338+ if (target_blocksize & (SECTOR_SIZE - 1)) {
13339+ printk("FileAllocator: Blocksizes are multiples of %d.\n", SECTOR_SIZE);
13340+ result = -EINVAL;
13341+ goto out;
13342+ }
13343+ }
13344+
13345+ printk("Suspend2 FileAllocator: Testing whether you can resume:\n");
13346+
13347+ suspend_file_get_target_info(commandline, 0, 1);
13348+
13349+ if (!suspend_file_target_bdev || IS_ERR(suspend_file_target_bdev)) {
13350+ suspend_file_target_bdev = NULL;
13351+ result = -1;
13352+ goto out;
13353+ }
13354+
13355+ if (target_blocksize)
13356+ set_devinfo(suspend_file_target_bdev, ffs(target_blocksize));
13357+
13358+ result = __test_suspend_file_target(commandline, 1);
13359+
13360+out:
13361+ if (result)
13362+ clear_suspend_state(SUSPEND_CAN_SUSPEND);
13363+ else
13364+ set_suspend_state(SUSPEND_CAN_SUSPEND);
13365+
13366+ printk("Resuming %sabled.\n", result ? "dis" : "en");
13367+
13368+ if (colon)
13369+ *colon = ':';
13370+ if (at_symbol)
13371+ *at_symbol = '@';
13372+
13373+ return result;
13374+}
13375+
13376+/* suspend_file_save_config_info
13377+ *
13378+ * Description: Save the target's name, not for resume time, but for all_settings.
13379+ * Arguments: Buffer: Pointer to a buffer of size PAGE_SIZE.
13380+ * Returns: Number of bytes used for saving our data.
13381+ */
13382+
13383+static int suspend_file_save_config_info(char *buffer)
13384+{
13385+ strcpy(buffer, suspend_file_target);
13386+ return strlen(suspend_file_target) + 1;
13387+}
13388+
13389+/* suspend_file_load_config_info
13390+ *
13391+ * Description: Reload target's name.
13392+ * Arguments: Buffer: Pointer to the start of the data.
13393+ * Size: Number of bytes that were saved.
13394+ */
13395+
13396+static void suspend_file_load_config_info(char *buffer, int size)
13397+{
13398+ strcpy(suspend_file_target, buffer);
13399+}
13400+
13401+static int suspend_file_initialise(int starting_cycle)
13402+{
13403+ int result = 0;
13404+
13405+ if (starting_cycle) {
13406+ if (suspendActiveAllocator != &suspend_fileops)
13407+ return 0;
13408+
13409+ if (!*suspend_file_target) {
13410+ printk("FileAllocator is the active writer, "
13411+ "but no filename has been set.\n");
13412+ return 1;
13413+ }
13414+ }
13415+
13416+ if (suspend_file_target)
13417+ suspend_file_get_target_info(suspend_file_target, starting_cycle, 0);
13418+
13419+ if (starting_cycle && (suspend_file_image_exists() == -1)) {
13420+ printk("%s is does not have a valid signature for suspending.\n",
13421+ suspend_file_target);
13422+ result = 1;
13423+ }
13424+
13425+ return result;
13426+}
13427+
13428+static struct suspend_sysfs_data sysfs_params[] = {
13429+
13430+ {
13431+ SUSPEND2_ATTR("target", SYSFS_RW),
13432+ SYSFS_STRING(suspend_file_target, 256, SYSFS_NEEDS_FOR_WRITE),
13433+ .write_side_effect = test_suspend_file_target,
13434+ },
13435+
13436+ {
13437+ SUSPEND2_ATTR("enabled", SYSFS_RW),
13438+ SYSFS_INT(&suspend_fileops.enabled, 0, 1),
13439+ .write_side_effect = attempt_to_parse_resume_device2,
13440+ }
13441+};
13442+
13443+static struct suspend_module_ops suspend_fileops = {
13444+ .type = WRITER_MODULE,
13445+ .name = "File Allocator",
13446+ .directory = "file",
13447+ .module = THIS_MODULE,
13448+ .print_debug_info = suspend_file_print_debug_stats,
13449+ .save_config_info = suspend_file_save_config_info,
13450+ .load_config_info = suspend_file_load_config_info,
13451+ .storage_needed = suspend_file_storage_needed,
13452+ .initialise = suspend_file_initialise,
13453+ .cleanup = suspend_file_cleanup,
13454+
13455+ .storage_available = suspend_file_storage_available,
13456+ .storage_allocated = suspend_file_storage_allocated,
13457+ .release_storage = suspend_file_release_storage,
13458+ .allocate_header_space = suspend_file_allocate_header_space,
13459+ .allocate_storage = suspend_file_allocate_storage,
13460+ .image_exists = suspend_file_image_exists,
13461+ .mark_resume_attempted = suspend_file_mark_resume_attempted,
13462+ .write_header_init = suspend_file_write_header_init,
13463+ .write_header_cleanup = suspend_file_write_header_cleanup,
13464+ .read_header_init = suspend_file_read_header_init,
13465+ .read_header_cleanup = suspend_file_read_header_cleanup,
13466+ .invalidate_image = suspend_file_invalidate_image,
13467+ .parse_sig_location = suspend_file_parse_sig_location,
13468+
13469+ .sysfs_data = sysfs_params,
13470+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
13471+};
13472+
13473+/* ---- Registration ---- */
13474+static __init int suspend_file_load(void)
13475+{
13476+ suspend_fileops.read_chunk = suspend_bio_ops.read_chunk;
13477+ suspend_fileops.write_chunk = suspend_bio_ops.write_chunk;
13478+ suspend_fileops.rw_init = suspend_bio_ops.rw_init;
13479+ suspend_fileops.rw_cleanup = suspend_bio_ops.rw_cleanup;
13480+ suspend_fileops.rw_header_chunk =
13481+ suspend_bio_ops.rw_header_chunk;
13482+
13483+ return suspend_register_module(&suspend_fileops);
13484+}
13485+
13486+#ifdef MODULE
13487+static __exit void suspend_file_unload(void)
13488+{
13489+ suspend_unregister_module(&suspend_fileops);
13490+}
13491+
13492+module_init(suspend_file_load);
13493+module_exit(suspend_file_unload);
13494+MODULE_LICENSE("GPL");
13495+MODULE_AUTHOR("Nigel Cunningham");
13496+MODULE_DESCRIPTION("Suspend2 FileAllocator");
13497+#else
13498+late_initcall(suspend_file_load);
13499+#endif
13500diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
13501new file mode 100644
13502index 0000000..9068d6c
13503--- /dev/null
13504+++ b/kernel/power/suspend_swap.c
13505@@ -0,0 +1,1217 @@
13506+/*
13507+ * kernel/power/suspend_swap.c
13508+ *
13509+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
13510+ * Copyright (C) 2006 Red Hat, inc.
13511+ *
13512+ * Distributed under GPLv2.
13513+ *
13514+ * This file encapsulates functions for usage of swap space as a
13515+ * backing store.
13516+ */
13517+
13518+#include <linux/suspend.h>
13519+#include <linux/module.h>
13520+#include <linux/blkdev.h>
13521+#include <linux/swapops.h>
13522+#include <linux/swap.h>
13523+
13524+#include "suspend.h"
13525+#include "sysfs.h"
13526+#include "modules.h"
13527+#include "io.h"
13528+#include "ui.h"
13529+#include "extent.h"
13530+#include "block_io.h"
13531+
13532+static struct suspend_module_ops suspend_swapops;
13533+
13534+#define SIGNATURE_VER 6
13535+
13536+/* --- Struct of pages stored on disk */
13537+
13538+union diskpage {
13539+ union swap_header swh; /* swh.magic is the only member used */
13540+};
13541+
13542+union p_diskpage {
13543+ union diskpage *pointer;
13544+ char *ptr;
13545+ unsigned long address;
13546+};
13547+
13548+/* Devices used for swap */
13549+static struct suspend_bdev_info devinfo[MAX_SWAPFILES];
13550+
13551+/* Extent chains for swap & blocks */
13552+struct extent_chain swapextents;
13553+struct extent_chain block_chain[MAX_SWAPFILES];
13554+
13555+static dev_t header_dev_t;
13556+static struct block_device *header_block_device;
13557+static unsigned long headerblock;
13558+
13559+/* For swapfile automatically swapon/off'd. */
13560+static char swapfilename[32] = "";
13561+extern asmlinkage long sys_swapon(const char *specialfile, int swap_flags);
13562+extern asmlinkage long sys_swapoff(const char *specialfile);
13563+static int suspend_swapon_status;
13564+
13565+/* Header Page Information */
13566+static int header_pages_allocated;
13567+
13568+/* User Specified Parameters. */
13569+
13570+static unsigned long resume_firstblock;
13571+static int resume_blocksize;
13572+static dev_t resume_dev_t;
13573+static struct block_device *resume_block_device;
13574+
13575+struct sysinfo swapinfo;
13576+static int suspend_swap_invalidate_image(void);
13577+
13578+/* Block devices open. */
13579+struct bdev_opened
13580+{
13581+ dev_t device;
13582+ struct block_device *bdev;
13583+ int claimed;
13584+};
13585+
13586+/*
13587+ * Entry MAX_SWAPFILES is the resume block device, which may
13588+ * not be a swap device enabled when we suspend.
13589+ * Entry MAX_SWAPFILES + 1 is the header block device, which
13590+ * is needed before we find out which slot it occupies.
13591+ */
13592+static struct bdev_opened *bdev_info_list[MAX_SWAPFILES + 2];
13593+
13594+static void close_bdev(int i)
13595+{
13596+ struct bdev_opened *this = bdev_info_list[i];
13597+
13598+ if (this->claimed)
13599+ bd_release(this->bdev);
13600+
13601+ /* Release our reference. */
13602+ blkdev_put(this->bdev);
13603+
13604+ /* Free our info. */
13605+ kfree(this);
13606+
13607+ bdev_info_list[i] = NULL;
13608+}
13609+
13610+static void close_bdevs(void)
13611+{
13612+ int i;
13613+
13614+ for (i = 0; i < MAX_SWAPFILES; i++)
13615+ if (bdev_info_list[i])
13616+ close_bdev(i);
13617+
13618+ resume_block_device = header_block_device = NULL;
13619+}
13620+
13621+static struct block_device *open_bdev(int index, dev_t device, int display_errs)
13622+{
13623+ struct bdev_opened *this;
13624+ struct block_device *bdev;
13625+
13626+ if (bdev_info_list[index] && (bdev_info_list[index]->device == device)){
13627+ bdev = bdev_info_list[index]->bdev;
13628+ return bdev;
13629+ }
13630+
13631+ if (bdev_info_list[index] && bdev_info_list[index]->device != device)
13632+ close_bdev(index);
13633+
13634+ bdev = open_by_devnum(device, FMODE_READ);
13635+
13636+ if (IS_ERR(bdev) || !bdev) {
13637+ if (display_errs)
13638+ suspend_early_boot_message(1,SUSPEND_CONTINUE_REQ,
13639+ "Failed to get access to block device "
13640+ "\"%x\" (error %d).\n Maybe you need "
13641+ "to run mknod and/or lvmsetup in an "
13642+ "initrd/ramfs?", device, bdev);
13643+ return ERR_PTR(-EINVAL);
13644+ }
13645+
13646+ this = kmalloc(sizeof(struct bdev_opened), GFP_KERNEL);
13647+ BUG_ON(!this);
13648+
13649+ bdev_info_list[index] = this;
13650+ this->device = device;
13651+ this->bdev = bdev;
13652+
13653+ if (index < MAX_SWAPFILES)
13654+ devinfo[index].bdev = bdev;
13655+
13656+ return bdev;
13657+}
13658+
13659+/* Must be silent - might be called from cat /sys/power/suspend2/debug_info
13660+ * Returns 0 if was off, -EBUSY if was on, error value otherwise.
13661+ */
13662+static int enable_swapfile(void)
13663+{
13664+ int activateswapresult = -EINVAL;
13665+
13666+ if (suspend_swapon_status)
13667+ return 0;
13668+
13669+ if (swapfilename[0]) {
13670+ /* Attempt to swap on with maximum priority */
13671+ activateswapresult = sys_swapon(swapfilename, 0xFFFF);
13672+ if ((activateswapresult) && (activateswapresult != -EBUSY))
13673+ printk(name_suspend
13674+ "The swapfile/partition specified by "
13675+ "/sys/power/suspend2/suspend_swap/swapfile (%s) could not"
13676+ " be turned on (error %d). Attempting "
13677+ "to continue.\n",
13678+ swapfilename, activateswapresult);
13679+ if (!activateswapresult)
13680+ suspend_swapon_status = 1;
13681+ }
13682+ return activateswapresult;
13683+}
13684+
13685+/* Returns 0 if was on, -EINVAL if was off, error value otherwise */
13686+static int disable_swapfile(void)
13687+{
13688+ int result = -EINVAL;
13689+
13690+ if (!suspend_swapon_status)
13691+ return 0;
13692+
13693+ if (swapfilename[0]) {
13694+ result = sys_swapoff(swapfilename);
13695+ if (result == -EINVAL)
13696+ return 0; /* Wasn't on */
13697+ if (!result)
13698+ suspend_swapon_status = 0;
13699+ }
13700+
13701+ return result;
13702+}
13703+
13704+static int try_to_parse_resume_device(char *commandline)
13705+{
13706+ struct kstat stat;
13707+ int error;
13708+
13709+ resume_dev_t = name_to_dev_t(commandline);
13710+
13711+ if (!resume_dev_t) {
13712+ error = vfs_stat(commandline, &stat);
13713+ if (!error)
13714+ resume_dev_t = stat.rdev;
13715+ }
13716+
13717+ if (!resume_dev_t) {
13718+ if (test_suspend_state(SUSPEND_TRYING_TO_RESUME))
13719+ suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
13720+ "Failed to translate \"%s\" into a device id.\n",
13721+ commandline);
13722+ else
13723+ printk(name_suspend
13724+ "Can't translate \"%s\" into a device id yet.\n",
13725+ commandline);
13726+ return 1;
13727+ }
13728+
13729+ if (IS_ERR(resume_block_device =
13730+ open_bdev(MAX_SWAPFILES, resume_dev_t, 0))) {
13731+ suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
13732+ "Failed to get access to \"%s\", where"
13733+ " the swap header should be found.",
13734+ commandline);
13735+ return 1;
13736+ }
13737+
13738+ return 0;
13739+}
13740+
13741+/*
13742+ * If we have read part of the image, we might have filled memory with
13743+ * data that should be zeroed out.
13744+ */
13745+static void suspend_swap_noresume_reset(void)
13746+{
13747+ memset((char *) &devinfo, 0, sizeof(devinfo));
13748+ close_bdevs();
13749+}
13750+
13751+static int parse_signature(char *header, int restore)
13752+{
13753+ int type = -1;
13754+
13755+ if (!memcmp("SWAP-SPACE",header,10))
13756+ return 0;
13757+ else if (!memcmp("SWAPSPACE2",header,10))
13758+ return 1;
13759+
13760+ else if (!memcmp("S1SUSP",header,6))
13761+ type = 2;
13762+ else if (!memcmp("S2SUSP",header,6))
13763+ type = 3;
13764+ else if (!memcmp("S1SUSPEND",header,9))
13765+ type = 4;
13766+
13767+ else if (!memcmp("z",header,1))
13768+ type = 12;
13769+ else if (!memcmp("Z",header,1))
13770+ type = 13;
13771+
13772+ /*
13773+ * Put bdev of suspend header in last byte of swap header
13774+ * (unsigned short)
13775+ */
13776+ if (type > 11) {
13777+ dev_t *header_ptr = (dev_t *) &header[1];
13778+ unsigned char *headerblocksize_ptr =
13779+ (unsigned char *) &header[5];
13780+ u32 *headerblock_ptr = (u32 *) &header[6];
13781+ header_dev_t = *header_ptr;
13782+ /*
13783+ * We are now using the highest bit of the char to indicate
13784+ * whether we have attempted to resume from this image before.
13785+ */
13786+ clear_suspend_state(SUSPEND_RESUMED_BEFORE);
13787+ if (((int) *headerblocksize_ptr) & 0x80)
13788+ set_suspend_state(SUSPEND_RESUMED_BEFORE);
13789+ headerblock = (unsigned long) *headerblock_ptr;
13790+ }
13791+
13792+ if ((restore) && (type > 5)) {
13793+ /* We only reset our own signatures */
13794+ if (type & 1)
13795+ memcpy(header,"SWAPSPACE2",10);
13796+ else
13797+ memcpy(header,"SWAP-SPACE",10);
13798+ }
13799+
13800+ return type;
13801+}
13802+
13803+/*
13804+ * prepare_signature
13805+ */
13806+static int prepare_signature(dev_t bdev, unsigned long block,
13807+ char *current_header)
13808+{
13809+ int current_type = parse_signature(current_header, 0);
13810+ dev_t *header_ptr = (dev_t *) (&current_header[1]);
13811+ unsigned long *headerblock_ptr =
13812+ (unsigned long *) (&current_header[6]);
13813+
13814+ if ((current_type > 1) && (current_type < 6))
13815+ return 1;
13816+
13817+ /* At the moment, I don't have a way to handle the block being
13818+ * > 32 bits. Not enough room in the signature and no way to
13819+ * safely put the data elsewhere. */
13820+
13821+ if (BITS_PER_LONG == 64 && ffs(block) > 31) {
13822+ suspend_prepare_status(DONT_CLEAR_BAR,
13823+ "Header sector requires 33+ bits. "
13824+ "Would not be able to resume.");
13825+ return 1;
13826+ }
13827+
13828+ if (current_type & 1)
13829+ current_header[0] = 'Z';
13830+ else
13831+ current_header[0] = 'z';
13832+ *header_ptr = bdev;
13833+ /* prev is the first/last swap page of the resume area */
13834+ *headerblock_ptr = (unsigned long) block;
13835+ return 0;
13836+}
13837+
13838+static int suspend_swap_allocate_storage(int space_requested);
13839+
13840+static int suspend_swap_allocate_header_space(int space_requested)
13841+{
13842+ int i;
13843+
13844+ if (!swapextents.size)
13845+ suspend_swap_allocate_storage(space_requested);
13846+
13847+ suspend_extent_state_goto_start(&suspend_writer_posn);
13848+ suspend_bio_ops.forward_one_page(); /* To first page */
13849+
13850+ for (i = 0; i < space_requested; i++) {
13851+ if (suspend_bio_ops.forward_one_page()) {
13852+ printk("Out of space while seeking to allocate "
13853+ "header pages,\n");
13854+ header_pages_allocated = i;
13855+ return -ENOSPC;
13856+ }
13857+
13858+ }
13859+
13860+ header_pages_allocated = space_requested;
13861+
13862+ /* The end of header pages will be the start of pageset 2;
13863+ * we are now sitting on the first pageset2 page. */
13864+ suspend_extent_state_save(&suspend_writer_posn,
13865+ &suspend_writer_posn_save[2]);
13866+ return 0;
13867+}
13868+
13869+static void get_main_pool_phys_params(void)
13870+{
13871+ struct extent *extentpointer = NULL;
13872+ unsigned long address;
13873+ int i, extent_min = -1, extent_max = -1, last_chain = -1;
13874+
13875+ for (i = 0; i < MAX_SWAPFILES; i++)
13876+ if (block_chain[i].first)
13877+ suspend_put_extent_chain(&block_chain[i]);
13878+
13879+ suspend_extent_for_each(&swapextents, extentpointer, address) {
13880+ swp_entry_t swap_address = extent_val_to_swap_entry(address);
13881+ pgoff_t offset = swp_offset(swap_address);
13882+ unsigned swapfilenum = swp_type(swap_address);
13883+ struct swap_info_struct *sis = get_swap_info_struct(swapfilenum);
13884+ sector_t new_sector = map_swap_page(sis, offset);
13885+
13886+ if ((new_sector == extent_max + 1) &&
13887+ (last_chain == swapfilenum))
13888+ extent_max++;
13889+ else {
13890+ if (extent_min > -1) {
13891+ if (test_action_state(SUSPEND_TEST_BIO))
13892+ printk("Adding extent chain %d %d-%d.\n",
13893+ swapfilenum,
13894+ extent_min <<
13895+ devinfo[last_chain].bmap_shift,
13896+ extent_max <<
13897+ devinfo[last_chain].bmap_shift);
13898+
13899+ suspend_add_to_extent_chain(
13900+ &block_chain[last_chain],
13901+ extent_min, extent_max);
13902+ }
13903+ extent_min = extent_max = new_sector;
13904+ last_chain = swapfilenum;
13905+ }
13906+ }
13907+
13908+ if (extent_min > -1) {
13909+ if (test_action_state(SUSPEND_TEST_BIO))
13910+ printk("Adding extent chain %d %d-%d.\n",
13911+ last_chain,
13912+ extent_min <<
13913+ devinfo[last_chain].bmap_shift,
13914+ extent_max <<
13915+ devinfo[last_chain].bmap_shift);
13916+ suspend_add_to_extent_chain(
13917+ &block_chain[last_chain],
13918+ extent_min, extent_max);
13919+ }
13920+
13921+ suspend_swap_allocate_header_space(header_pages_allocated);
13922+}
13923+
13924+static int suspend_swap_storage_allocated(void)
13925+{
13926+ return swapextents.size;
13927+}
13928+
13929+static int suspend_swap_storage_available(void)
13930+{
13931+ si_swapinfo(&swapinfo);
13932+ return swapinfo.freeswap + suspend_swap_storage_allocated();
13933+}
13934+
13935+static int suspend_swap_initialise(int starting_cycle)
13936+{
13937+ if (!starting_cycle)
13938+ return 0;
13939+
13940+ enable_swapfile();
13941+
13942+ if (resume_dev_t && !resume_block_device &&
13943+ IS_ERR(resume_block_device =
13944+ open_bdev(MAX_SWAPFILES, resume_dev_t, 1)))
13945+ return 1;
13946+
13947+ return 0;
13948+}
13949+
13950+static void suspend_swap_cleanup(int ending_cycle)
13951+{
13952+ if (ending_cycle)
13953+ disable_swapfile();
13954+
13955+ close_bdevs();
13956+}
13957+
13958+static int suspend_swap_release_storage(void)
13959+{
13960+ int i = 0;
13961+
13962+ if (test_action_state(SUSPEND_KEEP_IMAGE) &&
13963+ test_suspend_state(SUSPEND_NOW_RESUMING))
13964+ return 0;
13965+
13966+ header_pages_allocated = 0;
13967+
13968+ if (swapextents.first) {
13969+ /* Free swap entries */
13970+ struct extent *extentpointer;
13971+ unsigned long extentvalue;
13972+ swp_entry_t entry;
13973+ suspend_extent_for_each(&swapextents, extentpointer,
13974+ extentvalue) {
13975+ entry = extent_val_to_swap_entry(extentvalue);
13976+ swap_free(entry);
13977+ }
13978+
13979+ suspend_put_extent_chain(&swapextents);
13980+
13981+ for (i = 0; i < MAX_SWAPFILES; i++)
13982+ if (block_chain[i].first)
13983+ suspend_put_extent_chain(&block_chain[i]);
13984+ }
13985+
13986+ return 0;
13987+}
13988+
13989+/*
13990+ * Round robin allocation (where swap storage has the same priority).
13991+ * could make this very inefficient, so we track extents allocated on
13992+ * a per-swapfiles basis.
13993+ */
13994+static int suspend_swap_allocate_storage(int space_requested)
13995+{
13996+ int i, result = 0, first[MAX_SWAPFILES];
13997+ int pages_to_get = space_requested - swapextents.size;
13998+ unsigned long extent_min[MAX_SWAPFILES], extent_max[MAX_SWAPFILES];
13999+
14000+ if (pages_to_get < 1)
14001+ return 0;
14002+
14003+ for (i=0; i < MAX_SWAPFILES; i++) {
14004+ struct swap_info_struct *si = get_swap_info_struct(i);
14005+ if ((devinfo[i].bdev = si->bdev))
14006+ devinfo[i].dev_t = si->bdev->bd_dev;
14007+ devinfo[i].bmap_shift = 3;
14008+ devinfo[i].blocks_per_page = 1;
14009+ first[i] = 1;
14010+ }
14011+
14012+ for(i=0; i < pages_to_get; i++) {
14013+ swp_entry_t entry;
14014+ unsigned long new_value;
14015+ unsigned swapfilenum;
14016+
14017+ entry = get_swap_page();
14018+ if (!entry.val) {
14019+ printk("Failed to get a swap page.\n");
14020+ result = -ENOSPC;
14021+ break;
14022+ }
14023+
14024+ swapfilenum = swp_type(entry);
14025+ new_value = swap_entry_to_extent_val(entry);
14026+ if (first[swapfilenum]) {
14027+ first[swapfilenum] = 0;
14028+ extent_min[swapfilenum] = extent_max[swapfilenum] =
14029+ new_value;
14030+ } else {
14031+ if (new_value == extent_max[swapfilenum] + 1)
14032+ extent_max[swapfilenum]++;
14033+ else {
14034+ suspend_add_to_extent_chain(
14035+ &swapextents,
14036+ extent_min[swapfilenum],
14037+ extent_max[swapfilenum]);
14038+ extent_min[swapfilenum] =
14039+ extent_max[swapfilenum] = new_value;
14040+ }
14041+ }
14042+ }
14043+
14044+ for (i = 0; i < MAX_SWAPFILES; i++)
14045+ if (!first[i])
14046+ suspend_add_to_extent_chain(
14047+ &swapextents,
14048+ extent_min[i], extent_max[i]);
14049+
14050+ get_main_pool_phys_params();
14051+ return result;
14052+}
14053+
14054+static int suspend_swap_write_header_init(void)
14055+{
14056+ int i, result;
14057+ struct swap_info_struct *si;
14058+
14059+ suspend_header_bytes_used = 0;
14060+
14061+ suspend_extent_state_goto_start(&suspend_writer_posn);
14062+ /* Forward one page will be done prior to the read */
14063+
14064+ for (i = 0; i < MAX_SWAPFILES; i++) {
14065+ si = get_swap_info_struct(i);
14066+ if (si->swap_file)
14067+ devinfo[i].dev_t = si->bdev->bd_dev;
14068+ else
14069+ devinfo[i].dev_t = (dev_t) 0;
14070+ }
14071+
14072+ suspend_writer_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
14073+ if (!suspend_writer_buffer) {
14074+ printk("Failed to get suspend_swap buffer.\n");
14075+ return -ENOMEM;
14076+ }
14077+
14078+ suspend_writer_buffer_posn = 0;
14079+
14080+ /* Info needed to bootstrap goes at the start of the header.
14081+ * First we save the positions and devinfo, including the number
14082+ * of header pages. Then we save the structs containing data needed
14083+ * for reading the header pages back.
14084+ * Note that even if header pages take more than one page, when we
14085+ * read back the info, we will have restored the location of the
14086+ * next header page by the time we go to use it.
14087+ */
14088+
14089+ if ((result = suspend_bio_ops.rw_header_chunk(WRITE,
14090+ &suspend_swapops,
14091+ (char *) &suspend_writer_posn_save,
14092+ sizeof(suspend_writer_posn_save))))
14093+ return result;
14094+
14095+ if ((result = suspend_bio_ops.rw_header_chunk(WRITE,
14096+ &suspend_swapops,
14097+ (char *) &devinfo, sizeof(devinfo))))
14098+ return result;
14099+
14100+ for (i=0; i < MAX_SWAPFILES; i++)
14101+ suspend_serialise_extent_chain(&suspend_swapops, &block_chain[i]);
14102+
14103+ return 0;
14104+}
14105+
14106+static int suspend_swap_write_header_cleanup(void)
14107+{
14108+ int result;
14109+ struct swap_info_struct *si;
14110+
14111+ /* Write any unsaved data */
14112+ if (suspend_writer_buffer_posn)
14113+ suspend_bio_ops.write_header_chunk_finish();
14114+
14115+ suspend_bio_ops.finish_all_io();
14116+
14117+ suspend_extent_state_goto_start(&suspend_writer_posn);
14118+ suspend_bio_ops.forward_one_page();
14119+
14120+ /* Adjust swap header */
14121+ suspend_bio_ops.bdev_page_io(READ, resume_block_device,
14122+ resume_firstblock,
14123+ virt_to_page(suspend_writer_buffer));
14124+
14125+ si = get_swap_info_struct(suspend_writer_posn.current_chain);
14126+ result = prepare_signature(si->bdev->bd_dev,
14127+ suspend_writer_posn.current_offset,
14128+ ((union swap_header *) suspend_writer_buffer)->magic.magic);
14129+
14130+ if (!result)
14131+ suspend_bio_ops.bdev_page_io(WRITE, resume_block_device,
14132+ resume_firstblock,
14133+ virt_to_page(suspend_writer_buffer));
14134+
14135+ free_page((unsigned long) suspend_writer_buffer);
14136+ suspend_writer_buffer = NULL;
14137+
14138+ suspend_bio_ops.finish_all_io();
14139+
14140+ return result;
14141+}
14142+
14143+/* ------------------------- HEADER READING ------------------------- */
14144+
14145+/*
14146+ * read_header_init()
14147+ *
14148+ * Description:
14149+ * 1. Attempt to read the device specified with resume2=.
14150+ * 2. Check the contents of the swap header for our signature.
14151+ * 3. Warn, ignore, reset and/or continue as appropriate.
14152+ * 4. If continuing, read the suspend_swap configuration section
14153+ * of the header and set up block device info so we can read
14154+ * the rest of the header & image.
14155+ *
14156+ * Returns:
14157+ * May not return if user choose to reboot at a warning.
14158+ * -EINVAL if cannot resume at this time. Booting should continue
14159+ * normally.
14160+ */
14161+
14162+static int suspend_swap_read_header_init(void)
14163+{
14164+ int i;
14165+
14166+ BUG_ON(!resume_block_device);
14167+ BUG_ON(!resume_dev_t);
14168+
14169+ suspend_header_bytes_used = 0;
14170+
14171+ suspend_writer_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
14172+
14173+ BUG_ON(!suspend_writer_buffer);
14174+
14175+ if (!header_dev_t) {
14176+ printk("read_header_init called when we haven't "
14177+ "verified there is an image!\n");
14178+ return -EINVAL;
14179+ }
14180+
14181+ /*
14182+ * If the header is not on the resume_dev_t, get the resume device first.
14183+ */
14184+ if (header_dev_t != resume_dev_t) {
14185+ header_block_device = open_bdev(MAX_SWAPFILES + 1,
14186+ header_dev_t, 1);
14187+
14188+ if (IS_ERR(header_block_device))
14189+ return PTR_ERR(header_block_device);
14190+ } else
14191+ header_block_device = resume_block_device;
14192+
14193+ /*
14194+ * Read suspend_swap configuration.
14195+ * Headerblock size taken into account already.
14196+ */
14197+ suspend_bio_ops.bdev_page_io(READ, header_block_device,
14198+ headerblock << 3,
14199+ virt_to_page((unsigned long) suspend_writer_buffer));
14200+
14201+ memcpy(&suspend_writer_posn_save, suspend_writer_buffer, 3 * sizeof(struct extent_iterate_saved_state));
14202+
14203+ suspend_writer_buffer_posn = 3 * sizeof(struct extent_iterate_saved_state);
14204+ suspend_header_bytes_used += 3 * sizeof(struct extent_iterate_saved_state);
14205+
14206+ memcpy(&devinfo, suspend_writer_buffer + suspend_writer_buffer_posn, sizeof(devinfo));
14207+
14208+ suspend_writer_buffer_posn += sizeof(devinfo);
14209+ suspend_header_bytes_used += sizeof(devinfo);
14210+
14211+ /* Restore device info */
14212+ for (i = 0; i < MAX_SWAPFILES; i++) {
14213+ dev_t thisdevice = devinfo[i].dev_t;
14214+ struct block_device *result;
14215+
14216+ devinfo[i].bdev = NULL;
14217+
14218+ if (!thisdevice)
14219+ continue;
14220+
14221+ if (thisdevice == resume_dev_t) {
14222+ devinfo[i].bdev = resume_block_device;
14223+ bdev_info_list[i] = bdev_info_list[MAX_SWAPFILES];
14224+ BUG_ON(!bdev_info_list[i]);
14225+ bdev_info_list[MAX_SWAPFILES] = NULL;
14226+ continue;
14227+ }
14228+
14229+ if (thisdevice == header_dev_t) {
14230+ devinfo[i].bdev = header_block_device;
14231+ bdev_info_list[i] = bdev_info_list[MAX_SWAPFILES + 1];
14232+ BUG_ON(!bdev_info_list[i]);
14233+ bdev_info_list[MAX_SWAPFILES + 1] = NULL;
14234+ continue;
14235+ }
14236+
14237+ result = open_bdev(i, thisdevice, 1);
14238+ if (IS_ERR(result)) {
14239+ close_bdevs();
14240+ return PTR_ERR(result);
14241+ }
14242+ }
14243+
14244+ suspend_extent_state_goto_start(&suspend_writer_posn);
14245+ suspend_bio_ops.set_extra_page_forward();
14246+
14247+ for (i = 0; i < MAX_SWAPFILES; i++)
14248+ suspend_load_extent_chain(&block_chain[i]);
14249+
14250+ return 0;
14251+}
14252+
14253+static int suspend_swap_read_header_cleanup(void)
14254+{
14255+ free_page((unsigned long) suspend_writer_buffer);
14256+ return 0;
14257+}
14258+
14259+/* suspend_swap_invalidate_image
14260+ *
14261+ */
14262+static int suspend_swap_invalidate_image(void)
14263+{
14264+ union p_diskpage cur;
14265+ int result = 0;
14266+ char newsig[11];
14267+
14268+ cur.address = get_zeroed_page(GFP_ATOMIC);
14269+ if (!cur.address) {
14270+ printk("Unable to allocate a page for restoring the swap signature.\n");
14271+ return -ENOMEM;
14272+ }
14273+
14274+ /*
14275+ * If nr_suspends == 0, we must be booting, so no swap pages
14276+ * will be recorded as used yet.
14277+ */
14278+
14279+ if (nr_suspends > 0)
14280+ suspend_swap_release_storage();
14281+
14282+ /*
14283+ * We don't do a sanity check here: we want to restore the swap
14284+ * whatever version of kernel made the suspend image.
14285+ *
14286+ * We need to write swap, but swap may not be enabled so
14287+ * we write the device directly
14288+ */
14289+
14290+ suspend_bio_ops.bdev_page_io(READ, resume_block_device,
14291+ resume_firstblock,
14292+ virt_to_page(cur.pointer));
14293+
14294+ result = parse_signature(cur.pointer->swh.magic.magic, 1);
14295+
14296+ if (result < 5)
14297+ goto out;
14298+
14299+ strncpy(newsig, cur.pointer->swh.magic.magic, 10);
14300+ newsig[10] = 0;
14301+
14302+ suspend_bio_ops.bdev_page_io(WRITE, resume_block_device,
14303+ resume_firstblock,
14304+ virt_to_page(cur.pointer));
14305+
14306+ if (!nr_suspends)
14307+ printk(KERN_WARNING name_suspend "Image invalidated.\n");
14308+out:
14309+ suspend_bio_ops.finish_all_io();
14310+ free_page(cur.address);
14311+ return 0;
14312+}
14313+
14314+/*
14315+ * workspace_size
14316+ *
14317+ * Description:
14318+ * Returns the number of bytes of RAM needed for this
14319+ * code to do its work. (Used when calculating whether
14320+ * we have enough memory to be able to suspend & resume).
14321+ *
14322+ */
14323+static int suspend_swap_memory_needed(void)
14324+{
14325+ return 1;
14326+}
14327+
14328+/*
14329+ * Print debug info
14330+ *
14331+ * Description:
14332+ */
14333+static int suspend_swap_print_debug_stats(char *buffer, int size)
14334+{
14335+ int len = 0;
14336+ struct sysinfo sysinfo;
14337+
14338+ if (suspendActiveAllocator != &suspend_swapops) {
14339+ len = snprintf_used(buffer, size, "- SwapAllocator inactive.\n");
14340+ return len;
14341+ }
14342+
14343+ len = snprintf_used(buffer, size, "- SwapAllocator active.\n");
14344+ if (swapfilename[0])
14345+ len+= snprintf_used(buffer+len, size-len,
14346+ " Attempting to automatically swapon: %s.\n", swapfilename);
14347+
14348+ si_swapinfo(&sysinfo);
14349+
14350+ len+= snprintf_used(buffer+len, size-len, " Swap available for image: %ld pages.\n",
14351+ sysinfo.freeswap + suspend_swap_storage_allocated());
14352+
14353+ return len;
14354+}
14355+
14356+/*
14357+ * Storage needed
14358+ *
14359+ * Returns amount of space in the swap header required
14360+ * for the suspend_swap's data. This ignores the links between
14361+ * pages, which we factor in when allocating the space.
14362+ *
14363+ * We ensure the space is allocated, but actually save the
14364+ * data from write_header_init and therefore don't also define a
14365+ * save_config_info routine.
14366+ */
14367+static int suspend_swap_storage_needed(void)
14368+{
14369+ int i, result;
14370+ result = sizeof(suspend_writer_posn_save) + sizeof(devinfo);
14371+
14372+ for (i = 0; i < MAX_SWAPFILES; i++) {
14373+ result += 3 * sizeof(int);
14374+ result += (2 * sizeof(unsigned long) *
14375+ block_chain[i].num_extents);
14376+ }
14377+
14378+ return result;
14379+}
14380+
14381+/*
14382+ * Image_exists
14383+ */
14384+static int suspend_swap_image_exists(void)
14385+{
14386+ int signature_found;
14387+ union p_diskpage diskpage;
14388+
14389+ if (!resume_dev_t) {
14390+ printk("Not even trying to read header "
14391+ "because resume_dev_t is not set.\n");
14392+ return 0;
14393+ }
14394+
14395+ if (!resume_block_device &&
14396+ IS_ERR(resume_block_device =
14397+ open_bdev(MAX_SWAPFILES, resume_dev_t, 1))) {
14398+ printk("Failed to open resume dev_t (%x).\n", resume_dev_t);
14399+ return 0;
14400+ }
14401+
14402+ diskpage.address = get_zeroed_page(GFP_ATOMIC);
14403+
14404+ suspend_bio_ops.bdev_page_io(READ, resume_block_device,
14405+ resume_firstblock,
14406+ virt_to_page(diskpage.ptr));
14407+ suspend_bio_ops.finish_all_io();
14408+
14409+ signature_found = parse_signature(diskpage.pointer->swh.magic.magic, 0);
14410+ free_page(diskpage.address);
14411+
14412+ if (signature_found < 2) {
14413+ printk(name_suspend "Normal swapspace found.\n");
14414+ return 0; /* Normal swap space */
14415+ } else if (signature_found == -1) {
14416+ printk(KERN_ERR name_suspend
14417+ "Unable to find a signature. Could you have moved "
14418+ "a swap file?\n");
14419+ return 0;
14420+ } else if (signature_found < 6) {
14421+ printk(name_suspend "Dectected another implementation's signature.\n");
14422+ return 0;
14423+ } else if ((signature_found >> 1) != SIGNATURE_VER) {
14424+ if ((!(test_suspend_state(SUSPEND_NORESUME_SPECIFIED))) &&
14425+ suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
14426+ "Found a different style suspend image signature.")) {
14427+ set_suspend_state(SUSPEND_NORESUME_SPECIFIED);
14428+ printk(name_suspend "Dectected another implementation's signature.\n");
14429+ }
14430+ }
14431+
14432+ return 1;
14433+}
14434+
14435+/*
14436+ * Mark resume attempted.
14437+ *
14438+ * Record that we tried to resume from this image.
14439+ */
14440+static void suspend_swap_mark_resume_attempted(void)
14441+{
14442+ union p_diskpage diskpage;
14443+ int signature_found;
14444+
14445+ if (!resume_dev_t) {
14446+ printk("Not even trying to record attempt at resuming"
14447+ " because resume_dev_t is not set.\n");
14448+ return;
14449+ }
14450+
14451+ diskpage.address = get_zeroed_page(GFP_ATOMIC);
14452+
14453+ suspend_bio_ops.bdev_page_io(READ, resume_block_device,
14454+ resume_firstblock,
14455+ virt_to_page(diskpage.ptr));
14456+ signature_found = parse_signature(diskpage.pointer->swh.magic.magic, 0);
14457+
14458+ switch (signature_found) {
14459+ case 12:
14460+ case 13:
14461+ diskpage.pointer->swh.magic.magic[5] |= 0x80;
14462+ break;
14463+ }
14464+
14465+ suspend_bio_ops.bdev_page_io(WRITE, resume_block_device,
14466+ resume_firstblock,
14467+ virt_to_page(diskpage.ptr));
14468+ suspend_bio_ops.finish_all_io();
14469+ free_page(diskpage.address);
14470+
14471+ close_bdevs();
14472+ return;
14473+}
14474+
14475+/*
14476+ * Parse Image Location
14477+ *
14478+ * Attempt to parse a resume2= parameter.
14479+ * Swap Writer accepts:
14480+ * resume2=swap:DEVNAME[:FIRSTBLOCK][@BLOCKSIZE]
14481+ *
14482+ * Where:
14483+ * DEVNAME is convertable to a dev_t by name_to_dev_t
14484+ * FIRSTBLOCK is the location of the first block in the swap file
14485+ * (specifying for a swap partition is nonsensical but not prohibited).
14486+ * Data is validated by attempting to read a swap header from the
14487+ * location given. Failure will result in suspend_swap refusing to
14488+ * save an image, and a reboot with correct parameters will be
14489+ * necessary.
14490+ */
14491+static int suspend_swap_parse_sig_location(char *commandline, int only_allocator)
14492+{
14493+ char *thischar, *devstart, *colon = NULL, *at_symbol = NULL;
14494+ union p_diskpage diskpage;
14495+ int signature_found, result = -EINVAL, temp_result;
14496+
14497+ if (strncmp(commandline, "swap:", 5)) {
14498+ /*
14499+ * Failing swap:, we'll take a simple
14500+ * resume2=/dev/hda2, but fall through to
14501+ * other allocators if /dev/ isn't matched.
14502+ */
14503+ if (strncmp(commandline, "/dev/", 5))
14504+ return 1;
14505+ } else
14506+ commandline += 5;
14507+
14508+ devstart = thischar = commandline;
14509+ while ((*thischar != ':') && (*thischar != '@') &&
14510+ ((thischar - commandline) < 250) && (*thischar))
14511+ thischar++;
14512+
14513+ if (*thischar == ':') {
14514+ colon = thischar;
14515+ *colon = 0;
14516+ thischar++;
14517+ }
14518+
14519+ while ((*thischar != '@') && ((thischar - commandline) < 250) && (*thischar))
14520+ thischar++;
14521+
14522+ if (*thischar == '@') {
14523+ at_symbol = thischar;
14524+ *at_symbol = 0;
14525+ }
14526+
14527+ if (colon)
14528+ resume_firstblock = (int) simple_strtoul(colon + 1, NULL, 0);
14529+ else
14530+ resume_firstblock = 0;
14531+
14532+ clear_suspend_state(SUSPEND_CAN_SUSPEND);
14533+ clear_suspend_state(SUSPEND_CAN_RESUME);
14534+
14535+ /* Legacy */
14536+ if (at_symbol) {
14537+ resume_blocksize = (int) simple_strtoul(at_symbol + 1, NULL, 0);
14538+ if (resume_blocksize & (SECTOR_SIZE - 1)) {
14539+ printk("SwapAllocator: Blocksizes are multiples of %d!\n", SECTOR_SIZE);
14540+ return -EINVAL;
14541+ }
14542+ resume_firstblock = resume_firstblock * (resume_blocksize / SECTOR_SIZE);
14543+ }
14544+
14545+ temp_result = try_to_parse_resume_device(devstart);
14546+
14547+ if (colon)
14548+ *colon = ':';
14549+ if (at_symbol)
14550+ *at_symbol = '@';
14551+
14552+ if (temp_result)
14553+ return -EINVAL;
14554+
14555+ diskpage.address = get_zeroed_page(GFP_ATOMIC);
14556+ if (!diskpage.address) {
14557+ printk(KERN_ERR name_suspend "SwapAllocator: Failed to allocate a diskpage for I/O.\n");
14558+ return -ENOMEM;
14559+ }
14560+
14561+ temp_result = suspend_bio_ops.bdev_page_io(READ,
14562+ resume_block_device,
14563+ resume_firstblock,
14564+ virt_to_page(diskpage.ptr));
14565+
14566+ suspend_bio_ops.finish_all_io();
14567+
14568+ if (temp_result) {
14569+ printk(KERN_ERR name_suspend "SwapAllocator: Failed to submit I/O.\n");
14570+ goto invalid;
14571+ }
14572+
14573+ signature_found = parse_signature(diskpage.pointer->swh.magic.magic, 0);
14574+
14575+ if (signature_found != -1) {
14576+ printk(name_suspend "SwapAllocator: Signature found.\n");
14577+ result = 0;
14578+
14579+ suspend_bio_ops.set_devinfo(devinfo);
14580+ suspend_writer_posn.chains = &block_chain[0];
14581+ suspend_writer_posn.num_chains = MAX_SWAPFILES;
14582+ set_suspend_state(SUSPEND_CAN_SUSPEND);
14583+ set_suspend_state(SUSPEND_CAN_RESUME);
14584+ } else
14585+ printk(KERN_ERR name_suspend "SwapAllocator: No swap signature found at specified location.\n");
14586+invalid:
14587+ free_page((unsigned long) diskpage.address);
14588+ return result;
14589+
14590+}
14591+
14592+static int header_locations_read_sysfs(const char *page, int count)
14593+{
14594+ int i, printedpartitionsmessage = 0, len = 0, haveswap = 0;
14595+ struct inode *swapf = 0;
14596+ int zone;
14597+ char *path_page = (char *) __get_free_page(GFP_KERNEL);
14598+ char *path, *output = (char *) page;
14599+ int path_len;
14600+
14601+ if (!page)
14602+ return 0;
14603+
14604+ for (i = 0; i < MAX_SWAPFILES; i++) {
14605+ struct swap_info_struct *si = get_swap_info_struct(i);
14606+
14607+ if (!si->swap_file)
14608+ continue;
14609+
14610+ if (S_ISBLK(si->swap_file->f_mapping->host->i_mode)) {
14611+ haveswap = 1;
14612+ if (!printedpartitionsmessage) {
14613+ len += sprintf(output + len,
14614+ "For swap partitions, simply use the format: resume2=swap:/dev/hda1.\n");
14615+ printedpartitionsmessage = 1;
14616+ }
14617+ } else {
14618+ path_len = 0;
14619+
14620+ path = d_path(si->swap_file->f_dentry,
14621+ si->swap_file->f_vfsmnt,
14622+ path_page,
14623+ PAGE_SIZE);
14624+ path_len = snprintf(path_page, 31, "%s", path);
14625+
14626+ haveswap = 1;
14627+ swapf = si->swap_file->f_mapping->host;
14628+ if (!(zone = bmap(swapf,0))) {
14629+ len+= sprintf(output + len,
14630+ "Swapfile %s has been corrupted. Reuse mkswap on it and try again.\n",
14631+ path_page);
14632+ } else {
14633+ char name_buffer[255];
14634+ len+= sprintf(output + len, "For swapfile `%s`, use resume2=swap:/dev/%s:0x%x.\n",
14635+ path_page,
14636+ bdevname(si->bdev, name_buffer),
14637+ zone << (swapf->i_blkbits - 9));
14638+ }
14639+
14640+ }
14641+ }
14642+
14643+ if (!haveswap)
14644+ len = sprintf(output, "You need to turn on swap partitions before examining this file.\n");
14645+
14646+ free_page((unsigned long) path_page);
14647+ return len;
14648+}
14649+
14650+static struct suspend_sysfs_data sysfs_params[] = {
14651+ {
14652+ SUSPEND2_ATTR("swapfilename", SYSFS_RW),
14653+ SYSFS_STRING(swapfilename, 255, SYSFS_SM_NOT_NEEDED)
14654+ },
14655+
14656+ {
14657+ SUSPEND2_ATTR("headerlocations", SYSFS_READONLY),
14658+ SYSFS_CUSTOM(header_locations_read_sysfs, NULL, SYSFS_SM_NOT_NEEDED)
14659+ },
14660+
14661+ { SUSPEND2_ATTR("enabled", SYSFS_RW),
14662+ SYSFS_INT(&suspend_swapops.enabled, 0, 1),
14663+ .write_side_effect = attempt_to_parse_resume_device2,
14664+ }
14665+};
14666+
14667+static struct suspend_module_ops suspend_swapops = {
14668+ .type = WRITER_MODULE,
14669+ .name = "Swap Allocator",
14670+ .directory = "swap",
14671+ .module = THIS_MODULE,
14672+ .memory_needed = suspend_swap_memory_needed,
14673+ .print_debug_info = suspend_swap_print_debug_stats,
14674+ .storage_needed = suspend_swap_storage_needed,
14675+ .initialise = suspend_swap_initialise,
14676+ .cleanup = suspend_swap_cleanup,
14677+
14678+ .noresume_reset = suspend_swap_noresume_reset,
14679+ .storage_available = suspend_swap_storage_available,
14680+ .storage_allocated = suspend_swap_storage_allocated,
14681+ .release_storage = suspend_swap_release_storage,
14682+ .allocate_header_space = suspend_swap_allocate_header_space,
14683+ .allocate_storage = suspend_swap_allocate_storage,
14684+ .image_exists = suspend_swap_image_exists,
14685+ .mark_resume_attempted = suspend_swap_mark_resume_attempted,
14686+ .write_header_init = suspend_swap_write_header_init,
14687+ .write_header_cleanup = suspend_swap_write_header_cleanup,
14688+ .read_header_init = suspend_swap_read_header_init,
14689+ .read_header_cleanup = suspend_swap_read_header_cleanup,
14690+ .invalidate_image = suspend_swap_invalidate_image,
14691+ .parse_sig_location = suspend_swap_parse_sig_location,
14692+
14693+ .sysfs_data = sysfs_params,
14694+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
14695+};
14696+
14697+/* ---- Registration ---- */
14698+static __init int suspend_swap_load(void)
14699+{
14700+ suspend_swapops.rw_init = suspend_bio_ops.rw_init;
14701+ suspend_swapops.rw_cleanup = suspend_bio_ops.rw_cleanup;
14702+ suspend_swapops.read_chunk = suspend_bio_ops.read_chunk;
14703+ suspend_swapops.write_chunk = suspend_bio_ops.write_chunk;
14704+ suspend_swapops.rw_header_chunk = suspend_bio_ops.rw_header_chunk;
14705+
14706+ return suspend_register_module(&suspend_swapops);
14707+}
14708+
14709+#ifdef MODULE
14710+static __exit void suspend_swap_unload(void)
14711+{
14712+ suspend_unregister_module(&suspend_swapops);
14713+}
14714+
14715+module_init(suspend_swap_load);
14716+module_exit(suspend_swap_unload);
14717+MODULE_LICENSE("GPL");
14718+MODULE_AUTHOR("Nigel Cunningham");
14719+MODULE_DESCRIPTION("Suspend2 SwapAllocator");
14720+#else
14721+late_initcall(suspend_swap_load);
14722+#endif
14723diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
14724index 0b66659..797787a 100644
14725--- a/kernel/power/swsusp.c
14726+++ b/kernel/power/swsusp.c
14727@@ -49,6 +49,7 @@ #include <linux/swapops.h>
14728 #include <linux/bootmem.h>
14729 #include <linux/syscalls.h>
14730 #include <linux/highmem.h>
14731+#include <linux/freezer.h>
14732
14733 #include "power.h"
14734
14735@@ -190,6 +191,8 @@ int swsusp_shrink_memory(void)
14736 unsigned int i = 0;
14737 char *p = "-\\|/";
14738
14739+ thaw_kernel_threads();
14740+
14741 printk("Shrinking memory... ");
14742 do {
14743 size = 2 * count_highmem_pages();
14744@@ -214,6 +217,8 @@ int swsusp_shrink_memory(void)
14745 } while (tmp > 0);
14746 printk("\bdone (%lu pages freed)\n", pages);
14747
14748+ freeze_processes();
14749+
14750 return 0;
14751 }
14752
14753diff --git a/kernel/power/sysfs.c b/kernel/power/sysfs.c
14754new file mode 100644
14755index 0000000..4abe677
14756--- /dev/null
14757+++ b/kernel/power/sysfs.c
14758@@ -0,0 +1,305 @@
14759+/*
14760+ * kernel/power/sysfs.c
14761+ *
14762+ * Copyright (C) 2002-2006 Nigel Cunningham <nigel@suspend2.net>
14763+ * Copyright (C) 2006 Red Hat, inc.
14764+ *
14765+ * This file is released under the GPLv2.
14766+ *
14767+ * This file contains support for sysfs entries for tuning Suspend2.
14768+ *
14769+ * We have a generic handler that deals with the most common cases, and
14770+ * hooks for special handlers to use.
14771+ */
14772+
14773+#include <linux/suspend.h>
14774+#include <linux/module.h>
14775+#include <asm/uaccess.h>
14776+
14777+#include "sysfs.h"
14778+#include "suspend.h"
14779+#include "storage.h"
14780+
14781+static int suspend_sysfs_initialised = 0;
14782+
14783+static struct suspend_sysfs_data sysfs_params[];
14784+
14785+extern void __suspend_try_resume(void);
14786+
14787+extern struct subsystem power_subsys;
14788+
14789+#define to_sysfs_data(_attr) container_of(_attr, struct suspend_sysfs_data, attr)
14790+
14791+static void suspend_main_wrapper(void)
14792+{
14793+ suspend_main(0);
14794+}
14795+
14796+ssize_t suspend2_attr_show(struct kobject *kobj, struct attribute *attr,
14797+ char *page)
14798+{
14799+ struct suspend_sysfs_data *sysfs_data = to_sysfs_data(attr);
14800+ int len = 0;
14801+
14802+ if (suspend_start_anything(0))
14803+ return -EBUSY;
14804+
14805+ if (sysfs_data->needs_storage_manager & SYSFS_NEEDS_FOR_READ)
14806+ suspend_prepare_usm();
14807+
14808+ switch (sysfs_data->type) {
14809+ case SUSPEND_SYSFS_DATA_CUSTOM:
14810+ len = (sysfs_data->data.special.read_sysfs) ?
14811+ (sysfs_data->data.special.read_sysfs)(page, PAGE_SIZE)
14812+ : 0;
14813+ break;
14814+ case SUSPEND_SYSFS_DATA_BIT:
14815+ len = sprintf(page, "%d\n",
14816+ -test_bit(sysfs_data->data.bit.bit,
14817+ sysfs_data->data.bit.bit_vector));
14818+ break;
14819+ case SUSPEND_SYSFS_DATA_INTEGER:
14820+ len = sprintf(page, "%d\n",
14821+ *(sysfs_data->data.integer.variable));
14822+ break;
14823+ case SUSPEND_SYSFS_DATA_LONG:
14824+ len = sprintf(page, "%ld\n",
14825+ *(sysfs_data->data.a_long.variable));
14826+ break;
14827+ case SUSPEND_SYSFS_DATA_UL:
14828+ len = sprintf(page, "%lu\n",
14829+ *(sysfs_data->data.ul.variable));
14830+ break;
14831+ case SUSPEND_SYSFS_DATA_STRING:
14832+ len = sprintf(page, "%s\n",
14833+ sysfs_data->data.string.variable);
14834+ break;
14835+ }
14836+ /* Side effect routine? */
14837+ if (sysfs_data->read_side_effect)
14838+ sysfs_data->read_side_effect();
14839+
14840+ if (sysfs_data->needs_storage_manager & SYSFS_NEEDS_FOR_READ)
14841+ suspend_cleanup_usm();
14842+
14843+ suspend_finish_anything(0);
14844+
14845+ return len;
14846+}
14847+
14848+#define BOUND(_variable, _type) \
14849+ if (sysfs_data->data._type.maximum) { \
14850+ if (*_variable < sysfs_data->data._type.minimum) \
14851+ *_variable = sysfs_data->data._type.minimum; \
14852+ else if (*_variable > sysfs_data->data._type.maximum) \
14853+ *_variable = sysfs_data->data._type.maximum; \
14854+ }
14855+
14856+ssize_t suspend2_attr_store(struct kobject *kobj, struct attribute *attr,
14857+ const char *my_buf, size_t count)
14858+{
14859+ int assigned_temp_buffer = 0, result = count;
14860+ struct suspend_sysfs_data *sysfs_data = to_sysfs_data(attr);
14861+
14862+ if (suspend_start_anything(sysfs_data == &sysfs_params[0]))
14863+ return -EBUSY;
14864+
14865+ ((char *) my_buf)[count] = 0;
14866+
14867+ if (sysfs_data->needs_storage_manager & SYSFS_NEEDS_FOR_WRITE)
14868+ suspend_prepare_usm();
14869+
14870+ switch (sysfs_data->type) {
14871+ case SUSPEND_SYSFS_DATA_CUSTOM:
14872+ if (sysfs_data->data.special.write_sysfs)
14873+ result = (sysfs_data->data.special.write_sysfs)
14874+ (my_buf, count);
14875+ break;
14876+ case SUSPEND_SYSFS_DATA_BIT:
14877+ {
14878+ int value = simple_strtoul(my_buf, NULL, 0);
14879+ if (value)
14880+ set_bit(sysfs_data->data.bit.bit,
14881+ (sysfs_data->data.bit.bit_vector));
14882+ else
14883+ clear_bit(sysfs_data->data.bit.bit,
14884+ (sysfs_data->data.bit.bit_vector));
14885+ }
14886+ break;
14887+ case SUSPEND_SYSFS_DATA_INTEGER:
14888+ {
14889+ int *variable = sysfs_data->data.integer.variable;
14890+ *variable = simple_strtol(my_buf, NULL, 0);
14891+ BOUND(variable, integer);
14892+ break;
14893+ }
14894+ case SUSPEND_SYSFS_DATA_LONG:
14895+ {
14896+ long *variable = sysfs_data->data.a_long.variable;
14897+ *variable = simple_strtol(my_buf, NULL, 0);
14898+ BOUND(variable, a_long);
14899+ break;
14900+ }
14901+ case SUSPEND_SYSFS_DATA_UL:
14902+ {
14903+ unsigned long *variable = sysfs_data->data.ul.variable;
14904+ *variable = simple_strtoul(my_buf, NULL, 0);
14905+ BOUND(variable, ul);
14906+ break;
14907+ }
14908+ break;
14909+ case SUSPEND_SYSFS_DATA_STRING:
14910+ {
14911+ int copy_len = count;
14912+ char *variable =
14913+ sysfs_data->data.string.variable;
14914+
14915+ if (sysfs_data->data.string.max_length &&
14916+ (copy_len > sysfs_data->data.string.max_length))
14917+ copy_len = sysfs_data->data.string.max_length;
14918+
14919+ if (!variable) {
14920+ sysfs_data->data.string.variable =
14921+ variable = (char *) get_zeroed_page(GFP_ATOMIC);
14922+ assigned_temp_buffer = 1;
14923+ }
14924+ strncpy(variable, my_buf, copy_len);
14925+ if ((copy_len) &&
14926+ (my_buf[copy_len - 1] == '\n'))
14927+ variable[count - 1] = 0;
14928+ variable[count] = 0;
14929+ }
14930+ break;
14931+ }
14932+
14933+ /* Side effect routine? */
14934+ if (sysfs_data->write_side_effect)
14935+ sysfs_data->write_side_effect();
14936+
14937+ /* Free temporary buffers */
14938+ if (assigned_temp_buffer) {
14939+ free_page((unsigned long) sysfs_data->data.string.variable);
14940+ sysfs_data->data.string.variable = NULL;
14941+ }
14942+
14943+ if (sysfs_data->needs_storage_manager & SYSFS_NEEDS_FOR_WRITE)
14944+ suspend_cleanup_usm();
14945+
14946+ suspend_finish_anything(sysfs_data == &sysfs_params[0]);
14947+
14948+ return result;
14949+}
14950+
14951+static struct sysfs_ops suspend2_sysfs_ops = {
14952+ .show = &suspend2_attr_show,
14953+ .store = &suspend2_attr_store,
14954+};
14955+
14956+static struct kobj_type suspend2_ktype = {
14957+ .sysfs_ops = &suspend2_sysfs_ops,
14958+};
14959+
14960+decl_subsys(suspend2, &suspend2_ktype, NULL);
14961+
14962+/* Non-module sysfs entries.
14963+ *
14964+ * This array contains entries that are automatically registered at
14965+ * boot. Modules and the console code register their own entries separately.
14966+ *
14967+ * NB: If you move do_suspend, change suspend_write_sysfs's test so that
14968+ * suspend_start_anything still gets a 1 when the user echos > do_suspend!
14969+ */
14970+
14971+static struct suspend_sysfs_data sysfs_params[] = {
14972+ { SUSPEND2_ATTR("do_suspend", SYSFS_WRITEONLY),
14973+ SYSFS_CUSTOM(NULL, NULL, SYSFS_NEEDS_FOR_WRITE),
14974+ .write_side_effect = suspend_main_wrapper
14975+ },
14976+
14977+ { SUSPEND2_ATTR("do_resume", SYSFS_WRITEONLY),
14978+ SYSFS_CUSTOM(NULL, NULL, SYSFS_NEEDS_FOR_WRITE),
14979+ .write_side_effect = __suspend_try_resume
14980+ },
14981+};
14982+
14983+struct kobject *make_suspend2_sysdir(char *name)
14984+{
14985+ struct kobject *kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
14986+ int err;
14987+
14988+ BUG_ON(!kobj);
14989+
14990+ err = kobject_set_name(kobj, "%s", name);
14991+
14992+ if (err) {
14993+ kfree(kobj);
14994+ return NULL;
14995+ }
14996+
14997+ kobj->kset = &suspend2_subsys.kset;
14998+
14999+ err = kobject_register(kobj);
15000+
15001+ return err ? NULL : kobj;
15002+}
15003+
15004+/* suspend_initialise_sysfs
15005+ *
15006+ * Initialise the /sysfs/suspend2 directory.
15007+ */
15008+
15009+static void suspend_initialise_sysfs(void)
15010+{
15011+ int i, error;
15012+ int numfiles = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data);
15013+
15014+ if (suspend_sysfs_initialised)
15015+ return;
15016+
15017+ /* Make our suspend2 directory a child of /sys/power */
15018+ kobj_set_kset_s(&suspend2_subsys.kset, power_subsys);
15019+ error = subsystem_register(&suspend2_subsys);
15020+
15021+ if (error)
15022+ return;
15023+
15024+ /* Make it use the .store and .show routines above */
15025+ kobj_set_kset_s(&suspend2_subsys.kset, suspend2_subsys);
15026+
15027+ suspend_sysfs_initialised = 1;
15028+
15029+ for (i=0; i< numfiles; i++)
15030+ suspend_register_sysfs_file(&suspend2_subsys.kset.kobj,
15031+ &sysfs_params[i]);
15032+}
15033+
15034+/* suspend_register_sysfs_file
15035+ *
15036+ * Helper for registering a new /sysfs/suspend2 entry.
15037+ */
15038+
15039+int suspend_register_sysfs_file(
15040+ struct kobject *kobj,
15041+ struct suspend_sysfs_data *suspend_sysfs_data)
15042+{
15043+ int result;
15044+
15045+ if (!suspend_sysfs_initialised)
15046+ suspend_initialise_sysfs();
15047+
15048+ if ((result = sysfs_create_file(kobj, &suspend_sysfs_data->attr)))
15049+ printk("Suspend2: sysfs_create_file for %s returned %d.\n",
15050+ suspend_sysfs_data->attr.name, result);
15051+
15052+ return result;
15053+}
15054+
15055+/* suspend_unregister_sysfs_file
15056+ *
15057+ * Helper for removing unwanted /sysfs/suspend2 entries.
15058+ *
15059+ */
15060+void suspend_unregister_sysfs_file(struct suspend_sysfs_data *suspend_sysfs_data)
15061+{
15062+ sysfs_remove_file(&suspend2_subsys.kset.kobj, &suspend_sysfs_data->attr);
15063+}
15064diff --git a/kernel/power/sysfs.h b/kernel/power/sysfs.h
15065new file mode 100644
15066index 0000000..71213d3
15067--- /dev/null
15068+++ b/kernel/power/sysfs.h
15069@@ -0,0 +1,118 @@
15070+/*
15071+ * kernel/power/sysfs.h
15072+ *
15073+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
15074+ * Copyright (C) 2006 Red Hat, inc.
15075+ *
15076+ * This file is released under the GPLv2.
15077+ *
15078+ * It provides declarations for suspend to use in managing
15079+ * /sysfs/suspend2. When we switch to kobjects,
15080+ * this will become redundant.
15081+ *
15082+ */
15083+
15084+#include <linux/sysfs.h>
15085+#include "power.h"
15086+
15087+struct suspend_sysfs_data {
15088+ struct attribute attr;
15089+ int type;
15090+ int needs_storage_manager;
15091+ union {
15092+ struct {
15093+ unsigned long *bit_vector;
15094+ int bit;
15095+ } bit;
15096+ struct {
15097+ int *variable;
15098+ int minimum;
15099+ int maximum;
15100+ } integer;
15101+ struct {
15102+ long *variable;
15103+ long minimum;
15104+ long maximum;
15105+ } a_long;
15106+ struct {
15107+ unsigned long *variable;
15108+ unsigned long minimum;
15109+ unsigned long maximum;
15110+ } ul;
15111+ struct {
15112+ char *variable;
15113+ int max_length;
15114+ } string;
15115+ struct {
15116+ int (*read_sysfs) (const char *buffer, int count);
15117+ int (*write_sysfs) (const char *buffer, int count);
15118+ void *data;
15119+ } special;
15120+ } data;
15121+
15122+ /* Side effects routines. Used, eg, for reparsing the
15123+ * resume2 entry when it changes */
15124+ void (*read_side_effect) (void);
15125+ void (*write_side_effect) (void);
15126+ struct list_head sysfs_data_list;
15127+};
15128+
15129+enum {
15130+ SUSPEND_SYSFS_DATA_NONE = 1,
15131+ SUSPEND_SYSFS_DATA_CUSTOM,
15132+ SUSPEND_SYSFS_DATA_BIT,
15133+ SUSPEND_SYSFS_DATA_INTEGER,
15134+ SUSPEND_SYSFS_DATA_UL,
15135+ SUSPEND_SYSFS_DATA_LONG,
15136+ SUSPEND_SYSFS_DATA_STRING
15137+};
15138+
15139+#define SUSPEND2_ATTR(_name, _mode) \
15140+ .attr = {.name = _name , .mode = _mode }
15141+
15142+#define SYSFS_BIT(_ul, _bit) \
15143+ .type = SUSPEND_SYSFS_DATA_BIT, \
15144+ .data = { .bit = { .bit_vector = _ul, .bit = _bit } }
15145+
15146+#define SYSFS_INT(_int, _min, _max) \
15147+ .type = SUSPEND_SYSFS_DATA_INTEGER, \
15148+ .data = { .integer = { .variable = _int, .minimum = _min, \
15149+ .maximum = _max } }
15150+
15151+#define SYSFS_UL(_ul, _min, _max) \
15152+ .type = SUSPEND_SYSFS_DATA_UL, \
15153+ .data = { .ul = { .variable = _ul, .minimum = _min, \
15154+ .maximum = _max } }
15155+
15156+#define SYSFS_LONG(_long, _min, _max) \
15157+ .type = SUSPEND_SYSFS_DATA_LONG, \
15158+ .data = { .a_long = { .variable = _long, .minimum = _min, \
15159+ .maximum = _max } }
15160+
15161+#define SYSFS_STRING(_string, _max_len, _needs_usm) \
15162+ .type = SUSPEND_SYSFS_DATA_STRING, \
15163+ .needs_storage_manager = _needs_usm, \
15164+ .data = { .string = { .variable = _string, .max_length = _max_len } }
15165+
15166+#define SYSFS_CUSTOM(_read, _write, _needs_storage_manager) \
15167+ .type = SUSPEND_SYSFS_DATA_CUSTOM, \
15168+ .needs_storage_manager = _needs_storage_manager, \
15169+ .data = { .special = { .read_sysfs = _read, .write_sysfs = _write } }
15170+
15171+#define SYSFS_WRITEONLY 0200
15172+#define SYSFS_READONLY 0444
15173+#define SYSFS_RW 0644
15174+
15175+/* Storage manager needed? */
15176+#define SYSFS_SM_NOT_NEEDED 0
15177+#define SYSFS_NEEDS_FOR_READ 1
15178+#define SYSFS_NEEDS_FOR_WRITE 2
15179+#define SYSFS_NEEDS_FOR_BOTH 3
15180+
15181+int suspend_register_sysfs_file(struct kobject *kobj,
15182+ struct suspend_sysfs_data *suspend_sysfs_data);
15183+void suspend_unregister_sysfs_file(struct suspend_sysfs_data *suspend_sysfs_data);
15184+
15185+extern struct subsystem suspend2_subsys;
15186+
15187+struct kobject *make_suspend2_sysdir(char *name);
15188diff --git a/kernel/power/ui.c b/kernel/power/ui.c
15189new file mode 100644
15190index 0000000..6750c54
15191--- /dev/null
15192+++ b/kernel/power/ui.c
15193@@ -0,0 +1,760 @@
15194+/*
15195+ * kernel/power/ui.c
15196+ *
15197+ * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
15198+ * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
15199+ * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr>
15200+ * Copyright (C) 2002-2006 Nigel Cunningham <nigel@suspend2.net>
15201+ * Copyright (C) 2006 Red Hat, inc.
15202+ *
15203+ * This file is released under the GPLv2.
15204+ *
15205+ * Routines for Suspend2's user interface.
15206+ *
15207+ * The user interface code talks to a userspace program via a
15208+ * netlink socket.
15209+ *
15210+ * The kernel side:
15211+ * - starts the userui program;
15212+ * - sends text messages and progress bar status;
15213+ *
15214+ * The user space side:
15215+ * - passes messages regarding user requests (abort, toggle reboot etc)
15216+ *
15217+ */
15218+
15219+#define __KERNEL_SYSCALLS__
15220+
15221+#include <linux/suspend.h>
15222+#include <linux/freezer.h>
15223+#include <linux/console.h>
15224+#include <linux/ctype.h>
15225+#include <linux/tty.h>
15226+#include <linux/vt_kern.h>
15227+#include <linux/module.h>
15228+#include <linux/reboot.h>
15229+#include <linux/kmod.h>
15230+#include <linux/security.h>
15231+#include <linux/syscalls.h>
15232+
15233+#include "sysfs.h"
15234+#include "modules.h"
15235+#include "suspend.h"
15236+#include "ui.h"
15237+#include "netlink.h"
15238+#include "power_off.h"
15239+
15240+static char local_printf_buf[1024]; /* Same as printk - should be safe */
15241+
15242+/*! The console log level we default to. */
15243+int suspend_default_console_level = 0;
15244+
15245+#ifdef CONFIG_NET
15246+static struct user_helper_data ui_helper_data;
15247+static struct suspend_module_ops userui_ops;
15248+static int orig_loglevel;
15249+static int orig_default_message_loglevel;
15250+static int orig_kmsg;
15251+
15252+static char lastheader[512];
15253+static int lastheader_message_len;
15254+extern int console_suspended;
15255+static int ui_helper_changed; /* Used at resume-time so don't overwrite value
15256+ set from initrd/ramfs. */
15257+
15258+/* Number of distinct progress amounts that userspace can display */
15259+static int progress_granularity = 30;
15260+
15261+DECLARE_WAIT_QUEUE_HEAD(userui_wait_for_key);
15262+
15263+static void ui_nl_set_state(int n)
15264+{
15265+ /* Only let them change certain settings */
15266+ static const int suspend_action_mask =
15267+ (1 << SUSPEND_REBOOT) | (1 << SUSPEND_PAUSE) | (1 << SUSPEND_SLOW) |
15268+ (1 << SUSPEND_LOGALL) | (1 << SUSPEND_SINGLESTEP) |
15269+ (1 << SUSPEND_PAUSE_NEAR_PAGESET_END);
15270+
15271+ suspend_action = (suspend_action & (~suspend_action_mask)) |
15272+ (n & suspend_action_mask);
15273+
15274+ if (!test_action_state(SUSPEND_PAUSE) &&
15275+ !test_action_state(SUSPEND_SINGLESTEP))
15276+ wake_up_interruptible(&userui_wait_for_key);
15277+}
15278+
15279+void userui_redraw(void)
15280+{
15281+ suspend_send_netlink_message(&ui_helper_data,
15282+ USERUI_MSG_REDRAW, NULL, 0);
15283+}
15284+
15285+/* request_abort_suspend
15286+ *
15287+ * Description: Handle the user requesting the cancellation of a suspend by
15288+ * pressing escape.
15289+ * Callers: Invoked from a netlink packet from userspace when the user presses
15290+ * escape.
15291+ */
15292+void request_abort_suspend(void)
15293+{
15294+ if (test_result_state(SUSPEND_ABORT_REQUESTED))
15295+ return;
15296+
15297+ if (test_suspend_state(SUSPEND_NOW_RESUMING)) {
15298+ suspend_prepare_status(CLEAR_BAR, "Escape pressed. "
15299+ "Powering down again.");
15300+ suspend_power_down();
15301+ } else {
15302+ suspend_prepare_status(CLEAR_BAR, "--- ESCAPE PRESSED :"
15303+ " ABORTING SUSPEND ---");
15304+ set_result_state(SUSPEND_ABORTED);
15305+ set_result_state(SUSPEND_ABORT_REQUESTED);
15306+
15307+ wake_up_interruptible(&userui_wait_for_key);
15308+ }
15309+}
15310+
15311+static int userui_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
15312+{
15313+ int type;
15314+ int *data;
15315+
15316+ type = nlh->nlmsg_type;
15317+
15318+ /* A control message: ignore them */
15319+ if (type < NETLINK_MSG_BASE)
15320+ return 0;
15321+
15322+ /* Unknown message: reply with EINVAL */
15323+ if (type >= USERUI_MSG_MAX)
15324+ return -EINVAL;
15325+
15326+ /* All operations require privileges, even GET */
15327+ if (security_netlink_recv(skb, CAP_NET_ADMIN))
15328+ return -EPERM;
15329+
15330+ /* Only allow one task to receive NOFREEZE privileges */
15331+ if (type == NETLINK_MSG_NOFREEZE_ME && ui_helper_data.pid != -1)
15332+ return -EBUSY;
15333+
15334+ data = (int*)NLMSG_DATA(nlh);
15335+
15336+ switch (type) {
15337+ case USERUI_MSG_ABORT:
15338+ request_abort_suspend();
15339+ break;
15340+ case USERUI_MSG_GET_STATE:
15341+ suspend_send_netlink_message(&ui_helper_data,
15342+ USERUI_MSG_GET_STATE, &suspend_action,
15343+ sizeof(suspend_action));
15344+ break;
15345+ case USERUI_MSG_GET_DEBUG_STATE:
15346+ suspend_send_netlink_message(&ui_helper_data,
15347+ USERUI_MSG_GET_DEBUG_STATE,
15348+ &suspend_debug_state,
15349+ sizeof(suspend_debug_state));
15350+ break;
15351+ case USERUI_MSG_SET_STATE:
15352+ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(int)))
15353+ return -EINVAL;
15354+ ui_nl_set_state(*data);
15355+ break;
15356+ case USERUI_MSG_SET_DEBUG_STATE:
15357+ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(int)))
15358+ return -EINVAL;
15359+ suspend_debug_state = (*data);
15360+ break;
15361+ case USERUI_MSG_SPACE:
15362+ wake_up_interruptible(&userui_wait_for_key);
15363+ break;
15364+ }
15365+
15366+ return 1;
15367+}
15368+
15369+static int userui_storage_needed(void)
15370+{
15371+ return sizeof(ui_helper_data.program) + 1 + sizeof(int);
15372+}
15373+
15374+static int userui_save_config_info(char *buf)
15375+{
15376+ *((int *) buf) = progress_granularity;
15377+ memcpy(buf + sizeof(int), ui_helper_data.program, sizeof(ui_helper_data.program));
15378+ return sizeof(ui_helper_data.program) + sizeof(int) + 1;
15379+}
15380+
15381+static void userui_load_config_info(char *buf, int size)
15382+{
15383+ progress_granularity = *((int *) buf);
15384+ size -= sizeof(int);
15385+
15386+ /* Don't load the saved path if one has already been set */
15387+ if (ui_helper_changed)
15388+ return;
15389+
15390+ if (size > sizeof(ui_helper_data.program))
15391+ size = sizeof(ui_helper_data.program);
15392+
15393+ memcpy(ui_helper_data.program, buf + sizeof(int), size);
15394+ ui_helper_data.program[sizeof(ui_helper_data.program)-1] = '\0';
15395+}
15396+
15397+static void set_ui_program_set(void)
15398+{
15399+ ui_helper_changed = 1;
15400+}
15401+
15402+static int userui_memory_needed(void)
15403+{
15404+ /* ball park figure of 128 pages */
15405+ return (128 * PAGE_SIZE);
15406+}
15407+
15408+/* suspend_update_status
15409+ *
15410+ * Description: Update the progress bar and (if on) in-bar message.
15411+ * Arguments: UL value, maximum: Current progress percentage (value/max).
15412+ * const char *fmt, ...: Message to be displayed in the middle
15413+ * of the progress bar.
15414+ * Note that a NULL message does not mean that any previous
15415+ * message is erased! For that, you need suspend_prepare_status with
15416+ * clearbar on.
15417+ * Returns: Unsigned long: The next value where status needs to be updated.
15418+ * This is to reduce unnecessary calls to update_status.
15419+ */
15420+unsigned long suspend_update_status(unsigned long value, unsigned long maximum,
15421+ const char *fmt, ...)
15422+{
15423+ static int last_step = -1;
15424+ struct userui_msg_params msg;
15425+ int bitshift;
15426+ int this_step;
15427+ unsigned long next_update;
15428+
15429+ if (ui_helper_data.pid == -1)
15430+ return 0;
15431+
15432+ if ((!maximum) || (!progress_granularity))
15433+ return maximum;
15434+
15435+ if (value < 0)
15436+ value = 0;
15437+
15438+ if (value > maximum)
15439+ value = maximum;
15440+
15441+ /* Try to avoid math problems - we can't do 64 bit math here
15442+ * (and shouldn't need it - anyone got screen resolution
15443+ * of 65536 pixels or more?) */
15444+ bitshift = fls(maximum) - 16;
15445+ if (bitshift > 0) {
15446+ unsigned long temp_maximum = maximum >> bitshift;
15447+ unsigned long temp_value = value >> bitshift;
15448+ this_step = (int)
15449+ (temp_value * progress_granularity / temp_maximum);
15450+ next_update = (((this_step + 1) * temp_maximum /
15451+ progress_granularity) + 1) << bitshift;
15452+ } else {
15453+ this_step = (int) (value * progress_granularity / maximum);
15454+ next_update = ((this_step + 1) * maximum /
15455+ progress_granularity) + 1;
15456+ }
15457+
15458+ if (this_step == last_step)
15459+ return next_update;
15460+
15461+ memset(&msg, 0, sizeof(msg));
15462+
15463+ msg.a = this_step;
15464+ msg.b = progress_granularity;
15465+
15466+ if (fmt) {
15467+ va_list args;
15468+ va_start(args, fmt);
15469+ vsnprintf(msg.text, sizeof(msg.text), fmt, args);
15470+ va_end(args);
15471+ msg.text[sizeof(msg.text)-1] = '\0';
15472+ }
15473+
15474+ suspend_send_netlink_message(&ui_helper_data, USERUI_MSG_PROGRESS,
15475+ &msg, sizeof(msg));
15476+ last_step = this_step;
15477+
15478+ return next_update;
15479+}
15480+
15481+/* __suspend_message.
15482+ *
15483+ * Description: This function is intended to do the same job as printk, but
15484+ * without normally logging what is printed. The point is to be
15485+ * able to get debugging info on screen without filling the logs
15486+ * with "1/534. ^M 2/534^M. 3/534^M"
15487+ *
15488+ * It may be called from an interrupt context - can't sleep!
15489+ *
15490+ * Arguments: int mask: The debugging section(s) this message belongs to.
15491+ * int level: The level of verbosity of this message.
15492+ * int restartline: Whether to output a \r or \n with this line
15493+ * (\n if we're logging all output).
15494+ * const char *fmt, ...: Message to be displayed a la printk.
15495+ */
15496+void __suspend_message(unsigned long section, unsigned long level,
15497+ int normally_logged,
15498+ const char *fmt, ...)
15499+{
15500+ struct userui_msg_params msg;
15501+
15502+ if ((level) && (level > console_loglevel))
15503+ return;
15504+
15505+ memset(&msg, 0, sizeof(msg));
15506+
15507+ msg.a = section;
15508+ msg.b = level;
15509+ msg.c = normally_logged;
15510+
15511+ if (fmt) {
15512+ va_list args;
15513+ va_start(args, fmt);
15514+ vsnprintf(msg.text, sizeof(msg.text), fmt, args);
15515+ va_end(args);
15516+ msg.text[sizeof(msg.text)-1] = '\0';
15517+ }
15518+
15519+ if (test_action_state(SUSPEND_LOGALL))
15520+ printk("%s\n", msg.text);
15521+
15522+ suspend_send_netlink_message(&ui_helper_data, USERUI_MSG_MESSAGE,
15523+ &msg, sizeof(msg));
15524+}
15525+
15526+static void wait_for_key_via_userui(void)
15527+{
15528+ DECLARE_WAITQUEUE(wait, current);
15529+
15530+ add_wait_queue(&userui_wait_for_key, &wait);
15531+ set_current_state(TASK_INTERRUPTIBLE);
15532+
15533+ interruptible_sleep_on(&userui_wait_for_key);
15534+
15535+ set_current_state(TASK_RUNNING);
15536+ remove_wait_queue(&userui_wait_for_key, &wait);
15537+}
15538+
15539+static char suspend_wait_for_keypress(int timeout)
15540+{
15541+ int fd;
15542+ char key = '\0';
15543+ struct termios t, t_backup;
15544+
15545+ if (ui_helper_data.pid != -1) {
15546+ wait_for_key_via_userui();
15547+ key = ' ';
15548+ goto out;
15549+ }
15550+
15551+ /* We should be guaranteed /dev/console exists after populate_rootfs() in
15552+ * init/main.c
15553+ */
15554+ if ((fd = sys_open("/dev/console", O_RDONLY, 0)) < 0) {
15555+ printk("Couldn't open /dev/console.\n");
15556+ goto out;
15557+ }
15558+
15559+ if (sys_ioctl(fd, TCGETS, (long)&t) < 0)
15560+ goto out_close;
15561+
15562+ memcpy(&t_backup, &t, sizeof(t));
15563+
15564+ t.c_lflag &= ~(ISIG|ICANON|ECHO);
15565+ t.c_cc[VMIN] = 0;
15566+ if (timeout)
15567+ t.c_cc[VTIME] = timeout*10;
15568+
15569+ if (sys_ioctl(fd, TCSETS, (long)&t) < 0)
15570+ goto out_restore;
15571+
15572+ while (1) {
15573+ if (sys_read(fd, &key, 1) <= 0) {
15574+ key = '\0';
15575+ break;
15576+ }
15577+ key = tolower(key);
15578+ if (test_suspend_state(SUSPEND_SANITY_CHECK_PROMPT)) {
15579+ if (key == 'c') {
15580+ set_suspend_state(SUSPEND_CONTINUE_REQ);
15581+ break;
15582+ } else if (key == ' ')
15583+ break;
15584+ } else
15585+ break;
15586+ }
15587+
15588+out_restore:
15589+ sys_ioctl(fd, TCSETS, (long)&t_backup);
15590+out_close:
15591+ sys_close(fd);
15592+out:
15593+ return key;
15594+}
15595+
15596+/* abort_suspend
15597+ *
15598+ * Description: Begin to abort a cycle. If this wasn't at the user's request
15599+ * (and we're displaying output), tell the user why and wait for
15600+ * them to acknowledge the message.
15601+ * Arguments: A parameterised string (imagine this is printk) to display,
15602+ * telling the user why we're aborting.
15603+ */
15604+
15605+void abort_suspend(const char *fmt, ...)
15606+{
15607+ va_list args;
15608+ int printed_len = 0;
15609+
15610+ if (!test_result_state(SUSPEND_ABORTED)) {
15611+ if (!test_result_state(SUSPEND_ABORT_REQUESTED)) {
15612+ va_start(args, fmt);
15613+ printed_len = vsnprintf(local_printf_buf,
15614+ sizeof(local_printf_buf), fmt, args);
15615+ va_end(args);
15616+ if (ui_helper_data.pid != -1)
15617+ printed_len = sprintf(local_printf_buf + printed_len,
15618+ " (Press SPACE to continue)");
15619+ suspend_prepare_status(CLEAR_BAR, local_printf_buf);
15620+
15621+ /*
15622+ * Make sure message seen - wait for shift to be
15623+ * released if being pressed
15624+ */
15625+ if (ui_helper_data.pid != -1)
15626+ suspend_wait_for_keypress(0);
15627+ }
15628+ /* Turn on aborting flag */
15629+ set_result_state(SUSPEND_ABORTED);
15630+ }
15631+}
15632+
15633+/* suspend_prepare_status
15634+ * Description: Prepare the 'nice display', drawing the header and version,
15635+ * along with the current action and perhaps also resetting the
15636+ * progress bar.
15637+ * Arguments:
15638+ * int clearbar: Whether to reset the progress bar.
15639+ * const char *fmt, ...: The action to be displayed.
15640+ */
15641+void suspend_prepare_status(int clearbar, const char *fmt, ...)
15642+{
15643+ va_list args;
15644+
15645+ if (fmt) {
15646+ va_start(args, fmt);
15647+ lastheader_message_len = vsnprintf(lastheader, 512, fmt, args);
15648+ va_end(args);
15649+ }
15650+
15651+ if (clearbar)
15652+ suspend_update_status(0, 1, NULL);
15653+
15654+ suspend_message(0, SUSPEND_STATUS, 1, lastheader, NULL);
15655+
15656+ if (ui_helper_data.pid == -1)
15657+ printk(KERN_EMERG "%s\n", lastheader);
15658+}
15659+
15660+/* suspend_cond_pause
15661+ *
15662+ * Description: Potentially pause and wait for the user to tell us to continue.
15663+ * We normally only pause when @pause is set.
15664+ * Arguments: int pause: Whether we normally pause.
15665+ * char *message: The message to display. Not parameterised
15666+ * because it's normally a constant.
15667+ */
15668+
15669+void suspend_cond_pause(int pause, char *message)
15670+{
15671+#if 1 //#ifdef CONFIG_PM_DEBUG
15672+ int displayed_message = 0, last_key = 0;
15673+
15674+ while (last_key != 32 &&
15675+ ui_helper_data.pid != -1 &&
15676+ (!test_result_state(SUSPEND_ABORTED)) &&
15677+ ((test_action_state(SUSPEND_PAUSE) && pause) ||
15678+ (test_action_state(SUSPEND_SINGLESTEP)))) {
15679+ if (!displayed_message) {
15680+ suspend_prepare_status(DONT_CLEAR_BAR,
15681+ "%s Press SPACE to continue.%s",
15682+ message ? message : "",
15683+ (test_action_state(SUSPEND_SINGLESTEP)) ?
15684+ " Single step on." : "");
15685+ displayed_message = 1;
15686+ }
15687+ last_key = suspend_wait_for_keypress(0);
15688+ }
15689+#endif
15690+ schedule();
15691+}
15692+
15693+extern asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd,
15694+ unsigned long arg);
15695+
15696+/* suspend_prepare_console
15697+ *
15698+ * Description: Prepare a console for use, save current settings.
15699+ * Returns: Boolean: Whether an error occured. Errors aren't
15700+ * treated as fatal, but a warning is printed.
15701+ */
15702+void suspend_prepare_console(void)
15703+{
15704+ orig_loglevel = console_loglevel;
15705+ orig_default_message_loglevel = default_message_loglevel;
15706+ orig_kmsg = kmsg_redirect;
15707+ kmsg_redirect = fg_console + 1;
15708+ default_message_loglevel = 1;
15709+ console_loglevel = suspend_default_console_level;
15710+
15711+ ui_helper_data.pid = -1;
15712+
15713+ if (!userui_ops.enabled)
15714+ return;
15715+
15716+ if (!*ui_helper_data.program) {
15717+ printk("suspend_userui: program not configured. suspend_userui disabled.\n");
15718+ return;
15719+ }
15720+
15721+ suspend_netlink_setup(&ui_helper_data);
15722+
15723+ return;
15724+}
15725+
15726+/* suspend_cleanup_console
15727+ *
15728+ * Description: Restore the settings we saved above.
15729+ */
15730+
15731+void suspend_cleanup_console(void)
15732+{
15733+ suspend_default_console_level = console_loglevel;
15734+
15735+ if (ui_helper_data.pid > -1) {
15736+ struct task_struct *t;
15737+
15738+ suspend_send_netlink_message(&ui_helper_data,
15739+ NETLINK_MSG_CLEANUP, NULL, 0);
15740+
15741+ read_lock(&tasklist_lock);
15742+ if ((t = find_task_by_pid(ui_helper_data.pid)))
15743+ t->flags &= ~PF_NOFREEZE;
15744+ read_unlock(&tasklist_lock);
15745+
15746+ suspend_netlink_close(&ui_helper_data);
15747+
15748+ ui_helper_data.pid = -1;
15749+ }
15750+
15751+ console_loglevel = orig_loglevel;
15752+ kmsg_redirect = orig_kmsg;
15753+ default_message_loglevel = orig_default_message_loglevel;
15754+}
15755+#endif
15756+
15757+/* suspend_early_boot_message()
15758+ * Description: Handle errors early in the process of booting.
15759+ * The user may press C to continue booting, perhaps
15760+ * invalidating the image, or space to reboot.
15761+ * This works from either the serial console or normally
15762+ * attached keyboard.
15763+ *
15764+ * Note that we come in here from init, while the kernel is
15765+ * locked. If we want to get events from the serial console,
15766+ * we need to temporarily unlock the kernel.
15767+ *
15768+ * suspend_early_boot_message may also be called post-boot.
15769+ * In this case, it simply printks the message and returns.
15770+ *
15771+ * Arguments: int Whether we are able to erase the image.
15772+ * int default_answer. What to do when we timeout. This
15773+ * will normally be continue, but the user might
15774+ * provide command line options (__setup) to override
15775+ * particular cases.
15776+ * Char *. Pointer to a string explaining why we're moaning.
15777+ */
15778+
15779+#define say(message, a...) printk(KERN_EMERG message, ##a)
15780+#define message_timeout 25 /* message_timeout * 10 must fit in 8 bits */
15781+
15782+int suspend_early_boot_message(int message_detail, int default_answer, char *warning_reason, ...)
15783+{
15784+ unsigned long orig_state = get_suspend_state(), continue_req = 0;
15785+ va_list args;
15786+ int printed_len;
15787+
15788+ if (warning_reason) {
15789+ va_start(args, warning_reason);
15790+ printed_len = vsnprintf(local_printf_buf,
15791+ sizeof(local_printf_buf),
15792+ warning_reason,
15793+ args);
15794+ va_end(args);
15795+ }
15796+
15797+ if (!test_suspend_state(SUSPEND_BOOT_TIME)) {
15798+ printk(name_suspend "%s\n", local_printf_buf);
15799+ return default_answer;
15800+ }
15801+
15802+ /* We might be called directly from do_mounts_initrd if the
15803+ * user fails to set up their initrd properly. We need to
15804+ * enable the keyboard handler by setting the running flag */
15805+ set_suspend_state(SUSPEND_RUNNING);
15806+
15807+#if defined(CONFIG_VT) || defined(CONFIG_SERIAL_CONSOLE)
15808+ console_loglevel = 7;
15809+
15810+ say("=== Suspend2 ===\n\n");
15811+ if (warning_reason) {
15812+ say("BIG FAT WARNING!! %s\n\n", local_printf_buf);
15813+ switch (message_detail) {
15814+ case 0:
15815+ say("If you continue booting, note that any image WILL NOT BE REMOVED.\n");
15816+ say("Suspend is unable to do so because the appropriate modules aren't\n");
15817+ say("loaded. You should manually remove the image to avoid any\n");
15818+ say("possibility of corrupting your filesystem(s) later.\n");
15819+ break;
15820+ case 1:
15821+ say("If you want to use the current suspend image, reboot and try\n");
15822+ say("again with the same kernel that you suspended from. If you want\n");
15823+ say("to forget that image, continue and the image will be erased.\n");
15824+ break;
15825+ }
15826+ say("Press SPACE to reboot or C to continue booting with this kernel\n\n");
15827+ say("Default action if you don't select one in %d seconds is: %s.\n",
15828+ message_timeout,
15829+ default_answer == SUSPEND_CONTINUE_REQ ?
15830+ "continue booting" : "reboot");
15831+ } else {
15832+ say("BIG FAT WARNING!!\n\n");
15833+ say("You have tried to resume from this image before.\n");
15834+ say("If it failed once, it may well fail again.\n");
15835+ say("Would you like to remove the image and boot normally?\n");
15836+ say("This will be equivalent to entering noresume2 on the\n");
15837+ say("kernel command line.\n\n");
15838+ say("Press SPACE to remove the image or C to continue resuming.\n\n");
15839+ say("Default action if you don't select one in %d seconds is: %s.\n",
15840+ message_timeout,
15841+ !!default_answer ?
15842+ "continue resuming" : "remove the image");
15843+ }
15844+
15845+ set_suspend_state(SUSPEND_SANITY_CHECK_PROMPT);
15846+ clear_suspend_state(SUSPEND_CONTINUE_REQ);
15847+
15848+ if (suspend_wait_for_keypress(message_timeout) == 0) /* We timed out */
15849+ continue_req = !!default_answer;
15850+ else
15851+ continue_req = test_suspend_state(SUSPEND_CONTINUE_REQ);
15852+
15853+ if ((warning_reason) && (!continue_req))
15854+ machine_restart(NULL);
15855+
15856+ restore_suspend_state(orig_state);
15857+ if (continue_req)
15858+ set_suspend_state(SUSPEND_CONTINUE_REQ);
15859+
15860+#endif /* CONFIG_VT or CONFIG_SERIAL_CONSOLE */
15861+ return -EPERM;
15862+}
15863+#undef say
15864+
15865+/*
15866+ * User interface specific /sys/power/suspend2 entries.
15867+ */
15868+
15869+static struct suspend_sysfs_data sysfs_params[] = {
15870+#if defined(CONFIG_NET) && defined(CONFIG_SYSFS)
15871+ { SUSPEND2_ATTR("default_console_level", SYSFS_RW),
15872+#if 1 //#ifdef CONFIG_PM_DEBUG
15873+ SYSFS_INT(&suspend_default_console_level, 0, 7)
15874+#else
15875+ SYSFS_INT(&suspend_default_console_level, 0, 1)
15876+#endif
15877+ },
15878+
15879+ { SUSPEND2_ATTR("enable_escape", SYSFS_RW),
15880+ SYSFS_BIT(&suspend_action, SUSPEND_CAN_CANCEL)
15881+ },
15882+
15883+#if 1 //#ifdef CONFIG_PM_DEBUG
15884+ { SUSPEND2_ATTR("debug_sections", SYSFS_RW),
15885+ SYSFS_UL(&suspend_debug_state, 0, 2 << 30)
15886+ },
15887+
15888+ { SUSPEND2_ATTR("log_everything", SYSFS_RW),
15889+ SYSFS_BIT(&suspend_action, SUSPEND_LOGALL)
15890+ },
15891+
15892+ { SUSPEND2_ATTR("pause_between_steps", SYSFS_RW),
15893+ SYSFS_BIT(&suspend_action, SUSPEND_PAUSE)
15894+ },
15895+#endif
15896+ { SUSPEND2_ATTR("enabled", SYSFS_RW),
15897+ SYSFS_INT(&userui_ops.enabled, 0, 1)
15898+ },
15899+
15900+ { SUSPEND2_ATTR("progress_granularity", SYSFS_RW),
15901+ SYSFS_INT(&progress_granularity, 1, 2048)
15902+ },
15903+
15904+ { SUSPEND2_ATTR("program", SYSFS_RW),
15905+ SYSFS_STRING(ui_helper_data.program, 255, SYSFS_SM_NOT_NEEDED),
15906+ .write_side_effect = set_ui_program_set,
15907+ },
15908+#endif
15909+ { SUSPEND2_ATTR("pm_prepare_console", SYSFS_RW),
15910+ SYSFS_BIT(&suspend_action, SUSPEND_PM_PREPARE_CONSOLE)
15911+ }
15912+};
15913+
15914+static struct suspend_module_ops userui_ops = {
15915+ .type = MISC_MODULE,
15916+ .name = "Userspace UI Support",
15917+ .directory = "user_interface",
15918+ .module = THIS_MODULE,
15919+#ifdef CONFIG_NET
15920+ .storage_needed = userui_storage_needed,
15921+ .save_config_info = userui_save_config_info,
15922+ .load_config_info = userui_load_config_info,
15923+ .memory_needed = userui_memory_needed,
15924+#endif
15925+
15926+ .sysfs_data = sysfs_params,
15927+ .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct suspend_sysfs_data),
15928+};
15929+
15930+/* suspend_console_sysfs_init
15931+ * Description: Boot time initialisation for user interface.
15932+ */
15933+static __init int suspend_console_sysfs_init(void)
15934+{
15935+#ifdef CONFIG_NET
15936+ ui_helper_data.nl = NULL;
15937+ ui_helper_data.program[0] = '\0';
15938+ ui_helper_data.pid = -1;
15939+ ui_helper_data.skb_size = sizeof(struct userui_msg_params);
15940+ ui_helper_data.pool_limit = 6;
15941+ ui_helper_data.netlink_id = NETLINK_SUSPEND2_USERUI;
15942+ ui_helper_data.name = "userspace ui";
15943+ ui_helper_data.rcv_msg = userui_user_rcv_msg;
15944+ ui_helper_data.interface_version = 6;
15945+ ui_helper_data.must_init = 0;
15946+ ui_helper_data.not_ready = suspend_cleanup_console;
15947+ init_completion(&ui_helper_data.wait_for_process);
15948+#endif
15949+
15950+ return suspend_register_module(&userui_ops);
15951+}
15952+
15953+late_initcall(suspend_console_sysfs_init);
15954diff --git a/kernel/power/ui.h b/kernel/power/ui.h
15955new file mode 100644
15956index 0000000..a1e1b54
15957--- /dev/null
15958+++ b/kernel/power/ui.h
15959@@ -0,0 +1,89 @@
15960+/*
15961+ * kernel/power/ui.h
15962+ *
15963+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
15964+ * Copyright (C) 2006 Red Hat, inc.
15965+ */
15966+
15967+extern int suspend_default_console_level;
15968+
15969+enum {
15970+ DONT_CLEAR_BAR,
15971+ CLEAR_BAR
15972+};
15973+
15974+enum {
15975+ /* Userspace -> Kernel */
15976+ USERUI_MSG_ABORT = 0x11,
15977+ USERUI_MSG_SET_STATE = 0x12,
15978+ USERUI_MSG_GET_STATE = 0x13,
15979+ USERUI_MSG_GET_DEBUG_STATE = 0x14,
15980+ USERUI_MSG_SET_DEBUG_STATE = 0x15,
15981+ USERUI_MSG_SET_PROGRESS_GRANULARITY = 0x17,
15982+ USERUI_MSG_SPACE = 0x18,
15983+
15984+ /* Kernel -> Userspace */
15985+ USERUI_MSG_MESSAGE = 0x21,
15986+ USERUI_MSG_PROGRESS = 0x22,
15987+ USERUI_MSG_REDRAW = 0x25,
15988+ USERUI_MSG_KEYPRESS = 0x26,
15989+ USERUI_MSG_DEBUG_STATE = 0x29,
15990+
15991+ USERUI_MSG_MAX,
15992+};
15993+
15994+struct userui_msg_params {
15995+ unsigned long a, b, c, d;
15996+ char text[255];
15997+};
15998+
15999+#ifdef CONFIG_NET
16000+
16001+extern unsigned long suspend_update_status(unsigned long value,
16002+ unsigned long maximum, const char *fmt, ...);
16003+extern void suspend_prepare_status (int clearbar, const char *fmt, ...);
16004+extern void suspend_cond_pause(int pause, char *message);
16005+extern void abort_suspend(const char *fmt, ...);
16006+extern void suspend_prepare_console(void);
16007+extern void suspend_cleanup_console(void);
16008+extern void userui_redraw(void);
16009+extern void __suspend_message(unsigned long section, unsigned long level,
16010+ int normally_logged, const char *fmt, ...);
16011+
16012+#if 1 //#ifdef CONFIG_PM_DEBUG
16013+#define suspend_message(sn, lev, log, fmt, a...) \
16014+do { \
16015+ if (!sn || test_debug_state(sn)) \
16016+ __suspend_message(sn, lev, log, fmt, ##a); \
16017+} while(0)
16018+#else /* CONFIG_PM_DEBUG */
16019+#define suspend_message(sn, lev, log, fmt, a...) \
16020+do { \
16021+ if (lev == SUSPEND_STATUS) \
16022+ __suspend_message(sn, lev, log, fmt, ##a); \
16023+} while(0)
16024+#endif /* CONFIG_PM_DEBUG */
16025+
16026+
16027+#else
16028+static inline char suspend_wait_for_keypress(int timeout)
16029+{
16030+ return 0;
16031+}
16032+
16033+static inline unsigned long suspend_update_status(unsigned long value,
16034+ unsigned long maximum, const char *fmt, ...)
16035+{
16036+ return maximum;
16037+}
16038+
16039+static inline void __suspend_message(unsigned long section, unsigned long level,
16040+ int normally_logged,
16041+ const char *fmt, ...) { }
16042+static inline void suspend_prepare_status(int clearbar, const char *fmt, ...) { }
16043+static inline void suspend_cond_pause(int pause, char *message) { }
16044+static inline void abort_suspend(const char *fmt, ...) { }
16045+static inline void suspend_prepare_console(void) { }
16046+static inline void suspend_cleanup_console(void) { }
16047+static inline void userui_redraw(void) { }
16048+#endif
16049diff --git a/kernel/power/user.c b/kernel/power/user.c
16050index d991d3b..00f7d77 100644
16051--- a/kernel/power/user.c
16052+++ b/kernel/power/user.c
16053@@ -19,6 +19,7 @@ #include <linux/swap.h>
16054 #include <linux/swapops.h>
16055 #include <linux/pm.h>
16056 #include <linux/fs.h>
16057+#include <linux/freezer.h>
16058 #include <linux/console.h>
16059 #include <linux/cpu.h>
16060
16061diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
16062index 6dcea9d..015fc63 100644
16063--- a/kernel/rtmutex-tester.c
16064+++ b/kernel/rtmutex-tester.c
16065@@ -13,6 +13,7 @@ #include <linux/smp_lock.h>
16066 #include <linux/spinlock.h>
16067 #include <linux/sysdev.h>
16068 #include <linux/timer.h>
16069+#include <linux/freezer.h>
16070
16071 #include "rtmutex.h"
16072
16073diff --git a/kernel/sched.c b/kernel/sched.c
16074index 3399701..12fdbef 100644
16075--- a/kernel/sched.c
16076+++ b/kernel/sched.c
16077@@ -34,7 +34,7 @@ #include <linux/debug_locks.h>
16078 #include <linux/security.h>
16079 #include <linux/notifier.h>
16080 #include <linux/profile.h>
16081-#include <linux/suspend.h>
16082+#include <linux/freezer.h>
16083 #include <linux/vmalloc.h>
16084 #include <linux/blkdev.h>
16085 #include <linux/delay.h>
16086diff --git a/kernel/signal.c b/kernel/signal.c
16087index df18c16..827ba65 100644
16088--- a/kernel/signal.c
16089+++ b/kernel/signal.c
16090@@ -23,6 +23,7 @@ #include <linux/syscalls.h>
16091 #include <linux/ptrace.h>
16092 #include <linux/signal.h>
16093 #include <linux/capability.h>
16094+#include <linux/freezer.h>
16095 #include <asm/param.h>
16096 #include <asm/uaccess.h>
16097 #include <asm/unistd.h>
16098diff --git a/kernel/timer.c b/kernel/timer.c
16099index c1c7fbc..0901b20 100644
16100--- a/kernel/timer.c
16101+++ b/kernel/timer.c
16102@@ -34,6 +34,7 @@ #include <linux/posix-timers.h>
16103 #include <linux/cpu.h>
16104 #include <linux/syscalls.h>
16105 #include <linux/delay.h>
16106+#include <linux/freezer.h>
16107
16108 #include <asm/uaccess.h>
16109 #include <asm/unistd.h>
16110@@ -1010,6 +1011,15 @@ static inline void calc_load(unsigned lo
16111
16112 active_tasks = count_active_tasks();
16113 for (count -= ticks; count < 0; count += LOAD_FREQ) {
16114+ /* Suspend2 does a lot of work (pagecache I/O) before
16115+ * and after the atomic copy. If we let the load average
16116+ * be updated while suspending, it will be very high post
16117+ * resume. Processes such as some MTAs that stop work
16118+ * while the average is high will be unnecessarily disrupted.
16119+ */
16120+ if (unlikely(freezer_is_on()))
16121+ continue;
16122+
16123 CALC_LOAD(avenrun[0], EXP_1, active_tasks);
16124 CALC_LOAD(avenrun[1], EXP_5, active_tasks);
16125 CALC_LOAD(avenrun[2], EXP_15, active_tasks);
16126diff --git a/lib/Kconfig b/lib/Kconfig
16127index 734ce95..cb31c4f 100644
16128--- a/lib/Kconfig
16129+++ b/lib/Kconfig
16130@@ -43,6 +43,9 @@ config AUDIT_GENERIC
16131 depends on AUDIT && !AUDIT_ARCH
16132 default y
16133
16134+config DYN_PAGEFLAGS
16135+ bool
16136+
16137 #
16138 # compression support is select'ed if needed
16139 #
16140diff --git a/lib/Makefile b/lib/Makefile
16141index cf98fab..80f939c 100644
16142--- a/lib/Makefile
16143+++ b/lib/Makefile
16144@@ -35,6 +35,8 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
16145 lib-y += dec_and_lock.o
16146 endif
16147
16148+obj-$(CONFIG_DYN_PAGEFLAGS) += dyn_pageflags.o
16149+
16150 obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
16151 obj-$(CONFIG_CRC16) += crc16.o
16152 obj-$(CONFIG_CRC32) += crc32.o
16153diff --git a/lib/dyn_pageflags.c b/lib/dyn_pageflags.c
16154new file mode 100644
16155index 0000000..b8cc556
16156--- /dev/null
16157+++ b/lib/dyn_pageflags.c
16158@@ -0,0 +1,251 @@
16159+/*
16160+ * lib/dyn_pageflags.c
16161+ *
16162+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
16163+ *
16164+ * This file is released under the GPLv2.
16165+ *
16166+ * Routines for dynamically allocating and releasing bitmaps
16167+ * used as pseudo-pageflags.
16168+ */
16169+
16170+#include <linux/module.h>
16171+#include <linux/dyn_pageflags.h>
16172+#include <linux/bootmem.h>
16173+#include <linux/mm.h>
16174+
16175+#define page_to_zone_offset(pg) (page_to_pfn(pg) - page_zone(pg)->zone_start_pfn)
16176+
16177+#define pages_for_zone(zone) \
16178+ (DIV_ROUND_UP((zone)->spanned_pages, (PAGE_SIZE << 3)))
16179+
16180+/*
16181+ * clear_dyn_pageflags(dyn_pageflags_t pagemap)
16182+ *
16183+ * Clear an array used to store local page flags.
16184+ *
16185+ */
16186+
16187+void clear_dyn_pageflags(dyn_pageflags_t pagemap)
16188+{
16189+ int i = 0, zone_num = 0;
16190+ struct zone *zone;
16191+
16192+ BUG_ON(!pagemap);
16193+
16194+ for_each_zone(zone) {
16195+ if (!populated_zone(zone))
16196+ continue;
16197+
16198+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
16199+
16200+ for (i = 0; i < pages_for_zone(zone); i++)
16201+ memset((pagemap[zone_num][i]), 0, PAGE_SIZE);
16202+ }
16203+}
16204+
16205+/*
16206+ * allocate_dyn_pageflags(dyn_pageflags_t *pagemap)
16207+ *
16208+ * Allocate a bitmap for dynamic page flags.
16209+ *
16210+ */
16211+int allocate_dyn_pageflags(dyn_pageflags_t *pagemap)
16212+{
16213+ int i, zone_num, zone_pages;
16214+ struct zone *zone;
16215+
16216+ BUG_ON(*pagemap);
16217+
16218+ *pagemap = kzalloc(sizeof(void *) * (1 << ZONETABLE_SHIFT), GFP_ATOMIC);
16219+
16220+ if (!*pagemap) {
16221+ printk("Error. Unable to allocate memory for dynamic pageflags.");
16222+ return -ENOMEM;
16223+ }
16224+
16225+ for_each_zone(zone) {
16226+ if (!populated_zone(zone))
16227+ continue;
16228+
16229+ zone_pages = pages_for_zone(zone);
16230+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
16231+
16232+ (*pagemap)[zone_num] = kzalloc(sizeof(void *) * zone_pages,
16233+ GFP_ATOMIC);
16234+
16235+ if (!(*pagemap)[zone_num]) {
16236+ printk("Error. Unable to allocate memory for "
16237+ "dynamic pageflags.");
16238+ free_dyn_pageflags(pagemap);
16239+ return -ENOMEM;
16240+ }
16241+
16242+ for (i = 0; i < zone_pages; i++) {
16243+ unsigned long address = get_zeroed_page(GFP_ATOMIC);
16244+ (*pagemap)[zone_num][i] = (unsigned long *) address;
16245+ if (!(*pagemap)[zone_num][i]) {
16246+ printk("Error. Unable to allocate memory for "
16247+ "dynamic pageflags.");
16248+ free_dyn_pageflags(pagemap);
16249+ return -ENOMEM;
16250+ }
16251+ }
16252+ }
16253+
16254+ return 0;
16255+}
16256+
16257+/*
16258+ * free_dyn_pageflags(dyn_pageflags_t *pagemap)
16259+ *
16260+ * Free a dynamically allocated pageflags bitmap. For Suspend2 usage, we
16261+ * support data being relocated from slab to pages that don't conflict
16262+ * with the image that will be copied back. This is the reason for the
16263+ * PageSlab tests below.
16264+ *
16265+ */
16266+void free_dyn_pageflags(dyn_pageflags_t *pagemap)
16267+{
16268+ int i = 0, zone_num, zone_pages;
16269+ struct zone *zone;
16270+
16271+ if (!*pagemap)
16272+ return;
16273+
16274+ for_each_zone(zone) {
16275+ if (!populated_zone(zone))
16276+ continue;
16277+
16278+ zone_pages = pages_for_zone(zone);
16279+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
16280+
16281+ /*
16282+ * May be called on an error path in allocating, so this
16283+ * isn't redundant.
16284+ */
16285+ if (!((*pagemap)[zone_num]))
16286+ continue;
16287+
16288+ for (i = 0; i < zone_pages; i++)
16289+ if ((*pagemap)[zone_num][i])
16290+ free_page((unsigned long) (*pagemap)[zone_num][i]);
16291+
16292+ if (PageSlab(virt_to_page((*pagemap)[zone_num])))
16293+ kfree((*pagemap)[zone_num]);
16294+ else
16295+ free_page((unsigned long) (*pagemap)[zone_num]);
16296+ }
16297+
16298+ if (PageSlab(virt_to_page((*pagemap))))
16299+ kfree(*pagemap);
16300+ else
16301+ free_page((unsigned long) (*pagemap));
16302+
16303+ *pagemap = NULL;
16304+ return;
16305+}
16306+
16307+#define GET_BIT_AND_UL(bitmap, page) \
16308+ unsigned long zone_pfn = page_to_zone_offset(page); \
16309+ int zone_num = page_zone_id(page); \
16310+ int pagenum = PAGENUMBER(zone_pfn); \
16311+ int page_offset = PAGEINDEX(zone_pfn); \
16312+ unsigned long *ul = ((*bitmap)[zone_num][pagenum]) + page_offset; \
16313+ int bit = PAGEBIT(zone_pfn);
16314+
16315+/*
16316+ * test_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
16317+ *
16318+ * Is the page flagged in the given bitmap?
16319+ *
16320+ */
16321+
16322+int test_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
16323+{
16324+ GET_BIT_AND_UL(bitmap, page);
16325+ return test_bit(bit, ul);
16326+}
16327+
16328+/*
16329+ * set_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
16330+ *
16331+ * Set the flag for the page in the given bitmap.
16332+ *
16333+ */
16334+
16335+void set_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
16336+{
16337+ GET_BIT_AND_UL(bitmap, page);
16338+ set_bit(bit, ul);
16339+}
16340+
16341+/*
16342+ * clear_dynpageflags(dyn_pageflags_t *bitmap, struct page *page)
16343+ *
16344+ * Clear the flag for the page in the given bitmap.
16345+ *
16346+ */
16347+
16348+void clear_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
16349+{
16350+ GET_BIT_AND_UL(bitmap, page);
16351+ clear_bit(bit, ul);
16352+}
16353+
16354+/*
16355+ * get_next_bit_on(dyn_pageflags_t bitmap, int counter)
16356+ *
16357+ * Given a pfn (possibly -1), find the next pfn in the bitmap that
16358+ * is set. If there are no more flags set, return -1.
16359+ *
16360+ */
16361+
16362+unsigned long get_next_bit_on(dyn_pageflags_t bitmap, unsigned long counter)
16363+{
16364+ struct page *page;
16365+ struct zone *zone;
16366+ unsigned long *ul = NULL;
16367+ unsigned long zone_offset;
16368+ int pagebit, zone_num, first = (counter == max_pfn);
16369+
16370+ if (first)
16371+ counter = first_online_pgdat()->node_zones->zone_start_pfn;
16372+
16373+ page = pfn_to_page(counter);
16374+ zone = page_zone(page);
16375+ zone_num = page_zone_id(page);
16376+ zone_offset = counter - zone->zone_start_pfn;
16377+
16378+ if (first)
16379+ goto test;
16380+
16381+ do {
16382+ zone_offset++;
16383+
16384+ if (zone_offset >= zone->spanned_pages) {
16385+ do {
16386+ zone = next_zone(zone);
16387+ if (!zone)
16388+ return max_pfn;
16389+ } while(!zone->spanned_pages);
16390+
16391+ zone_num = page_zone_id(pfn_to_page(zone->zone_start_pfn));
16392+ zone_offset = 0;
16393+ }
16394+test:
16395+ pagebit = PAGEBIT(zone_offset);
16396+
16397+ if (!pagebit || !ul)
16398+ ul = (bitmap[zone_num][PAGENUMBER(zone_offset)]) + PAGEINDEX(zone_offset);
16399+
16400+ if (!(*ul & ~((1 << pagebit) - 1))) {
16401+ zone_offset += BITS_PER_LONG - pagebit - 1;
16402+ continue;
16403+ }
16404+
16405+ } while(!test_bit(pagebit, ul));
16406+
16407+ return zone->zone_start_pfn + zone_offset;
16408+}
16409+
16410diff --git a/lib/vsprintf.c b/lib/vsprintf.c
16411index bed7229..abc81c8 100644
16412--- a/lib/vsprintf.c
16413+++ b/lib/vsprintf.c
16414@@ -236,6 +236,29 @@ static char * number(char * buf, char *
16415 return buf;
16416 }
16417
16418+/*
16419+ * vsnprintf_used
16420+ *
16421+ * Functionality : Print a string with parameters to a buffer of a
16422+ * limited size. Unlike vsnprintf, we return the number
16423+ * of bytes actually put in the buffer, not the number
16424+ * that would have been put in if it was big enough.
16425+ */
16426+int snprintf_used(char *buffer, int buffer_size, const char *fmt, ...)
16427+{
16428+ int result;
16429+ va_list args;
16430+
16431+ if (!buffer_size)
16432+ return 0;
16433+
16434+ va_start(args, fmt);
16435+ result = vsnprintf(buffer, buffer_size, fmt, args);
16436+ va_end(args);
16437+
16438+ return result > buffer_size ? buffer_size : result;
16439+}
16440+
16441 /**
16442 * vsnprintf - Format a string and place it in a buffer
16443 * @buf: The buffer to place the result into
16444diff --git a/mm/memory.c b/mm/memory.c
16445index 156861f..1782029 100644
16446--- a/mm/memory.c
16447+++ b/mm/memory.c
16448@@ -976,6 +976,15 @@ no_page_table:
16449 return page;
16450 }
16451
16452+/*
16453+ * We want the address of the page for Suspend2 to mark as being in pageset1.
16454+ */
16455+
16456+struct page *suspend2_follow_page(struct mm_struct *mm, unsigned long address)
16457+{
16458+ return follow_page(mm->mmap, address, 0);
16459+}
16460+
16461 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
16462 unsigned long start, int len, int write, int force,
16463 struct page **pages, struct vm_area_struct **vmas)
16464diff --git a/mm/pdflush.c b/mm/pdflush.c
16465index b02102f..8ce0900 100644
16466--- a/mm/pdflush.c
16467+++ b/mm/pdflush.c
16468@@ -21,6 +21,7 @@ #include <linux/fs.h> // Needed by writ
16469 #include <linux/writeback.h> // Prototypes pdflush_operation()
16470 #include <linux/kthread.h>
16471 #include <linux/cpuset.h>
16472+#include <linux/freezer.h>
16473
16474
16475 /*
16476diff --git a/mm/vmscan.c b/mm/vmscan.c
16477index 518540a..ff0a6b7 100644
16478--- a/mm/vmscan.c
16479+++ b/mm/vmscan.c
16480@@ -36,6 +36,7 @@ #include <linux/notifier.h>
16481 #include <linux/rwsem.h>
16482 #include <linux/delay.h>
16483 #include <linux/kthread.h>
16484+#include <linux/freezer.h>
16485
16486 #include <asm/tlbflush.h>
16487 #include <asm/div64.h>
16488@@ -1265,6 +1266,80 @@ out:
16489 return nr_reclaimed;
16490 }
16491
16492+struct lru_save {
16493+ struct zone *zone;
16494+ struct list_head active_list;
16495+ struct list_head inactive_list;
16496+ unsigned long nr_active;
16497+ unsigned long nr_inactive;
16498+ struct lru_save *next;
16499+};
16500+
16501+struct lru_save *lru_save_list;
16502+
16503+static void _relink_lru_list(struct list_head *src, struct list_head *dest)
16504+{
16505+ while (!list_empty(src)) {
16506+ struct page *page = lru_to_page(src);
16507+ list_del(&page->lru);
16508+ list_add(&page->lru, dest);
16509+ }
16510+}
16511+
16512+void unlink_lru_lists(void)
16513+{
16514+ struct zone *zone;
16515+
16516+ for_each_zone(zone) {
16517+ struct lru_save *this;
16518+
16519+ if (!zone->spanned_pages)
16520+ continue;
16521+
16522+ this = (struct lru_save *)
16523+ kzalloc(sizeof(struct lru_save), GFP_ATOMIC);
16524+
16525+ BUG_ON(!this);
16526+
16527+ this->next = lru_save_list;
16528+ lru_save_list = this;
16529+
16530+ this->zone = zone;
16531+
16532+ spin_lock_irq(&zone->lru_lock);
16533+ this->nr_active = zone->nr_active;
16534+ this->nr_inactive = zone->nr_inactive;
16535+ INIT_LIST_HEAD(&this->active_list);
16536+ INIT_LIST_HEAD(&this->inactive_list);
16537+ _relink_lru_list(&zone->active_list, &this->active_list);
16538+ _relink_lru_list(&zone->inactive_list, &this->inactive_list);
16539+ BUG_ON(!list_empty(&zone->active_list));
16540+ BUG_ON(!list_empty(&zone->inactive_list));
16541+ zone->nr_active = zone->nr_inactive = 0;
16542+
16543+ spin_unlock_irq(&zone->lru_lock);
16544+ }
16545+}
16546+
16547+void relink_lru_lists(void)
16548+{
16549+ while(lru_save_list) {
16550+ struct lru_save *this = lru_save_list;
16551+ struct zone *zone = this->zone;
16552+
16553+ lru_save_list = this->next;
16554+
16555+ spin_lock_irq(&zone->lru_lock);
16556+ _relink_lru_list(&this->active_list, &zone->active_list);
16557+ _relink_lru_list(&this->inactive_list, &zone->inactive_list);
16558+ zone->nr_active += this->nr_active;
16559+ zone->nr_inactive += this->nr_inactive;
16560+ spin_unlock_irq(&zone->lru_lock);
16561+
16562+ kfree(this);
16563+ }
16564+}
16565+
16566 /*
16567 * The background pageout daemon, started as a kernel thread
16568 * from the init process.
16569diff --git a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c
16570index dada34a..49effd9 100644
16571--- a/net/rxrpc/krxiod.c
16572+++ b/net/rxrpc/krxiod.c
16573@@ -13,6 +13,7 @@ #include <linux/sched.h>
16574 #include <linux/completion.h>
16575 #include <linux/spinlock.h>
16576 #include <linux/init.h>
16577+#include <linux/freezer.h>
16578 #include <rxrpc/krxiod.h>
16579 #include <rxrpc/transport.h>
16580 #include <rxrpc/peer.h>
16581diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
16582index cea4eb5..3ab0f77 100644
16583--- a/net/rxrpc/krxsecd.c
16584+++ b/net/rxrpc/krxsecd.c
16585@@ -27,6 +27,7 @@ #include <rxrpc/peer.h>
16586 #include <rxrpc/call.h>
16587 #include <linux/udp.h>
16588 #include <linux/ip.h>
16589+#include <linux/freezer.h>
16590 #include <net/sock.h>
16591 #include "internal.h"
16592
16593diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c
16594index 3e74669..9a9b613 100644
16595--- a/net/rxrpc/krxtimod.c
16596+++ b/net/rxrpc/krxtimod.c
16597@@ -13,6 +13,7 @@ #include <linux/module.h>
16598 #include <linux/init.h>
16599 #include <linux/sched.h>
16600 #include <linux/completion.h>
16601+#include <linux/freezer.h>
16602 #include <rxrpc/rxrpc.h>
16603 #include <rxrpc/krxtimod.h>
16604 #include <asm/errno.h>
16605diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
16606index 64ca1f6..1c68956 100644
16607--- a/net/sunrpc/svcsock.c
16608+++ b/net/sunrpc/svcsock.c
16609@@ -32,6 +32,7 @@ #include <linux/slab.h>
16610 #include <linux/netdevice.h>
16611 #include <linux/skbuff.h>
16612 #include <linux/file.h>
16613+#include <linux/freezer.h>
16614 #include <net/sock.h>
16615 #include <net/checksum.h>
16616 #include <net/ip.h>
This page took 1.904672 seconds and 4 git commands to generate.