From: Nigel Cunningham <nigel@tuxonice.net>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Linux PM list <linux-pm@vger.kernel.org>,
LKML <linux-kernel@vger.kernel.org>, Jan Kara <jack@suse.cz>,
linux-fsdevel@vger.kernel.org, Dave Chinner <david@fromorbit.com>,
Pavel Machek <pavel@ucw.cz>,
"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Subject: Re: [RFC][PATCH] PM / Sleep: Freeze filesystems during system suspend/hibernation
Date: Sun, 29 Jan 2012 08:23:54 +1100 [thread overview]
Message-ID: <4F24676A.4070907@tuxonice.net> (raw)
In-Reply-To: <201201281445.49377.rjw@sisk.pl>
Hi.
On 29/01/12 00:45, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
>
> Freeze all filesystems during system suspend and (kernel-driven)
> hibernation by calling freeze_supers() for all superblocks and thaw
> them during the subsequent resume with the help of thaw_supers().
>
> This makes filesystems stay in a consistent state in case something
> goes wrong between system suspend (or hibernation) and the subsequent
> resume (e.g. journal replays won't be necessary in those cases). In
> particular, this should help to solve a long-standing issue that, in
> some cases, during resume from hibernation the boot loader causes the
> journal to be replied for the filesystem containing the kernel image
> and/or initrd causing it to become inconsistent with the information
> stored in the hibernation image.
>
> The user-space-driven hibernation (s2disk) is not covered by this
> change, because the freezing of filesystems prevents s2disk from
> accessing device special files it needs to do its job.
>
> This change is based on earlier work by Nigel Cunningham.
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
> fs/super.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/fs.h | 3 +
> kernel/power/hibernate.c | 11 +++++--
> kernel/power/power.h | 23 --------------
> kernel/power/suspend.c | 42 +++++++++++++++++++++++++++
> 5 files changed, 128 insertions(+), 24 deletions(-)
>
> Index: linux/include/linux/fs.h
> ===================================================================
> --- linux.orig/include/linux/fs.h
> +++ linux/include/linux/fs.h
> @@ -210,6 +210,7 @@ struct inodes_stat_t {
> #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
> #define MS_I_VERSION (1<<23) /* Update inode I_version field */
> #define MS_STRICTATIME (1<<24) /* Always perform atime updates */
> +#define MS_FROZEN (1<<25) /* Frozen filesystem */
> #define MS_NOSEC (1<<28)
> #define MS_BORN (1<<29)
> #define MS_ACTIVE (1<<30)
> @@ -2501,6 +2502,8 @@ extern void drop_super(struct super_bloc
> extern void iterate_supers(void (*)(struct super_block *, void *), void *);
> extern void iterate_supers_type(struct file_system_type *,
> void (*)(struct super_block *, void *), void *);
> +extern int freeze_supers(void);
> +extern void thaw_supers(void);
>
> extern int dcache_dir_open(struct inode *, struct file *);
> extern int dcache_dir_close(struct inode *, struct file *);
> Index: linux/fs/super.c
> ===================================================================
> --- linux.orig/fs/super.c
> +++ linux/fs/super.c
> @@ -594,6 +594,79 @@ void iterate_supers_type(struct file_sys
> EXPORT_SYMBOL(iterate_supers_type);
>
> /**
> + * thaw_supers - call thaw_super() for all superblocks
> + */
> +void thaw_supers(void)
> +{
> + struct super_block *sb, *p = NULL;
> +
> + spin_lock(&sb_lock);
> + list_for_each_entry(sb, &super_blocks, s_list) {
> + if (list_empty(&sb->s_instances))
> + continue;
> + sb->s_count++;
> + spin_unlock(&sb_lock);
> +
> + if (sb->s_flags & MS_FROZEN) {
> + thaw_super(sb);
> + sb->s_flags &= ~MS_FROZEN;
> + }
> +
> + spin_lock(&sb_lock);
> + if (p)
> + __put_super(p);
> + p = sb;
> + }
> + if (p)
> + __put_super(p);
> + spin_unlock(&sb_lock);
> +}
It might be helpful to explain why you delay calling __put_super (I
can't see why, though I realise that fs/super.c does it this way too),
and perhaps also where the balancing get is (it's not obvious that
s->count++ is the open coded get).
> +
> +/**
> + * freeze_supers - call freeze_super() for all superblocks
> + */
> +int freeze_supers(void)
> +{
> + struct super_block *sb, *p = NULL;
> + int error = 0;
> +
> + spin_lock(&sb_lock);
> + /*
> + * Freeze in reverse order so filesystems depending on others are
> + * frozen in the right order (eg. loopback on ext3).
> + */
> + list_for_each_entry_reverse(sb, &super_blocks, s_list) {
> + if (list_empty(&sb->s_instances))
> + continue;
> + sb->s_count++;
> + spin_unlock(&sb_lock);
> +
> + if (sb->s_root && sb->s_frozen != SB_FREEZE_TRANS
> + && !(sb->s_flags & MS_RDONLY)) {
> + error = freeze_super(sb);
No chance of a race against another caller of freeze_super, right?
(Userspace is already frozen and kernel threads aren't going to invoke
this without pushing). Might be good to document that there's no locking
in freeze_super anyway?
> + if (!error)
> + sb->s_flags |= MS_FROZEN;
> + }
> +
> + spin_lock(&sb_lock);
> + if (error)
> + break;
> + if (p)
> + __put_super(p);
> + p = sb;
> + }
> + if (p)
> + __put_super(p);
> + spin_unlock(&sb_lock);
> +
> + if (error)
> + thaw_supers();
> +
> + return error;
> +}
> +
> +
> +/**
> * get_super - get the superblock of a device
> * @bdev: device to get the superblock for
> *
> Index: linux/kernel/power/power.h
> ===================================================================
> --- linux.orig/kernel/power/power.h
> +++ linux/kernel/power/power.h
> @@ -1,3 +1,4 @@
> +#include <linux/fs.h>
> #include <linux/suspend.h>
> #include <linux/suspend_ioctls.h>
> #include <linux/utsname.h>
> @@ -227,25 +228,3 @@ enum {
> #define TEST_MAX (__TEST_AFTER_LAST - 1)
>
> extern int pm_test_level;
> -
> -#ifdef CONFIG_SUSPEND_FREEZER
> -static inline int suspend_freeze_processes(void)
> -{
> - int error = freeze_processes();
> - return error ? : freeze_kernel_threads();
> -}
> -
> -static inline void suspend_thaw_processes(void)
> -{
> - thaw_processes();
> -}
> -#else
> -static inline int suspend_freeze_processes(void)
> -{
> - return 0;
> -}
> -
> -static inline void suspend_thaw_processes(void)
> -{
> -}
> -#endif
> Index: linux/kernel/power/suspend.c
> ===================================================================
> --- linux.orig/kernel/power/suspend.c
> +++ linux/kernel/power/suspend.c
> @@ -29,6 +29,48 @@
>
> #include "power.h"
>
> +#ifdef CONFIG_SUSPEND_FREEZER
> +
> +static inline int suspend_freeze_processes(void)
> +{
> + int error;
> +
> + error = freeze_processes();
> + if (error)
> + return error;
> +
> + error = freeze_supers();
> + if (error) {
> + thaw_processes();
> + return error;
> + }
> +
> + error = freeze_kernel_threads();
> + if (error)
> + thaw_supers();
Comment why there's no matching thaw_processes() as well?
That's all from me.
Regards,
Nigel
> +
> + return error;
> +}
> +
> +static inline void suspend_thaw_processes(void)
> +{
> + thaw_supers();
> + thaw_processes();
> +}
> +
> +#else /* !CONFIG_SUSPEND_FREEZER */
> +
> +static inline int suspend_freeze_processes(void)
> +{
> + return 0;
> +}
> +
> +static inline void suspend_thaw_processes(void)
> +{
> +}
> +
> +#endif /* !CONFIG_SUSPEND_FREEZER */
> +
> const char *const pm_states[PM_SUSPEND_MAX] = {
> [PM_SUSPEND_STANDBY] = "standby",
> [PM_SUSPEND_MEM] = "mem",
> Index: linux/kernel/power/hibernate.c
> ===================================================================
> --- linux.orig/kernel/power/hibernate.c
> +++ linux/kernel/power/hibernate.c
> @@ -626,12 +626,17 @@ int hibernate(void)
> if (error)
> goto Finish;
>
> - error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
> + error = freeze_supers();
> if (error)
> goto Thaw;
> +
> + error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
> + if (error)
> + goto Thaw_fs;
> +
> if (freezer_test_done) {
> freezer_test_done = false;
> - goto Thaw;
> + goto Thaw_fs;
> }
>
> if (in_suspend) {
> @@ -655,6 +660,8 @@ int hibernate(void)
> pr_debug("PM: Image restored successfully.\n");
> }
>
> + Thaw_fs:
> + thaw_supers();
> Thaw:
> thaw_processes();
> Finish:
>
--
Evolution (n): A hypothetical process whereby improbable
events occur with alarming frequency, order arises from chaos, and
no one is given credit.
next prev parent reply other threads:[~2012-01-28 21:31 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-28 13:45 [RFC][PATCH] PM / Sleep: Freeze filesystems during system suspend/hibernation Rafael J. Wysocki
2012-01-28 21:23 ` Nigel Cunningham [this message]
2012-01-29 15:55 ` Martin Steigerwald
2012-01-29 19:53 ` Rafael J. Wysocki
2012-01-29 16:28 ` Srivatsa S. Bhat
2012-01-29 19:53 ` Rafael J. Wysocki
2012-01-30 23:24 ` Srivatsa S. Bhat
2012-01-30 20:00 ` Jan Kara
2012-01-30 21:05 ` Rafael J. Wysocki
2012-01-30 21:10 ` Nigel Cunningham
2012-01-31 0:03 ` Jan Kara
2012-01-30 23:58 ` Jan Kara
2012-02-01 13:36 ` Pavel Machek
2012-02-01 15:29 ` Alan Stern
2012-02-10 2:52 ` Jamie Lokier
2012-02-10 9:03 ` Jan Kara
2012-02-02 3:17 ` Nigel Cunningham
2012-02-17 15:41 ` Josh Boyer
2012-02-17 15:41 ` Josh Boyer
2012-02-17 18:33 ` Josh Boyer
2012-02-17 20:59 ` Rafael J. Wysocki
2012-05-25 16:55 ` Josh Boyer
2012-05-25 16:55 ` Josh Boyer
2012-05-25 19:13 ` Rafael J. Wysocki
2013-12-17 16:03 ` Josh Boyer
2013-12-17 16:04 ` Josh Boyer
2013-12-17 23:08 ` Pavel Machek
2013-12-17 23:31 ` Dave Chinner
2013-12-18 0:01 ` Pavel Machek
2013-12-18 12:39 ` Dave Chinner
2013-12-18 14:08 ` Pavel Machek
2013-12-19 0:22 ` Dave Chinner
2013-12-21 23:33 ` Pavel Machek
2013-12-23 3:48 ` Dave Chinner
2013-12-18 0:52 ` Rafael J. Wysocki
2013-12-18 1:00 ` Josh Boyer
2013-12-18 1:16 ` Rafael J. Wysocki
2013-12-18 12:31 ` Josh Boyer
2013-12-18 21:40 ` Rafael J. Wysocki
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=4F24676A.4070907@tuxonice.net \
--to=nigel@tuxonice.net \
--cc=david@fromorbit.com \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=pavel@ucw.cz \
--cc=rjw@sisk.pl \
--cc=srivatsa.bhat@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.