Thread (37 messages) 37 messages, 12 authors, 2013-12-23

Re: [RFC][PATCH] PM / Sleep: Freeze filesystems during system suspend/hibernation

From: Jan Kara <jack@suse.cz>
Date: 2012-01-30 20:00:40
Also in: linux-fsdevel

On Sat 28-01-12 14:45:49, Rafael J. Wysocki wrote:
quoted hunk ↗ jump to hunk
From: Rafael J. Wysocki <redacted>

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 <redacted>
---
 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/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);
+}
  At least for thawing you can use iterate_supers() helper.
+/**
+ *	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).
+	 */
  Ho, hum, are you sure the order in super_blocks list is the one you need?
Maybe it is but I'm not sure you are guaranteed it is. I've added Al to CC,
he'll likely have opinion on this...
+	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);
+			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
  *	
								Honza
-- 
Jan Kara [off-list ref]
SUSE Labs, CR
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help