[Devel] [PATCH rh7 v3] ext4: add generic uevent infrastructure
Andrey Ryabinin
aryabinin at virtuozzo.com
Thu Jun 15 16:20:12 MSK 2017
From: Dmitry Monakhov <dmonakhov at openvz.org>
*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 <dmonakhov at openvz.org>
https://jira.sw.ru/browse/PSBM-66618
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
Changes since v2:
- Report error event only once per superblock
fs/ext4/ext4.h | 11 ++++++++
fs/ext4/super.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 1cd964870da3..ce60718c7143 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1356,6 +1356,8 @@ struct ext4_sb_info {
/* Precomputed FS UUID checksum for seeding other checksums */
__u32 s_csum_seed;
+ bool s_err_event_sent;
+
/* Reclaim extents from extent status tree */
struct shrinker s_es_shrinker;
struct list_head s_es_lru;
@@ -2758,6 +2760,15 @@ extern int ext4_check_blockref(const char *, unsigned int,
struct ext4_ext_path;
struct ext4_extent;
+enum ext4_event_type {
+ EXT4_UA_MOUNT,
+ EXT4_UA_UMOUNT,
+ EXT4_UA_REMOUNT,
+ EXT4_UA_ERROR,
+ EXT4_UA_FREEZE,
+ EXT4_UA_UNFREEZE,
+};
+
/*
* Maximum number of logical blocks in a file; ext4_extent's ee_block is
* __le32.
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index ee065861b62a..088313b6333f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -301,6 +301,79 @@ void ext4_itable_unused_set(struct super_block *sb,
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
}
+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;
+}
static void __save_error_info(struct super_block *sb, const char *func,
unsigned int line)
@@ -389,6 +462,9 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
static void ext4_handle_error(struct super_block *sb)
{
+ if (!xchg(&EXT4_SB(sb)->s_err_event_sent, 1))
+ ext4_send_uevent(sb, EXT4_UA_ERROR);
+
if (sb->s_flags & MS_RDONLY)
return;
@@ -780,6 +856,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 +4540,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 +5089,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 +5113,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 +5125,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 +5372,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
More information about the Devel
mailing list