[RFC PATCH 3/4] fs/super.c: introduce reverse superblock iterator and use it in emergency remount

From: James Bottomley
Date: Thu Mar 27 2025 - 10:19:09 EST


Originally proposed by Amir as an extract from the android kernel:

https://lore.kernel.org/linux-fsdevel/CAA2m6vfatWKS1CQFpaRbii2AXiZFvQUjVvYhGxWTSpz+2rxDyg@xxxxxxxxxxxxxx/

Since suspend/resume requires a reverse iterator, I'm dusting it off.

Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx>
---
fs/super.c | 48 +++++++++++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 19 deletions(-)

diff --git a/fs/super.c b/fs/super.c
index 5a7db4a556e3..76785509d906 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -887,28 +887,38 @@ void drop_super_exclusive(struct super_block *sb)
}
EXPORT_SYMBOL(drop_super_exclusive);

+#define ITERATE_SUPERS(f, rev) \
+ struct super_block *sb, *p = NULL; \
+ \
+ spin_lock(&sb_lock); \
+ \
+ list_for_each_entry##rev(sb, &super_blocks, s_list) { \
+ if (super_flags(sb, SB_DYING)) \
+ 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);
+
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 (super_flags(sb, SB_DYING))
- continue;
- sb->s_count++;
- spin_unlock(&sb_lock);
-
- f(sb);
+ ITERATE_SUPERS(f,)
+}

- spin_lock(&sb_lock);
- if (p)
- __put_super(p);
- p = sb;
- }
- if (p)
- __put_super(p);
- spin_unlock(&sb_lock);
+static void __iterate_supers_rev(void (*f)(struct super_block *))
+{
+ ITERATE_SUPERS(f, _reverse)
}
+
/**
* iterate_supers - call function for all active superblocks
* @f: function to call
@@ -1132,7 +1142,7 @@ static void do_emergency_remount_callback(struct super_block *sb)

static void do_emergency_remount(struct work_struct *work)
{
- __iterate_supers(do_emergency_remount_callback);
+ __iterate_supers_rev(do_emergency_remount_callback);
kfree(work);
printk("Emergency Remount complete\n");
}
--
2.43.0