Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm-for-3.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael J. Wysocki:
"Fix for an issue causing hibernation to hang on systems with highmem
(that practically means i386) due to broken memory management (bug
introduced in 3.2, so -stable material) and PM documentation update
making the freezer documentation follow the code again after some
recent updates."

* tag 'pm-for-3.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM / Freezer / Docs: Update documentation about freezing of tasks
PM / Hibernate: fix the number of pages used for hibernate/thaw buffering

+41 -24
+19 -18
Documentation/power/freezing-of-tasks.txt
··· 9 9 10 10 II. How does it work? 11 11 12 - There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE 12 + There are three per-task flags used for that, PF_NOFREEZE, PF_FROZEN 13 13 and PF_FREEZER_SKIP (the last one is auxiliary). The tasks that have 14 14 PF_NOFREEZE unset (all user space processes and some kernel threads) are 15 15 regarded as 'freezable' and treated in a special way before the system enters a ··· 17 17 we only consider hibernation, but the description also applies to suspend). 18 18 19 19 Namely, as the first step of the hibernation procedure the function 20 - freeze_processes() (defined in kernel/power/process.c) is called. It executes 21 - try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and 22 - either wakes them up, if they are kernel threads, or sends fake signals to them, 23 - if they are user space processes. A task that has TIF_FREEZE set, should react 24 - to it by calling the function called __refrigerator() (defined in 25 - kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state 26 - to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it. 27 - Then, we say that the task is 'frozen' and therefore the set of functions 28 - handling this mechanism is referred to as 'the freezer' (these functions are 29 - defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h). 30 - User space processes are generally frozen before kernel threads. 20 + freeze_processes() (defined in kernel/power/process.c) is called. A system-wide 21 + variable system_freezing_cnt (as opposed to a per-task flag) is used to indicate 22 + whether the system is to undergo a freezing operation. And freeze_processes() 23 + sets this variable. After this, it executes try_to_freeze_tasks() that sends a 24 + fake signal to all user space processes, and wakes up all the kernel threads. 25 + All freezable tasks must react to that by calling try_to_freeze(), which 26 + results in a call to __refrigerator() (defined in kernel/freezer.c), which sets 27 + the task's PF_FROZEN flag, changes its state to TASK_UNINTERRUPTIBLE and makes 28 + it loop until PF_FROZEN is cleared for it. Then, we say that the task is 29 + 'frozen' and therefore the set of functions handling this mechanism is referred 30 + to as 'the freezer' (these functions are defined in kernel/power/process.c, 31 + kernel/freezer.c & include/linux/freezer.h). User space processes are generally 32 + frozen before kernel threads. 31 33 32 34 __refrigerator() must not be called directly. Instead, use the 33 35 try_to_freeze() function (defined in include/linux/freezer.h), that checks 34 - the task's TIF_FREEZE flag and makes the task enter __refrigerator() if the 35 - flag is set. 36 + if the task is to be frozen and makes the task enter __refrigerator(). 36 37 37 38 For user space processes try_to_freeze() is called automatically from the 38 39 signal-handling code, but the freezable kernel threads need to call it 39 40 explicitly in suitable places or use the wait_event_freezable() or 40 41 wait_event_freezable_timeout() macros (defined in include/linux/freezer.h) 41 - that combine interruptible sleep with checking if TIF_FREEZE is set and calling 42 - try_to_freeze(). The main loop of a freezable kernel thread may look like the 43 - following one: 42 + that combine interruptible sleep with checking if the task is to be frozen and 43 + calling try_to_freeze(). The main loop of a freezable kernel thread may look 44 + like the following one: 44 45 45 46 set_freezable(); 46 47 do { ··· 54 53 (from drivers/usb/core/hub.c::hub_thread()). 55 54 56 55 If a freezable kernel thread fails to call try_to_freeze() after the freezer has 57 - set TIF_FREEZE for it, the freezing of tasks will fail and the entire 56 + initiated a freezing operation, the freezing of tasks will fail and the entire 58 57 hibernation operation will be cancelled. For this reason, freezable kernel 59 58 threads must call try_to_freeze() somewhere or use one of the 60 59 wait_event_freezable() and wait_event_freezable_timeout() macros.
+22 -6
kernel/power/swap.c
··· 51 51 52 52 #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) 53 53 54 + /* 55 + * Number of free pages that are not high. 56 + */ 57 + static inline unsigned long low_free_pages(void) 58 + { 59 + return nr_free_pages() - nr_free_highpages(); 60 + } 61 + 62 + /* 63 + * Number of pages required to be kept free while writing the image. Always 64 + * half of all available low pages before the writing starts. 65 + */ 66 + static inline unsigned long reqd_free_pages(void) 67 + { 68 + return low_free_pages() / 2; 69 + } 70 + 54 71 struct swap_map_page { 55 72 sector_t entries[MAP_PAGE_ENTRIES]; 56 73 sector_t next_swap; ··· 89 72 sector_t cur_swap; 90 73 sector_t first_sector; 91 74 unsigned int k; 92 - unsigned long nr_free_pages, written; 75 + unsigned long reqd_free_pages; 93 76 u32 crc32; 94 77 }; 95 78 ··· 333 316 goto err_rel; 334 317 } 335 318 handle->k = 0; 336 - handle->nr_free_pages = nr_free_pages() >> 1; 337 - handle->written = 0; 319 + handle->reqd_free_pages = reqd_free_pages(); 338 320 handle->first_sector = handle->cur_swap; 339 321 return 0; 340 322 err_rel: ··· 368 352 handle->cur_swap = offset; 369 353 handle->k = 0; 370 354 } 371 - if (bio_chain && ++handle->written > handle->nr_free_pages) { 355 + if (bio_chain && low_free_pages() <= handle->reqd_free_pages) { 372 356 error = hib_wait_on_bio_chain(bio_chain); 373 357 if (error) 374 358 goto out; 375 - handle->written = 0; 359 + handle->reqd_free_pages = reqd_free_pages(); 376 360 } 377 361 out: 378 362 return error; ··· 634 618 * Adjust number of free pages after all allocations have been done. 635 619 * We don't want to run out of pages when writing. 636 620 */ 637 - handle->nr_free_pages = nr_free_pages() >> 1; 621 + handle->reqd_free_pages = reqd_free_pages(); 638 622 639 623 /* 640 624 * Start the CRC32 thread.