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

Submitted by Andrey Ryabinin on June 15, 2017, 1:20 p.m.

Details

Message ID 20170615132012.17251-1-aryabinin@virtuozzo.com
State New
Series "ext4: add generic uevent infrastructure"
Headers show

Commit Message

Andrey Ryabinin June 15, 2017, 1:20 p.m.
From: Dmitry Monakhov <dmonakhov@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@openvz.org>

https://jira.sw.ru/browse/PSBM-66618
Signed-off-by: Andrey Ryabinin <aryabinin@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(-)

Patch hide | download patch | download mbox

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;
 

Comments

Dmitry Monakhov June 16, 2017, 7:46 a.m.
Andrey Ryabinin <aryabinin@virtuozzo.com> writes:

> From: Dmitry Monakhov <dmonakhov@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@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@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
Konstantin Khorenko June 20, 2017, 4:49 p.m.
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@virtuozzo.com> writes:
>
>> From: Dmitry Monakhov <dmonakhov@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@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@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@openvz.org
> https://lists.openvz.org/mailman/listinfo/devel
> .
>
Andrey Ryabinin June 20, 2017, 5:21 p.m.
On 06/20/2017 07:49 PM, Konstantin Khorenko wrote:
> Kirill, Andrey, what is about Dima's comment?
> 

We've had an offline discussion and Dima is agreed that the GFP_KERNEL is totally ok here.


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