[Devel] [PATCH vz8 2/2] ext4: send abort uevent on ext4 journal abort
From: Dmitry Monakhov Currenlty error from device result in ext4_abort, but uevent not generated because ext4_abort() caller's context do not allow GFP_KERNEL memory allocation. Let's relax submission context requirement and deffer actual uevent submission to work_queue. It can be any workqueue I've pick rsv_conversion_wq because it is already exists. khorenko@: "system_wq" does not fit here because at the moment of work execution sb can be already destroyed. "EXT4_SB(sb)->rsv_conversion_wq" is flushed before sb is destroyed. Signed-off-by: Dmitry Monakhov [aryabinin rh8 rebase] Signed-off-by: Andrey Ryabinin --- fs/ext4/ext4.h | 2 ++ fs/ext4/super.c | 10 ++ 2 files changed, 12 insertions(+) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 228492c9518f..bbdd7efc8447 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1499,6 +1499,7 @@ struct ext4_sb_info { __u32 s_csum_seed; bool s_err_event_sent; + bool s_abrt_event_sent; /* Reclaim extents from extent status tree */ struct shrinker s_es_shrinker; @@ -3126,6 +3127,7 @@ enum ext4_event_type { EXT4_UA_UMOUNT, EXT4_UA_REMOUNT, EXT4_UA_ERROR, + EXT4_UA_ABORT, EXT4_UA_FREEZE, EXT4_UA_UNFREEZE, }; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3cc979825ec8..00619f45b1c3 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -420,6 +420,9 @@ static void ext4_send_uevent_work(struct work_struct *w) case EXT4_UA_ERROR: ret = add_uevent_var(env, "FS_ACTION=%s", "ERROR"); break; + case EXT4_UA_ABORT: + ret = add_uevent_var(env, "FS_ACTION=%s", "ABORT"); + break; case EXT4_UA_FREEZE: ret = add_uevent_var(env, "FS_ACTION=%s", "FREEZE"); break; @@ -576,6 +579,9 @@ static void ext4_handle_error(struct super_block *sb) if (!test_opt(sb, ERRORS_CONT)) { journal_t *journal = EXT4_SB(sb)->s_journal; + if (!xchg(_SB(sb)->s_abrt_event_sent, 1)) + ext4_send_uevent(sb, EXT4_UA_ABORT); + EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; if (journal) jbd2_journal_abort(journal, -EIO); @@ -801,6 +807,10 @@ void __ext4_abort(struct super_block *sb, const char *function, if (sb_rdonly(sb) == 0) { ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); + + if (!xchg(_SB(sb)->s_abrt_event_sent, 1)) + ext4_send_uevent(sb, EXT4_UA_ABORT); + EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; /* * Make sure updated value of ->s_mount_flags will be visible -- 2.26.2 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
[Devel] [PATCH vz8 1/2] ext4: add generic uevent infrastructure
From: Dmitry Monakhov *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 [aryabinin: add error event, rh8 rebase] Signed-off-by: Andrey Ryabinin --- fs/ext4/ext4.h | 11 + fs/ext4/super.c | 128 +++- 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 028832d858fc..228492c9518f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1498,6 +1498,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_list; /* List of inodes with reclaimable extents */ @@ -3119,6 +3121,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 7fc5ad243953..3cc979825ec8 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -354,6 +354,117 @@ static time64_t __ext4_get_tstamp(__le32 *lo, __u8 *hi) #define ext4_get_tstamp(es, tstamp) \ __ext4_get_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi) +static int ext4_uuid_valid(const u8 *uuid) +{ + int i; + + for (i = 0; i < 16; i++) { + if (uuid[i]) + return 1; + } + return 0; +} + +struct ext4_uevent { + struct super_block *sb; + enum ext4_event_type action; + struct work_struct work; +}; + +/** + * ext4_send_uevent - prepare and send uevent + * + * @sb:super_block + * @action:action type + * + */ +static void ext4_send_uevent_work(struct work_struct *w) +{ + struct ext4_uevent *e = container_of(w, struct ext4_uevent, work); + struct super_block *sb = e->sb; + struct kobj_uevent_env *env; + const u8 *uuid = EXT4_SB(sb)->s_es->s_uuid; + enum kobject_action kaction = KOBJ_CHANGE; + int ret; + + env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); + if (!env){ + kfree(e); + return; + } + 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 (e->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); + kfree(e); +} + +/** + * ext4_send_uevent - prepare and schedule event submission + * + * @sb:super_block + * @action:action type + * + */ +void ext4_send_uevent(struct super_block *sb, enum ext4_event_type action) +{ + struct ext4_uevent *e; + + /* +* May happen if called from ext4_put_super() -> __ext4_abort() +* -> ext4_send_uevent() +*/ + if (!EXT4_SB(sb)->rsv_conversion_wq) + return; + + e = kzalloc(sizeof(*e), GFP_NOIO); + if (!e) + return; + + e->sb = sb; + e->action = action; + INIT_WORK(>work, ext4_send_uevent_work); +
Re: [Devel] [PATCH rh7] ve/net/core: allow to call setsockopt(SO_RCVBUFFORCE) from Containers
On 11/05/2020 06:20 PM, Konstantin Khorenko wrote: "nft" util (in CentOS 8 environment) does use setsockopt(SO_RCVBUFFORCE) unconditionally, so we have to allow it from inside a Container. At the same time we don't want to allow a Container to set too much memory for a socket, so just threat SO_RCVBUFFORCE like SO_RCVBUF if called inside a Container. Simple rule to test: # NFT=/usr/sbin/nft ./run-tests.sh -v -g testcases/nft-f/0011manydefines_0 which fails inside a Container because of not enough rcb buffer because of failed setsockopt(3, SOL_SOCKET, SO_RCVBUFFORCE, [10561584], 4) = -1 EPERM (Operation not permitted) https://jira.sw.ru/browse/PSBM-121791 Signed-off-by: Konstantin Khorenko --- net/core/sock.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 07ea42f976cf..44e91c8c0f0a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -793,6 +793,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, goto set_sndbuf; case SO_RCVBUF: +unpriv_rcvbuf: /* Don't error on this BSD doesn't and if you think * about it this is right. Otherwise apps have to * play 'guess the biggest size' games. RCVBUF/SNDBUF @@ -824,11 +825,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; case SO_RCVBUFFORCE: - if (!capable(CAP_NET_ADMIN)) { + if (!ve_capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } + /* nft utility uses this sockopt in CentOS 8 env */ + if (!ve_is_super(get_exec_env())) + goto unpriv_rcvbuf; + /* No negative values (to prevent underflow, as val will be * multiplied by 2). */ ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
[Devel] [PATCH rh7] ve/net/core: allow to call setsockopt(SO_RCVBUFFORCE) from Containers
"nft" util (in CentOS 8 environment) does use setsockopt(SO_RCVBUFFORCE) unconditionally, so we have to allow it from inside a Container. At the same time we don't want to allow a Container to set too much memory for a socket, so just threat SO_RCVBUFFORCE like SO_RCVBUF if called inside a Container. Simple rule to test: # NFT=/usr/sbin/nft ./run-tests.sh -v -g testcases/nft-f/0011manydefines_0 which fails inside a Container because of not enough rcb buffer because of failed setsockopt(3, SOL_SOCKET, SO_RCVBUFFORCE, [10561584], 4) = -1 EPERM (Operation not permitted) Signed-off-by: Konstantin Khorenko --- net/core/sock.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 07ea42f976cf..44e91c8c0f0a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -793,6 +793,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, goto set_sndbuf; case SO_RCVBUF: +unpriv_rcvbuf: /* Don't error on this BSD doesn't and if you think * about it this is right. Otherwise apps have to * play 'guess the biggest size' games. RCVBUF/SNDBUF @@ -824,11 +825,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; case SO_RCVBUFFORCE: - if (!capable(CAP_NET_ADMIN)) { + if (!ve_capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } + /* nft utility uses this sockopt in CentOS 8 env */ + if (!ve_is_super(get_exec_env())) + goto unpriv_rcvbuf; + /* No negative values (to prevent underflow, as val will be * multiplied by 2). */ -- 2.24.3 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel