Re: [RFC PATCH 4/4] vfs: add filesystem freeze/thaw callbacks for power management
From: James Bottomley
Date: Fri Mar 28 2025 - 10:38:35 EST
On Fri, 2025-03-28 at 10:21 -0400, James Bottomley wrote:
> [...]
> That's right. I'm happy to post my patch below, but it depends on Al
> accepting the simple_next_child() proposal, so it doesn't apply to
> any
> tree.
And here's the patch I forgot to attach.
Regards,
James
---
diff --git a/fs/efivarfs/internal.h b/fs/efivarfs/internal.h
index ac6a1dd0a6a5..f913b6824289 100644
--- a/fs/efivarfs/internal.h
+++ b/fs/efivarfs/internal.h
@@ -17,7 +17,6 @@ struct efivarfs_fs_info {
struct efivarfs_mount_opts mount_opts;
struct super_block *sb;
struct notifier_block nb;
- struct notifier_block pm_nb;
};
struct efi_variable {
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index 7d47f8d7ad1d..3398ec5c60b3 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -119,12 +119,15 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
return 0;
}
+
+static int efivarfs_thaw(struct super_block *sb, enum freeze_holder who);
static const struct super_operations efivarfs_ops = {
.statfs = efivarfs_statfs,
.drop_inode = generic_delete_inode,
.alloc_inode = efivarfs_alloc_inode,
.free_inode = efivarfs_free_inode,
.show_options = efivarfs_show_options,
+ .thaw_super = efivarfs_thaw,
};
/*
@@ -367,8 +370,6 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (err)
return err;
- register_pm_notifier(&sfi->pm_nb);
-
return efivar_init(efivarfs_callback, sb, true);
}
@@ -432,24 +433,17 @@ static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor,
return err;
}
-static int efivarfs_pm_notify(struct notifier_block *nb, unsigned long action,
- void *ptr)
+static int efivarfs_thaw(struct super_block *sb, enum freeze_holder who)
{
- struct efivarfs_fs_info *sfi = container_of(nb, struct efivarfs_fs_info,
- pm_nb);
static bool rescan_done = true;
- struct dentry *parent = sfi->sb->s_root;
+ struct dentry *parent = sb->s_root;
struct dentry *child = NULL;
- if (action == PM_HIBERNATION_PREPARE) {
- rescan_done = false;
- return NOTIFY_OK;
- } else if (action != PM_POST_HIBERNATION) {
- return NOTIFY_DONE;
- }
+ if ((who & FREEZE_FOR_HIBERNATE) == 0)
+ return 0;
if (rescan_done)
- return NOTIFY_DONE;
+ return 0;
pr_info("efivarfs: resyncing variable state\n");
@@ -488,9 +482,9 @@ static int efivarfs_pm_notify(struct notifier_block *nb, unsigned long action,
* then loop over variables, creating them if there's no matching
* dentry
*/
- efivar_init(efivarfs_check_missing, sfi->sb, false);
+ efivar_init(efivarfs_check_missing, sb, false);
- return NOTIFY_OK;
+ return 0;
}
static int efivarfs_init_fs_context(struct fs_context *fc)
@@ -510,9 +504,6 @@ static int efivarfs_init_fs_context(struct fs_context *fc)
fc->s_fs_info = sfi;
fc->ops = &efivarfs_context_ops;
- sfi->pm_nb.notifier_call = efivarfs_pm_notify;
- sfi->pm_nb.priority = 0;
-
return 0;
}
@@ -521,7 +512,6 @@ static void efivarfs_kill_sb(struct super_block *sb)
struct efivarfs_fs_info *sfi = sb->s_fs_info;
blocking_notifier_chain_unregister(&efivar_ops_nh, &sfi->nb);
- unregister_pm_notifier(&sfi->pm_nb);
kill_litter_super(sb);
kfree(sfi);