Freeze all filesystems during system suspend/hibernate.
Rebased http://marc.info/?l=linux-kernel&m=132775832509351&w=4 to 3.3-rc3
This commit is contained in:
parent
49739536e3
commit
fcbaf26ab3
287
hibernate-freeze-filesystems.patch
Normal file
287
hibernate-freeze-filesystems.patch
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
commit b94887bbc0621e1e8402e7f0ec4bc3adf46c9a6e
|
||||||
|
Author: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Date: Fri Feb 17 12:42:08 2012 -0500
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
Rebased to 3.3-rc3 by Josh Boyer <jwboyer@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/fs/super.c b/fs/super.c
|
||||||
|
index 6015c02..c8057fa 100644
|
||||||
|
--- a/fs/super.c
|
||||||
|
+++ b/fs/super.c
|
||||||
|
@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_system_type *type,
|
||||||
|
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 (hlist_unhashed(&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);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * 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 (hlist_unhashed(&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);
|
||||||
|
+ 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
|
||||||
|
*
|
||||||
|
diff --git a/include/linux/fs.h b/include/linux/fs.h
|
||||||
|
index 386da09..a164f4a 100644
|
||||||
|
--- a/include/linux/fs.h
|
||||||
|
+++ b/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_block *sb);
|
||||||
|
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 *);
|
||||||
|
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
|
||||||
|
index 6d6d288..492fc62 100644
|
||||||
|
--- a/kernel/power/hibernate.c
|
||||||
|
+++ b/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:
|
||||||
|
diff --git a/kernel/power/power.h b/kernel/power/power.h
|
||||||
|
index 21724ee..40d6f64 100644
|
||||||
|
--- a/kernel/power/power.h
|
||||||
|
+++ b/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,45 +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;
|
||||||
|
-
|
||||||
|
- error = freeze_processes();
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * freeze_processes() automatically thaws every task if freezing
|
||||||
|
- * fails. So we need not do anything extra upon error.
|
||||||
|
- */
|
||||||
|
- if (error)
|
||||||
|
- goto Finish;
|
||||||
|
-
|
||||||
|
- error = freeze_kernel_threads();
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * freeze_kernel_threads() thaws only kernel threads upon freezing
|
||||||
|
- * failure. So we have to thaw the userspace tasks ourselves.
|
||||||
|
- */
|
||||||
|
- if (error)
|
||||||
|
- thaw_processes();
|
||||||
|
-
|
||||||
|
- Finish:
|
||||||
|
- return error;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-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
|
||||||
|
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
|
||||||
|
index 4fd51be..5f51fc7 100644
|
||||||
|
--- a/kernel/power/suspend.c
|
||||||
|
+++ b/kernel/power/suspend.c
|
||||||
|
@@ -29,6 +29,62 @@
|
||||||
|
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
|
+#ifdef CONFIG_SUSPEND_FREEZER
|
||||||
|
+
|
||||||
|
+static inline int suspend_freeze_processes(void)
|
||||||
|
+{
|
||||||
|
+ int error;
|
||||||
|
+
|
||||||
|
+ error = freeze_processes();
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * freeze_processes() automatically thaws every task if freezing
|
||||||
|
+ * fails. So we need not do anything extra upon error.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ if (error)
|
||||||
|
+ goto Finish;
|
||||||
|
+
|
||||||
|
+ error = freeze_supers();
|
||||||
|
+ if (error) {
|
||||||
|
+ thaw_processes();
|
||||||
|
+ goto Finish;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ error = freeze_kernel_threads();
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * freeze_kernel_threads() thaws only kernel threads upon freezing
|
||||||
|
+ * failure. So we have to thaw the userspace tasks ourselves.
|
||||||
|
+ */
|
||||||
|
+ if (error) {
|
||||||
|
+ thaw_supers();
|
||||||
|
+ thaw_processes();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+Finish:
|
||||||
|
+ 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",
|
@ -54,7 +54,7 @@ Summary: The Linux kernel
|
|||||||
# For non-released -rc kernels, this will be appended after the rcX and
|
# For non-released -rc kernels, this will be appended after the rcX and
|
||||||
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
||||||
#
|
#
|
||||||
%global baserelease 1
|
%global baserelease 2
|
||||||
%global fedora_build %{baserelease}
|
%global fedora_build %{baserelease}
|
||||||
|
|
||||||
# base_sublevel is the kernel version we're starting with and patching
|
# base_sublevel is the kernel version we're starting with and patching
|
||||||
@ -730,6 +730,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch
|
|||||||
|
|
||||||
Patch13003: efi-dont-map-boot-services-on-32bit.patch
|
Patch13003: efi-dont-map-boot-services-on-32bit.patch
|
||||||
|
|
||||||
|
Patch14000: hibernate-freeze-filesystems.patch
|
||||||
|
|
||||||
Patch20000: utrace.patch
|
Patch20000: utrace.patch
|
||||||
|
|
||||||
# Flattened devicetree support
|
# Flattened devicetree support
|
||||||
@ -1447,6 +1449,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch
|
|||||||
|
|
||||||
ApplyPatch efi-dont-map-boot-services-on-32bit.patch
|
ApplyPatch efi-dont-map-boot-services-on-32bit.patch
|
||||||
|
|
||||||
|
ApplyPatch hibernate-freeze-filesystems.patch
|
||||||
|
|
||||||
# utrace.
|
# utrace.
|
||||||
ApplyPatch utrace.patch
|
ApplyPatch utrace.patch
|
||||||
|
|
||||||
@ -2351,6 +2355,9 @@ fi
|
|||||||
# ||----w |
|
# ||----w |
|
||||||
# || ||
|
# || ||
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Feb 17 2012 Josh Boyer <jwboyer@redhat.com> - 3.3.0-0.rc3.git7.2
|
||||||
|
- Freeze all filesystems during system suspend/hibernate.
|
||||||
|
|
||||||
* Fri Feb 17 2012 Josh Boyer <jwboyer@redhat.com> - 3.3.0-0.rc3.git7.1
|
* Fri Feb 17 2012 Josh Boyer <jwboyer@redhat.com> - 3.3.0-0.rc3.git7.1
|
||||||
- Linux 3.3-rc3-git7 (upstream 4903062b5485f0e2c286a23b44c9b59d9b017d53)
|
- Linux 3.3-rc3-git7 (upstream 4903062b5485f0e2c286a23b44c9b59d9b017d53)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user