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

Konstantin Khorenko khorenko at virtuozzo.com
Tue Jun 20 19:49:58 MSK 2017


Kirill, Andrey, what is about Dima's comment?

 > +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.


--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 06/16/2017 10:46 AM, Dmitry Monakhov wrote:
> 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
> _______________________________________________
> Devel mailing list
> Devel at openvz.org
> https://lists.openvz.org/mailman/listinfo/devel
> .
>


More information about the Devel mailing list