On Sat 28-01-12 14:45:49, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rjw@xxxxxxx> > > 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@xxxxxxx> > --- > 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 <jack@xxxxxxx> SUSE Labs, CR -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html