[Devel] [PATCH rh7 v3] ext4: add generic uevent infrastructure

Dmitry Monakhov dmonakhov at openvz.org
Fri Jun 16 10:46:15 MSK 2017


Andrey Ryabinin <aryabinin at virtuozzo.com> writes:

> 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>
Only one note about mem allocation context, see below. Otherwise looks good.
>
> 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);
Please change GFP_KERNEL to GFP_NOFS otherwise it may deadlock.
> +	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