Merge branch 'hibernate'
* hibernate: PM: Fix suspend_console and resume_console to use only one semaphore PM: Wait for console in resume PM: Fix pm_notifiers during user mode hibernation swsusp: clean up shrink_all_zones() swsusp: dont fiddle with swappiness PM: fix build for CONFIG_PM unset PM/hibernate: fix "swap breaks after hibernation failures" PM/resume: wait for device probing to finish Consolidate driver_probe_done() loops into one place
This commit is contained in:
commit
adfafefd10
|
@ -18,9 +18,11 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/async.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
|
@ -167,6 +169,21 @@ int driver_probe_done(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_for_device_probe
|
||||
* Wait for device probing to be completed.
|
||||
*
|
||||
* Note: this function polls at 100 msec intervals.
|
||||
*/
|
||||
int wait_for_device_probe(void)
|
||||
{
|
||||
/* wait for the known devices to complete their probing */
|
||||
while (driver_probe_done() != 0)
|
||||
msleep(100);
|
||||
async_synchronize_full();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_probe_device - attempt to bind device & driver together
|
||||
* @drv: driver to bind a device to
|
||||
|
|
|
@ -147,6 +147,8 @@ extern void put_driver(struct device_driver *drv);
|
|||
extern struct device_driver *driver_find(const char *name,
|
||||
struct bus_type *bus);
|
||||
extern int driver_probe_done(void);
|
||||
extern int wait_for_device_probe(void);
|
||||
|
||||
|
||||
/* sysfs interface for exporting driver attributes */
|
||||
|
||||
|
|
|
@ -370,10 +370,14 @@ void __init prepare_namespace(void)
|
|||
ssleep(root_delay);
|
||||
}
|
||||
|
||||
/* wait for the known devices to complete their probing */
|
||||
while (driver_probe_done() != 0)
|
||||
msleep(100);
|
||||
async_synchronize_full();
|
||||
/*
|
||||
* wait for the known devices to complete their probing
|
||||
*
|
||||
* Note: this is a potential source of long boot delays.
|
||||
* For example, it is not atypical to wait 5 seconds here
|
||||
* for the touchpad of a laptop to initialize.
|
||||
*/
|
||||
wait_for_device_probe();
|
||||
|
||||
md_run_setup();
|
||||
|
||||
|
@ -399,6 +403,7 @@ void __init prepare_namespace(void)
|
|||
while (driver_probe_done() != 0 ||
|
||||
(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
|
||||
msleep(100);
|
||||
async_synchronize_full();
|
||||
}
|
||||
|
||||
is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
|
||||
|
|
|
@ -281,8 +281,9 @@ static void __init autodetect_raid(void)
|
|||
*/
|
||||
printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
|
||||
printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
|
||||
while (driver_probe_done() < 0)
|
||||
msleep(100);
|
||||
|
||||
wait_for_device_probe();
|
||||
|
||||
fd = sys_open("/dev/md0", 0, 0);
|
||||
if (fd >= 0) {
|
||||
sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
|
||||
|
|
|
@ -78,6 +78,12 @@ void pm_restore_console(void)
|
|||
}
|
||||
set_console(orig_fgconsole);
|
||||
release_console_sem();
|
||||
|
||||
if (vt_waitactive(orig_fgconsole)) {
|
||||
pr_debug("Resume: Can't switch VCs.");
|
||||
return;
|
||||
}
|
||||
|
||||
kmsg_redirect = orig_kmsg;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -594,6 +594,12 @@ static int software_resume(void)
|
|||
int error;
|
||||
unsigned int flags;
|
||||
|
||||
/*
|
||||
* If the user said "noresume".. bail out early.
|
||||
*/
|
||||
if (noresume)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* name_to_dev_t() below takes a sysfs buffer mutex when sysfs
|
||||
* is configured into the kernel. Since the regular hibernate
|
||||
|
@ -610,6 +616,11 @@ static int software_resume(void)
|
|||
mutex_unlock(&pm_mutex);
|
||||
return -ENOENT;
|
||||
}
|
||||
/*
|
||||
* Some device discovery might still be in progress; we need
|
||||
* to wait for this to finish.
|
||||
*/
|
||||
wait_for_device_probe();
|
||||
swsusp_resume_device = name_to_dev_t(resume_file);
|
||||
pr_debug("PM: Resume from partition %s\n", resume_file);
|
||||
} else {
|
||||
|
|
|
@ -95,15 +95,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)
|
|||
data->swap = swsusp_resume_device ?
|
||||
swap_type_of(swsusp_resume_device, 0, NULL) : -1;
|
||||
data->mode = O_RDONLY;
|
||||
error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
|
||||
if (error)
|
||||
pm_notifier_call_chain(PM_POST_RESTORE);
|
||||
} else {
|
||||
data->swap = -1;
|
||||
data->mode = O_WRONLY;
|
||||
error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
|
||||
if (error)
|
||||
pm_notifier_call_chain(PM_POST_HIBERNATION);
|
||||
} else {
|
||||
data->swap = -1;
|
||||
data->mode = O_WRONLY;
|
||||
error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
|
||||
if (error)
|
||||
pm_notifier_call_chain(PM_POST_RESTORE);
|
||||
}
|
||||
if (error)
|
||||
atomic_inc(&snapshot_device_available);
|
||||
|
|
|
@ -73,7 +73,6 @@ EXPORT_SYMBOL(oops_in_progress);
|
|||
* driver system.
|
||||
*/
|
||||
static DECLARE_MUTEX(console_sem);
|
||||
static DECLARE_MUTEX(secondary_console_sem);
|
||||
struct console *console_drivers;
|
||||
EXPORT_SYMBOL_GPL(console_drivers);
|
||||
|
||||
|
@ -891,12 +890,14 @@ void suspend_console(void)
|
|||
printk("Suspending console(s) (use no_console_suspend to debug)\n");
|
||||
acquire_console_sem();
|
||||
console_suspended = 1;
|
||||
up(&console_sem);
|
||||
}
|
||||
|
||||
void resume_console(void)
|
||||
{
|
||||
if (!console_suspend_enabled)
|
||||
return;
|
||||
down(&console_sem);
|
||||
console_suspended = 0;
|
||||
release_console_sem();
|
||||
}
|
||||
|
@ -912,11 +913,9 @@ void resume_console(void)
|
|||
void acquire_console_sem(void)
|
||||
{
|
||||
BUG_ON(in_interrupt());
|
||||
if (console_suspended) {
|
||||
down(&secondary_console_sem);
|
||||
return;
|
||||
}
|
||||
down(&console_sem);
|
||||
if (console_suspended)
|
||||
return;
|
||||
console_locked = 1;
|
||||
console_may_schedule = 1;
|
||||
}
|
||||
|
@ -926,6 +925,10 @@ int try_acquire_console_sem(void)
|
|||
{
|
||||
if (down_trylock(&console_sem))
|
||||
return -1;
|
||||
if (console_suspended) {
|
||||
up(&console_sem);
|
||||
return -1;
|
||||
}
|
||||
console_locked = 1;
|
||||
console_may_schedule = 0;
|
||||
return 0;
|
||||
|
@ -979,7 +982,7 @@ void release_console_sem(void)
|
|||
unsigned wake_klogd = 0;
|
||||
|
||||
if (console_suspended) {
|
||||
up(&secondary_console_sem);
|
||||
up(&console_sem);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -635,7 +635,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
|
|||
|
||||
if (!bdev) {
|
||||
if (bdev_p)
|
||||
*bdev_p = sis->bdev;
|
||||
*bdev_p = bdget(sis->bdev->bd_dev);
|
||||
|
||||
spin_unlock(&swap_lock);
|
||||
return i;
|
||||
|
@ -647,7 +647,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
|
|||
struct swap_extent, list);
|
||||
if (se->start_block == offset) {
|
||||
if (bdev_p)
|
||||
*bdev_p = sis->bdev;
|
||||
*bdev_p = bdget(sis->bdev->bd_dev);
|
||||
|
||||
spin_unlock(&swap_lock);
|
||||
bdput(bdev);
|
||||
|
|
28
mm/vmscan.c
28
mm/vmscan.c
|
@ -2057,31 +2057,31 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
|
|||
int pass, struct scan_control *sc)
|
||||
{
|
||||
struct zone *zone;
|
||||
unsigned long nr_to_scan, ret = 0;
|
||||
enum lru_list l;
|
||||
unsigned long ret = 0;
|
||||
|
||||
for_each_zone(zone) {
|
||||
enum lru_list l;
|
||||
|
||||
if (!populated_zone(zone))
|
||||
continue;
|
||||
|
||||
if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY)
|
||||
continue;
|
||||
|
||||
for_each_evictable_lru(l) {
|
||||
enum zone_stat_item ls = NR_LRU_BASE + l;
|
||||
unsigned long lru_pages = zone_page_state(zone, ls);
|
||||
|
||||
/* For pass = 0, we don't shrink the active list */
|
||||
if (pass == 0 &&
|
||||
(l == LRU_ACTIVE || l == LRU_ACTIVE_FILE))
|
||||
if (pass == 0 && (l == LRU_ACTIVE_ANON ||
|
||||
l == LRU_ACTIVE_FILE))
|
||||
continue;
|
||||
|
||||
zone->lru[l].nr_scan +=
|
||||
(zone_page_state(zone, NR_LRU_BASE + l)
|
||||
>> prio) + 1;
|
||||
zone->lru[l].nr_scan += (lru_pages >> prio) + 1;
|
||||
if (zone->lru[l].nr_scan >= nr_pages || pass > 3) {
|
||||
unsigned long nr_to_scan;
|
||||
|
||||
zone->lru[l].nr_scan = 0;
|
||||
nr_to_scan = min(nr_pages,
|
||||
zone_page_state(zone,
|
||||
NR_LRU_BASE + l));
|
||||
nr_to_scan = min(nr_pages, lru_pages);
|
||||
ret += shrink_list(l, nr_to_scan, zone,
|
||||
sc, prio);
|
||||
if (ret >= nr_pages)
|
||||
|
@ -2089,7 +2089,6 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2112,7 +2111,6 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
|
|||
.may_swap = 0,
|
||||
.swap_cluster_max = nr_pages,
|
||||
.may_writepage = 1,
|
||||
.swappiness = vm_swappiness,
|
||||
.isolate_pages = isolate_pages_global,
|
||||
};
|
||||
|
||||
|
@ -2146,10 +2144,8 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
|
|||
int prio;
|
||||
|
||||
/* Force reclaiming mapped pages in the passes #3 and #4 */
|
||||
if (pass > 2) {
|
||||
if (pass > 2)
|
||||
sc.may_swap = 1;
|
||||
sc.swappiness = 100;
|
||||
}
|
||||
|
||||
for (prio = DEF_PRIORITY; prio >= 0; prio--) {
|
||||
unsigned long nr_to_scan = nr_pages - ret;
|
||||
|
|
Loading…
Reference in New Issue