From: Dmitry Monakhov <[email protected]>

*Purpose:
It is reasonable to annaunce fs related events via uevent infrastructure.
This patch implement only ext4'th part, but IMHO this should be usefull for
any generic filesystem.

Example: Runtime fs-error is pure async event. Currently there is no good
way to handle this situation and inform user-space about this.

*Implementation:
 Add uevent infrastructure similar to dm uevent
 FS_ACTION = {MOUNT|UMOUNT|REMOUNT|ERROR|FREEZE|UNFREEZE}
 FS_UUID
 FS_NAME
 FS_TYPE

Signed-off-by: Dmitry Monakhov <[email protected]>

https://jira.sw.ru/browse/PSBM-66618
Signed-off-by: Andrey Ryabinin <[email protected]>
---
 fs/ext4/super.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 86 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index ee065861b62a..19e7c2af25a0 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -372,6 +372,80 @@ static void ext4_journal_commit_callback(journal_t 
*journal, transaction_t *txn)
        spin_unlock(&sbi->s_md_lock);
 }
 
+static int ext4_uuid_valid(const u8 *uuid)
+{
+       int i;
+
+       for (i = 0; i < 16; i++) {
+           if (uuid[i])
+               return 1;
+               }
+               return 0;
+}
+
+/**
+ * ext4_send_uevent - prepare and send uevent
+ *
+ * @sb:                super_block
+ * @action:            action type
+ *
+ */
+int ext4_send_uevent(struct super_block *sb, enum ext4_event_type action)
+{
+       int ret;
+       struct kobj_uevent_env *env;
+       const u8 *uuid = sb->s_uuid;
+       enum kobject_action kaction = KOBJ_CHANGE;
+
+       env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
+       if (!env)
+               return -ENOMEM;
+
+       ret = add_uevent_var(env, "FS_TYPE=%s", sb->s_type->name);
+       if (ret)
+               goto out;
+       ret = add_uevent_var(env, "FS_NAME=%s", sb->s_id);
+       if (ret)
+               goto out;
+
+       if (ext4_uuid_valid(uuid)) {
+               ret = add_uevent_var(env, "UUID=%pUB", uuid);
+               if (ret)
+                       goto out;
+       }
+
+       switch (action) {
+       case EXT4_UA_MOUNT:
+               kaction = KOBJ_ONLINE;
+               ret = add_uevent_var(env, "FS_ACTION=%s", "MOUNT");
+               break;
+       case EXT4_UA_UMOUNT:
+               kaction = KOBJ_OFFLINE;
+               ret = add_uevent_var(env, "FS_ACTION=%s", "UMOUNT");
+               break;
+       case EXT4_UA_REMOUNT:
+               ret = add_uevent_var(env, "FS_ACTION=%s", "REMOUNT");
+               break;
+       case EXT4_UA_ERROR:
+               ret = add_uevent_var(env, "FS_ACTION=%s", "ERROR");
+               break;
+       case EXT4_UA_FREEZE:
+               ret = add_uevent_var(env, "FS_ACTION=%s", "FREEZE");
+               break;
+       case EXT4_UA_UNFREEZE:
+               ret = add_uevent_var(env, "FS_ACTION=%s", "UNFREEZE");
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       if (ret)
+               goto out;
+       ret = kobject_uevent_env(&(EXT4_SB(sb)->s_kobj), kaction, env->envp);
+out:
+       kfree(env);
+       return ret;
+}
+
 /* Deal with the reporting of failure conditions on a filesystem such as
  * inconsistencies detected or read IO failures.
  *
@@ -411,6 +485,7 @@ static void ext4_handle_error(struct super_block *sb)
        if (test_opt(sb, ERRORS_PANIC))
                panic("EXT4-fs (device %s): panic forced after error\n",
                        sb->s_id);
+       ext4_send_uevent(sb, EXT4_UA_ERROR);
 }
 
 #define ext4_error_ratelimit(sb)                                       \
@@ -780,6 +855,7 @@ static void ext4_put_super(struct super_block *sb)
        struct ext4_super_block *es = sbi->s_es;
        int i, err;
 
+       ext4_send_uevent(sb, EXT4_UA_UMOUNT);
        ext4_unregister_li_request(sb);
        dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
@@ -4463,6 +4539,7 @@ no_journal:
        ratelimit_state_init(&sbi->s_warning_ratelimit_state, 5 * HZ, 10);
        ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
 
+       ext4_send_uevent(sb, EXT4_UA_MOUNT);
        kfree(orig_data);
        return 0;
 
@@ -5011,8 +5088,10 @@ static int ext4_freeze(struct super_block *sb)
        int error = 0;
        journal_t *journal;
 
-       if (sb->s_flags & MS_RDONLY)
+       if (sb->s_flags & MS_RDONLY) {
+               ext4_send_uevent(sb, EXT4_UA_FREEZE);
                return 0;
+       }
 
        journal = EXT4_SB(sb)->s_journal;
 
@@ -5033,6 +5112,9 @@ static int ext4_freeze(struct super_block *sb)
 out:
        /* we rely on upper layer to stop further updates */
        jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+       if (!error)
+               ext4_send_uevent(sb, EXT4_UA_FREEZE);
+
        return error;
 }
 
@@ -5042,6 +5124,8 @@ out:
  */
 static int ext4_unfreeze(struct super_block *sb)
 {
+       ext4_send_uevent(sb, EXT4_UA_UNFREEZE);
+
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
@@ -5287,6 +5371,7 @@ static int ext4_remount(struct super_block *sb, int 
*flags, char *data)
 
        *flags = (*flags & ~MS_LAZYTIME) | (sb->s_flags & MS_LAZYTIME);
        ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
+       ext4_send_uevent(sb, EXT4_UA_REMOUNT);
        kfree(orig_data);
        return 0;
 
-- 
2.13.0

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to