Message ID | 20250329-work-freeze-v2-6-a47af37ecc3d@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Extend freeze support to suspend and hibernate | expand |
On Sat, Mar 29, 2025 at 09:42:19AM +0100, Christian Brauner wrote: > Allow the power subsystem to support filesystem freeze for > suspend and hibernate. > > Signed-off-by: Christian Brauner <brauner@kernel.org> > --- > fs/super.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/fs.h | 2 ++ > 2 files changed, 57 insertions(+) > > diff --git a/fs/super.c b/fs/super.c > index 666a2a16df87..4364b763e91f 100644 > --- a/fs/super.c > +++ b/fs/super.c > @@ -1176,6 +1176,61 @@ void emergency_thaw_all(void) > } > } > > +static inline bool get_active_super(struct super_block *sb) > +{ > + bool active; Typo on my end. This is ofc bool active = false; And fixed. > + > + if (super_lock_excl(sb)) { > + active = atomic_inc_not_zero(&sb->s_active); > + super_unlock_excl(sb); > + } > + return active; > +} > + > +static void filesystems_freeze_callback(struct super_block *sb, void *unused) > +{ > + if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super) > + return; > + > + if (!get_active_super(sb)) > + return; > + > + if (sb->s_op->freeze_super) > + sb->s_op->freeze_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); > + else > + freeze_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); > + > + deactivate_super(sb); > +} > + > +void filesystems_freeze(bool hibernate) > +{ > + __iterate_supers(filesystems_freeze_callback, NULL, > + SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE); > +} > + > +static void filesystems_thaw_callback(struct super_block *sb, void *unused) > +{ > + if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super) > + return; > + > + if (!get_active_super(sb)) > + return; > + > + if (sb->s_op->thaw_super) > + sb->s_op->thaw_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); > + else > + thaw_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); > + > + deactivate_super(sb); > +} > + > +void filesystems_thaw(bool hibernate) > +{ > + __iterate_supers(filesystems_thaw_callback, NULL, > + SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE); > +} > + > static DEFINE_IDA(unnamed_dev_ida); > > /** > diff --git a/include/linux/fs.h b/include/linux/fs.h > index c475fa874055..29bd28491eff 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -3518,6 +3518,8 @@ extern void drop_super_exclusive(struct super_block *sb); > extern void iterate_supers(void (*f)(struct super_block *, void *), void *arg); > extern void iterate_supers_type(struct file_system_type *, > void (*)(struct super_block *, void *), void *); > +void filesystems_freeze(bool hibernate); > +void filesystems_thaw(bool hibernate); > > extern int dcache_dir_open(struct inode *, struct file *); > extern int dcache_dir_close(struct inode *, struct file *); > > -- > 2.47.2 >
On Sat 29-03-25 09:42:19, Christian Brauner wrote: > Allow the power subsystem to support filesystem freeze for > suspend and hibernate. > > Signed-off-by: Christian Brauner <brauner@kernel.org> One comment below. Otherwise feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> > +void filesystems_thaw(bool hibernate) > +{ > + __iterate_supers(filesystems_thaw_callback, NULL, > + SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE); > +} I think we should thaw in normal superblock order, not in reverse one? To thaw the bottommost filesystem first? The filesystem thaw callback can write to the underlying device and this could cause deadlocks... Honza
On Mon, Mar 31, 2025 at 12:23:04PM +0200, Jan Kara wrote: > On Sat 29-03-25 09:42:19, Christian Brauner wrote: > > Allow the power subsystem to support filesystem freeze for > > suspend and hibernate. > > > > Signed-off-by: Christian Brauner <brauner@kernel.org> > > One comment below. Otherwise feel free to add: > > Reviewed-by: Jan Kara <jack@suse.cz> > > > +void filesystems_thaw(bool hibernate) > > +{ > > + __iterate_supers(filesystems_thaw_callback, NULL, > > + SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE); > > +} > > I think we should thaw in normal superblock order, not in reverse one? To > thaw the bottommost filesystem first? The filesystem thaw callback can > write to the underlying device and this could cause deadlocks... Yep, I've fixed that already up in vfs-6.16.super yesterday. Sorry, forgot to mention that here. Thanks for noticing!
diff --git a/fs/super.c b/fs/super.c index 666a2a16df87..4364b763e91f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1176,6 +1176,61 @@ void emergency_thaw_all(void) } } +static inline bool get_active_super(struct super_block *sb) +{ + bool active; + + if (super_lock_excl(sb)) { + active = atomic_inc_not_zero(&sb->s_active); + super_unlock_excl(sb); + } + return active; +} + +static void filesystems_freeze_callback(struct super_block *sb, void *unused) +{ + if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super) + return; + + if (!get_active_super(sb)) + return; + + if (sb->s_op->freeze_super) + sb->s_op->freeze_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); + else + freeze_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); + + deactivate_super(sb); +} + +void filesystems_freeze(bool hibernate) +{ + __iterate_supers(filesystems_freeze_callback, NULL, + SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE); +} + +static void filesystems_thaw_callback(struct super_block *sb, void *unused) +{ + if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super) + return; + + if (!get_active_super(sb)) + return; + + if (sb->s_op->thaw_super) + sb->s_op->thaw_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); + else + thaw_super(sb, FREEZE_MAY_NEST | FREEZE_HOLDER_KERNEL); + + deactivate_super(sb); +} + +void filesystems_thaw(bool hibernate) +{ + __iterate_supers(filesystems_thaw_callback, NULL, + SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE); +} + static DEFINE_IDA(unnamed_dev_ida); /** diff --git a/include/linux/fs.h b/include/linux/fs.h index c475fa874055..29bd28491eff 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3518,6 +3518,8 @@ extern void drop_super_exclusive(struct super_block *sb); extern void iterate_supers(void (*f)(struct super_block *, void *), void *arg); extern void iterate_supers_type(struct file_system_type *, void (*)(struct super_block *, void *), void *); +void filesystems_freeze(bool hibernate); +void filesystems_thaw(bool hibernate); extern int dcache_dir_open(struct inode *, struct file *); extern int dcache_dir_close(struct inode *, struct file *);
Allow the power subsystem to support filesystem freeze for suspend and hibernate. Signed-off-by: Christian Brauner <brauner@kernel.org> --- fs/super.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 57 insertions(+)