From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Sebastian Ott <sebott@linux.vnet.ibm.com>,
linux-pm@lists.linux-foundation.org,
linux-kernel@vger.kernel.org,
Benjamin Herrenschmidt <benh@kernel.crashing.org>,
KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Subject: Re: [RFC][PATCH] PM: disable nonboot cpus before suspending devices
Date: Thu, 4 Feb 2010 01:50:26 +0100 [thread overview]
Message-ID: <201002040150.26503.rjw@sisk.pl> (raw)
In-Reply-To: <20100203150803.5a4b37fe.akpm@linux-foundation.org>
On Thursday 04 February 2010, Andrew Morton wrote:
> On Wed, 3 Feb 2010 23:34:37 +0100
> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
>
> > On Wednesday 03 February 2010, Andrew Morton wrote:
> > > On Wed, 3 Feb 2010 02:44:23 +0100 "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> > >
> > > > +static inline gfp_t clear_gfp_allowed_mask(gfp_t mask)
> > > > +{
> > > > + gfp_t ret = gfp_allowed_mask;
> > > > + gfp_allowed_mask &= ~mask;
> > > > + return ret;
> > > > +}
> > >
> > > Fair enuf.
> > >
> > > Of course, this is all horridly racy/buggy without locking. Would I be
> > > correct in hoping that all the callers happen when the system is in
> > > everyone-is-frozen mode?
> >
> > As far as I can tell, gfp_allowed_mask is only touched during init apart from
> > this.
>
> Well yes - the new interfaces are the problem - they're racy!
>
> > > Perhaps we should add some documentation (or even an assertion) to
> > > prevent someone from using these interfaces from within normal code.
> >
> > I thought about that, but didn't invent anything smart enough.
> >
> > Well, maybe except for a comment like "this must be called with pm_mutex held",
> > because that's the only case when it would be really safe.
>
> Is that the locking rule? My above guess was incorrect?
>
> Maybe slip a
>
> BUG_ON(!mutex_is_locked(&pm_mutex));
>
> in there?
That actually is a good idea, although I prefer WARN_ON (BUG_ON would be
rather blunt, so to speak, as it could kill setups not using suspend/hibernate
at all).
Updated patch follows.
Rafael
---
From: Rafael J. Wysocki <rjw@sisk.pl>
Subject: MM / PM: Force GFP_NOIO during suspend/hibernation and resume (rev. 3)
There are quite a few GFP_KERNEL memory allocations made during
suspend/hibernation and resume that may cause the system to hang,
because the I/O operations they depend on cannot be completed due to
the underlying devices being suspended.
Mitigate this problem by clearing the __GFP_IO and __GFP_FS bits in
gfp_allowed_mask before suspend/hibernation and restoring the
original values of these bits in gfp_allowed_mask durig the
subsequent resume.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reported-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
include/linux/gfp.h | 7 +++----
init/main.c | 2 +-
kernel/power/hibernate.c | 9 +++++++++
kernel/power/suspend.c | 3 +++
mm/page_alloc.c | 24 ++++++++++++++++++++++++
5 files changed, 40 insertions(+), 5 deletions(-)
Index: linux-2.6/include/linux/gfp.h
===================================================================
--- linux-2.6.orig/include/linux/gfp.h
+++ linux-2.6/include/linux/gfp.h
@@ -83,6 +83,7 @@ struct vm_area_struct;
#define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
__GFP_HARDWALL | __GFP_HIGHMEM | \
__GFP_MOVABLE)
+#define GFP_IOFS (__GFP_IO | __GFP_FS)
#ifdef CONFIG_NUMA
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
@@ -337,9 +338,7 @@ void drain_local_pages(void *dummy);
extern gfp_t gfp_allowed_mask;
-static inline void set_gfp_allowed_mask(gfp_t mask)
-{
- gfp_allowed_mask = mask;
-}
+extern void set_gfp_allowed_mask(gfp_t mask);
+extern gfp_t clear_gfp_allowed_mask(gfp_t mask);
#endif /* __LINUX_GFP_H */
Index: linux-2.6/init/main.c
===================================================================
--- linux-2.6.orig/init/main.c
+++ linux-2.6/init/main.c
@@ -601,7 +601,7 @@ asmlinkage void __init start_kernel(void
local_irq_enable();
/* Interrupts are enabled now so all GFP allocations are safe. */
- set_gfp_allowed_mask(__GFP_BITS_MASK);
+ gfp_allowed_mask = __GFP_BITS_MASK;
kmem_cache_init_late();
Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c
+++ linux-2.6/mm/page_alloc.c
@@ -76,6 +76,30 @@ unsigned long totalreserve_pages __read_
int percpu_pagelist_fraction;
gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
+/*
+ * The following functions are used by the suspend/hibernate code to temporarily
+ * change gfp_allowed_mask in order to avoid using I/O during memory allocations
+ * while devices are suspended. To avoid races with the suspend/hibernate code,
+ * they should always be called with pm_mutex held (gfp_allowed_mask also should
+ * only be modified with pm_mutex held, unless the suspend/hibernate code is
+ * guaranteed not to run in parallel with that modification).
+ */
+
+void set_gfp_allowed_mask(gfp_t mask)
+{
+ WARN_ON(!mutex_is_locked(&pm_mutex));
+ gfp_allowed_mask = mask;
+}
+
+gfp_t clear_gfp_allowed_mask(gfp_t mask)
+{
+ gfp_t ret = gfp_allowed_mask;
+
+ WARN_ON(!mutex_is_locked(&pm_mutex));
+ gfp_allowed_mask &= ~mask;
+ return ret;
+}
+
#ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
int pageblock_order __read_mostly;
#endif
Index: linux-2.6/kernel/power/hibernate.c
===================================================================
--- linux-2.6.orig/kernel/power/hibernate.c
+++ linux-2.6/kernel/power/hibernate.c
@@ -323,6 +323,7 @@ static int create_image(int platform_mod
int hibernation_snapshot(int platform_mode)
{
int error;
+ gfp_t saved_mask;
error = platform_begin(platform_mode);
if (error)
@@ -334,6 +335,7 @@ int hibernation_snapshot(int platform_mo
goto Close;
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
error = dpm_suspend_start(PMSG_FREEZE);
if (error)
goto Recover_platform;
@@ -351,6 +353,7 @@ int hibernation_snapshot(int platform_mo
dpm_resume_end(in_suspend ?
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+ set_gfp_allowed_mask(saved_mask);
resume_console();
Close:
platform_end(platform_mode);
@@ -445,14 +448,17 @@ static int resume_target_kernel(bool pla
int hibernation_restore(int platform_mode)
{
int error;
+ gfp_t saved_mask;
pm_prepare_console();
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
error = dpm_suspend_start(PMSG_QUIESCE);
if (!error) {
error = resume_target_kernel(platform_mode);
dpm_resume_end(PMSG_RECOVER);
}
+ set_gfp_allowed_mask(saved_mask);
resume_console();
pm_restore_console();
return error;
@@ -466,6 +472,7 @@ int hibernation_restore(int platform_mod
int hibernation_platform_enter(void)
{
int error;
+ gfp_t saved_mask;
if (!hibernation_ops)
return -ENOSYS;
@@ -481,6 +488,7 @@ int hibernation_platform_enter(void)
entering_platform_hibernation = true;
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
error = dpm_suspend_start(PMSG_HIBERNATE);
if (error) {
if (hibernation_ops->recover)
@@ -518,6 +526,7 @@ int hibernation_platform_enter(void)
Resume_devices:
entering_platform_hibernation = false;
dpm_resume_end(PMSG_RESTORE);
+ set_gfp_allowed_mask(saved_mask);
resume_console();
Close:
Index: linux-2.6/kernel/power/suspend.c
===================================================================
--- linux-2.6.orig/kernel/power/suspend.c
+++ linux-2.6/kernel/power/suspend.c
@@ -198,6 +198,7 @@ static int suspend_enter(suspend_state_t
int suspend_devices_and_enter(suspend_state_t state)
{
int error;
+ gfp_t saved_mask;
if (!suspend_ops)
return -ENOSYS;
@@ -208,6 +209,7 @@ int suspend_devices_and_enter(suspend_st
goto Close;
}
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
@@ -224,6 +226,7 @@ int suspend_devices_and_enter(suspend_st
suspend_test_start();
dpm_resume_end(PMSG_RESUME);
suspend_test_finish("resume devices");
+ set_gfp_allowed_mask(saved_mask);
resume_console();
Close:
if (suspend_ops->end)
next prev parent reply other threads:[~2010-02-04 0:49 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-01-22 18:00 [RFC][PATCH] PM: disable nonboot cpus before suspending devices Sebastian Ott
2010-01-22 20:48 ` Rafael J. Wysocki
2010-01-22 21:24 ` Rafael J. Wysocki
2010-01-22 21:24 ` Rafael J. Wysocki
2010-01-22 21:24 ` Rafael J. Wysocki
2010-01-22 21:24 ` Rafael J. Wysocki
2010-01-25 15:08 ` Sebastian Ott
2010-01-25 21:37 ` Rafael J. Wysocki
2010-01-25 21:37 ` Rafael J. Wysocki
2010-02-01 14:41 ` Sebastian Ott
2010-02-01 15:30 ` Rafael J. Wysocki
2010-02-01 15:30 ` Rafael J. Wysocki
2010-02-01 15:43 ` Maxim Levitsky
2010-02-01 15:43 ` Maxim Levitsky
2010-02-01 15:57 ` Andrew Morton
2010-02-03 1:44 ` Rafael J. Wysocki
2010-02-03 1:48 ` Andrew Morton
2010-02-03 22:34 ` Rafael J. Wysocki
2010-02-03 22:34 ` Rafael J. Wysocki
2010-02-03 23:08 ` Andrew Morton
2010-02-03 23:08 ` Andrew Morton
2010-02-04 0:50 ` Rafael J. Wysocki [this message]
2010-02-04 1:21 ` Andrew Morton
2010-02-04 1:41 ` Andrew Morton
2010-02-04 1:41 ` Andrew Morton
2010-02-04 19:33 ` Rafael J. Wysocki
2010-02-04 19:33 ` Rafael J. Wysocki
2010-02-04 1:21 ` Andrew Morton
2010-02-04 0:50 ` Rafael J. Wysocki
2010-02-03 1:48 ` Andrew Morton
2010-02-03 1:44 ` Rafael J. Wysocki
2010-02-01 15:57 ` Andrew Morton
2010-02-01 14:41 ` Sebastian Ott
2010-01-25 15:08 ` Sebastian Ott
2010-01-22 20:48 ` Rafael J. Wysocki
-- strict thread matches above, loose matches on Subject: below --
2010-01-22 18:00 Sebastian Ott
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201002040150.26503.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=akpm@linux-foundation.org \
--cc=benh@kernel.crashing.org \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=sebott@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.