* [PATCH 0/2] fix emergency unfreezing
@ 2017-10-03 16:17 Mateusz Guzik
2017-10-03 16:17 ` [PATCH 1/2] vfs: factor sb iteration out of do_emergency_remount Mateusz Guzik
2017-10-03 16:17 ` [PATCH 2/2] buffer.c: call thaw_super during emergency thaw Mateusz Guzik
0 siblings, 2 replies; 3+ messages in thread
From: Mateusz Guzik @ 2017-10-03 16:17 UTC (permalink / raw)
To: Eric Sandeen, Al Viro; +Cc: mszeredi, linux-fsdevel, linux-kernel
Filesystems frozen with fsfreeze --freeze are not getting thawed with
sysrq j (or echo j > /proc/sysrq-trigger). Thawing only deals with bdev
part, does not do anything about fsfreeze.
I went for the easiest fix possible: just thaw the super block.
Doing it requires a little bit of refactoring in order to keep the sb
locked the whole time.
The first patch moves sb iteration found in emergency remount to a
dedicated func for code reuse. This patch patch is a no-op.
The second employs factored out code to do both bdev and sb thaws.
Mateusz Guzik (2):
vfs: factor sb iteration out of do_emergency_remount
buffer.c: call thaw_super during emergency thaw
fs/buffer.c | 25 +------------
fs/super.c | 105 +++++++++++++++++++++++++++++++++++++++--------------
include/linux/fs.h | 1 +
3 files changed, 80 insertions(+), 51 deletions(-)
--
1.8.3.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] vfs: factor sb iteration out of do_emergency_remount
2017-10-03 16:17 [PATCH 0/2] fix emergency unfreezing Mateusz Guzik
@ 2017-10-03 16:17 ` Mateusz Guzik
2017-10-03 16:17 ` [PATCH 2/2] buffer.c: call thaw_super during emergency thaw Mateusz Guzik
1 sibling, 0 replies; 3+ messages in thread
From: Mateusz Guzik @ 2017-10-03 16:17 UTC (permalink / raw)
To: Eric Sandeen, Al Viro; +Cc: mszeredi, linux-fsdevel, linux-kernel
The intent is to reduce code duplication with other code
iterating the list.
No functional changes.
Signed-off-by: Mateusz Guzik <mguzik@redhat.com>
---
fs/super.c | 61 ++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 36 insertions(+), 25 deletions(-)
diff --git a/fs/super.c b/fs/super.c
index 166c4ee..fd9c02f 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -574,6 +574,28 @@ void drop_super_exclusive(struct super_block *sb)
}
EXPORT_SYMBOL(drop_super_exclusive);
+static void __iterate_supers(void (*f)(struct super_block *))
+{
+ 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);
+
+ f(sb);
+
+ spin_lock(&sb_lock);
+ if (p)
+ __put_super(p);
+ p = sb;
+ }
+ if (p)
+ __put_super(p);
+ spin_unlock(&sb_lock);
+}
/**
* iterate_supers - call function for all active superblocks
* @f: function to call
@@ -881,33 +903,22 @@ int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
return retval;
}
-static void do_emergency_remount(struct work_struct *work)
+static void do_emergency_remount_callback(struct super_block *sb)
{
- 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);
- down_write(&sb->s_umount);
- if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) &&
- !sb_rdonly(sb)) {
- /*
- * What lock protects sb->s_flags??
- */
- do_remount_sb(sb, SB_RDONLY, NULL, 1);
- }
- up_write(&sb->s_umount);
- spin_lock(&sb_lock);
- if (p)
- __put_super(p);
- p = sb;
+ down_write(&sb->s_umount);
+ if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) &&
+ !sb_rdonly(sb)) {
+ /*
+ * What lock protects sb->s_flags??
+ */
+ do_remount_sb(sb, SB_RDONLY, NULL, 1);
}
- if (p)
- __put_super(p);
- spin_unlock(&sb_lock);
+ up_write(&sb->s_umount);
+}
+
+static void do_emergency_remount(struct work_struct *work)
+{
+ __iterate_supers(do_emergency_remount_callback);
kfree(work);
printk("Emergency Remount complete\n");
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] buffer.c: call thaw_super during emergency thaw
2017-10-03 16:17 [PATCH 0/2] fix emergency unfreezing Mateusz Guzik
2017-10-03 16:17 ` [PATCH 1/2] vfs: factor sb iteration out of do_emergency_remount Mateusz Guzik
@ 2017-10-03 16:17 ` Mateusz Guzik
1 sibling, 0 replies; 3+ messages in thread
From: Mateusz Guzik @ 2017-10-03 16:17 UTC (permalink / raw)
To: Eric Sandeen, Al Viro; +Cc: mszeredi, linux-fsdevel, linux-kernel
There are 2 distinct freezing mechanisms - one operates on block
devices and another one directly on super blocks. Both end up with the
same result, but thaw of only one of these does not thaw the other.
In particular fsfreeze --freeze uses the ioctl variant going to the
super block. Since prior to this patch emergency thaw was not doing
a relevant thaw, filesystems frozen with this method remained
unaffected.
The patch is a hack which adds blind unfreezing.
In order to keep the super block write-locked the whole time the code
is shuffled around and the newly introduced __iterate_supers is
employed.
Signed-off-by: Mateusz Guzik <mguzik@redhat.com>
---
fs/buffer.c | 25 +------------------------
fs/super.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
include/linux/fs.h | 1 +
3 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 170df85..37ea00b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -523,35 +523,12 @@ static int osync_buffers_list(spinlock_t *lock, struct list_head *list)
return err;
}
-static void do_thaw_one(struct super_block *sb, void *unused)
+void emergency_thaw_bdev(struct super_block *sb)
{
while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
printk(KERN_WARNING "Emergency Thaw on %pg\n", sb->s_bdev);
}
-static void do_thaw_all(struct work_struct *work)
-{
- iterate_supers(do_thaw_one, NULL);
- kfree(work);
- printk(KERN_WARNING "Emergency Thaw complete\n");
-}
-
-/**
- * emergency_thaw_all -- forcibly thaw every frozen filesystem
- *
- * Used for emergency unfreeze of all filesystems via SysRq
- */
-void emergency_thaw_all(void)
-{
- struct work_struct *work;
-
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
- if (work) {
- INIT_WORK(work, do_thaw_all);
- schedule_work(work);
- }
-}
-
/**
* sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers
* @mapping: the mapping which wants those buffers written
diff --git a/fs/super.c b/fs/super.c
index fd9c02f..83c5c8a 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -36,6 +36,7 @@
#include <linux/user_namespace.h>
#include "internal.h"
+static int thaw_super_locked(struct super_block *sb);
static LIST_HEAD(super_blocks);
static DEFINE_SPINLOCK(sb_lock);
@@ -934,6 +935,40 @@ void emergency_remount(void)
}
}
+static void do_thaw_all_callback(struct super_block *sb)
+{
+ down_write(&sb->s_umount);
+ if (sb->s_root && sb->s_flags & MS_BORN) {
+ emergency_thaw_bdev(sb);
+ thaw_super_locked(sb);
+ } else {
+ up_write(&sb->s_umount);
+ }
+}
+
+static void do_thaw_all(struct work_struct *work)
+{
+ __iterate_supers(do_thaw_all_callback);
+ kfree(work);
+ printk(KERN_WARNING "Emergency Thaw complete\n");
+}
+
+/**
+ * emergency_thaw_all -- forcibly thaw every frozen filesystem
+ *
+ * Used for emergency unfreeze of all filesystems via SysRq
+ */
+void emergency_thaw_all(void)
+{
+ struct work_struct *work;
+
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+ if (work) {
+ INIT_WORK(work, do_thaw_all);
+ schedule_work(work);
+ }
+}
+
/*
* Unnamed block devices are dummy devices used by virtual
* filesystems which don't use real block-devices. -- jrs
@@ -1503,11 +1538,10 @@ int freeze_super(struct super_block *sb)
*
* Unlocks the filesystem and marks it writeable again after freeze_super().
*/
-int thaw_super(struct super_block *sb)
+static int thaw_super_locked(struct super_block *sb)
{
int error;
- down_write(&sb->s_umount);
if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) {
up_write(&sb->s_umount);
return -EINVAL;
@@ -1538,4 +1572,10 @@ int thaw_super(struct super_block *sb)
deactivate_locked_super(sb);
return 0;
}
+
+int thaw_super(struct super_block *sb)
+{
+ down_write(&sb->s_umount);
+ return thaw_super_locked(sb);
+}
EXPORT_SYMBOL(thaw_super);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 339e737..e3f1b13 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2428,6 +2428,7 @@ extern int finish_open(struct file *file, struct dentry *dentry,
extern void kill_bdev(struct block_device *);
extern struct super_block *freeze_bdev(struct block_device *);
extern void emergency_thaw_all(void);
+extern void emergency_thaw_bdev(struct super_block *sb);
extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
extern int fsync_bdev(struct block_device *);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-10-03 16:17 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-03 16:17 [PATCH 0/2] fix emergency unfreezing Mateusz Guzik
2017-10-03 16:17 ` [PATCH 1/2] vfs: factor sb iteration out of do_emergency_remount Mateusz Guzik
2017-10-03 16:17 ` [PATCH 2/2] buffer.c: call thaw_super during emergency thaw Mateusz Guzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).