From: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Subject: Re: [Devel] [PATCH VZ10 v6 7/9] ve: Introduce per-VE failcount
Date: Wed, 19 Aug 2026 13:16:17 +0000 [thread overview]
Message-ID: <178714537779.798038.4175166408746452014.b4-review@b4> (raw)
In-Reply-To: <ebe38e1d8f588bee698b17b1781ae3875697c0b8.1787129389.git.vladimir.riabchun@virtuozzo.com>
> It may be useful to have a history of resource limit hits for every VE,
> this may simplify debugging and provide some information about the
> resources usage.
>
> This information is provided by ve.failcount file, any write to it
> resets all failcounts.
>
> To add a new failcounter we need to create a new atomic_t field
> name_failcount in ve structure and add a new VE_FC_ENTRY in
> ve_failcounts array.
>
> One change, unrelated to failcounts: aio fields are now initialized
> in ve0.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-135520
>
> Feature: per-ve failcounters
> Signed-off-by: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
>
> diff --git a/fs/aio.c b/fs/aio.c
> index cb63416af135..3fa07cc626f8 100644
> --- a/fs/aio.c
> +++ b/fs/aio.c
> @@ -814,6 +814,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
> spin_lock(&ve->aio_nr_lock);
> if (ve->aio_nr + ctx->max_reqs > ve->aio_max_nr ||
> ve->aio_nr + ctx->max_reqs < ve->aio_nr) {
> + atomic_inc(&ve->aio_failcount);
> spin_unlock(&ve->aio_nr_lock);
> err = -EAGAIN;
> goto err_ctx;
> diff --git a/fs/namespace.c b/fs/namespace.c
> index c9e2ab9b3b57..eeeb2f780e46 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -3369,6 +3369,8 @@ static inline int ve_try_reserve_mount(struct ve_struct *ve)
>
> if (ret)
> get_ve(ve);
> + else
> + atomic_inc(&ve->mnt_failcount);
> return ret;
> }
>
> diff --git a/include/linux/ve.h b/include/linux/ve.h
> index 5687faad46ff..9e73527e970e 100644
> --- a/include/linux/ve.h
> +++ b/include/linux/ve.h
> @@ -72,12 +72,15 @@ struct ve_struct {
> struct kmapset_key proc_perms_key;
>
> atomic_t netns_avail_nr;
> + atomic_t netns_failcount;
> int netns_max_nr;
>
> atomic_t netif_avail_nr;
> + atomic_t netif_failcount;
> int netif_max_nr;
>
> atomic_t bpf_prog_avail_nr;
> + atomic_t bpf_prog_failcount;
> int bpf_prog_max_nr;
>
> atomic64_t _uevent_seqnum;
> @@ -86,6 +89,7 @@ struct ve_struct {
>
> atomic_t arp_neigh_nr;
> atomic_t nd_neigh_nr;
> + atomic_t neigh_tbl_failcount;
> unsigned long meminfo_val;
>
> /*
> @@ -94,6 +98,7 @@ struct ve_struct {
> * other containers.
> */
> atomic_t mnt_avail_nr; /* number of available VE mounts */
> + atomic_t mnt_failcount;
> int mnt_max_nr;
>
> #ifdef CONFIG_COREDUMP
> @@ -121,6 +126,7 @@ struct ve_struct {
> spinlock_t aio_nr_lock;
> unsigned long aio_nr;
> unsigned long aio_max_nr;
> + atomic_t aio_failcount;
> #endif
> struct vfsmount *devtmpfs_mnt;
> };
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index c94d4240e3d3..9d57e7999ae0 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -2891,6 +2891,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
> if (!bpf_cap && type == BPF_PROG_TYPE_CGROUP_DEVICE) {
> load_ve = get_exec_env();
> if (atomic_dec_if_positive(&load_ve->bpf_prog_avail_nr) < 0) {
> + atomic_inc(&load_ve->bpf_prog_failcount);
> load_ve = NULL;
> err = -ENOSPC;
> goto put_token;
> diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
> index 0f02835765ff..55a83b0b5981 100644
> --- a/kernel/ve/ve.c
> +++ b/kernel/ve/ve.c
> @@ -99,10 +99,13 @@ struct ve_struct ve0 = {
> .features = -1,
> .sched_lat_ve.cur = &ve0_lat_stats,
> .netns_avail_nr = ATOMIC_INIT(INT_MAX),
> + .netns_failcount = ATOMIC_INIT(0),
> .netns_max_nr = INT_MAX,
> .netif_avail_nr = ATOMIC_INIT(INT_MAX),
> + .netif_failcount = ATOMIC_INIT(0),
> .netif_max_nr = INT_MAX,
> .bpf_prog_avail_nr = ATOMIC_INIT(INT_MAX),
> + .bpf_prog_failcount = ATOMIC_INIT(0),
> .bpf_prog_max_nr = INT_MAX,
> .fsync_enable = FSYNC_FILTERED,
> ._randomize_va_space =
> @@ -114,8 +117,16 @@ struct ve_struct ve0 = {
>
> .arp_neigh_nr = ATOMIC_INIT(0),
> .nd_neigh_nr = ATOMIC_INIT(0),
> + .neigh_tbl_failcount = ATOMIC_INIT(0),
> .mnt_avail_nr = ATOMIC_INIT(INT_MAX),
> .mnt_max_nr = INT_MAX,
> + .mnt_failcount = ATOMIC_INIT(0),
> +#ifdef CONFIG_AIO
> + .aio_nr_lock = __SPIN_LOCK_UNLOCKED(aio_nr_lock),
> + .aio_nr = 0,
> + .aio_max_nr = AIO_MAX_NR_DEFAULT,
> + .aio_failcount = ATOMIC_INIT(0),
> +#endif
> .meminfo_val = VE_MEMINFO_SYSTEM,
> .umh_running_helpers = ATOMIC_INIT(0),
> .umh_helpers_waitq = __WAIT_QUEUE_HEAD_INITIALIZER(ve0.umh_helpers_waitq),
> @@ -780,12 +791,15 @@ static struct cgroup_subsys_state *ve_create(struct cgroup_subsys_state *parent_
> ve->fsync_enable = FSYNC_FILTERED;
>
> atomic_set(&ve->netns_avail_nr, NETNS_MAX_NR_DEFAULT);
> + atomic_set(&ve->netns_failcount, 0);
> ve->netns_max_nr = NETNS_MAX_NR_DEFAULT;
>
> atomic_set(&ve->netif_avail_nr, NETIF_MAX_NR_DEFAULT);
> + atomic_set(&ve->netif_failcount, 0);
> ve->netif_max_nr = NETIF_MAX_NR_DEFAULT;
>
> atomic_set(&ve->bpf_prog_avail_nr, BPF_PROG_MAX_NR_DEFAULT);
> + atomic_set(&ve->bpf_prog_failcount, 0);
> ve->bpf_prog_max_nr = BPF_PROG_MAX_NR_DEFAULT;
>
> err = ve_log_init(ve);
> @@ -812,7 +826,9 @@ static struct cgroup_subsys_state *ve_create(struct cgroup_subsys_state *parent_
>
> atomic_set(&ve->arp_neigh_nr, 0);
> atomic_set(&ve->nd_neigh_nr, 0);
> + atomic_set(&ve->neigh_tbl_failcount, 0);
> ve->mnt_max_nr = MNT_MAX_NR_DEFAULT;
> + atomic_set(&ve->mnt_failcount, 0);
> atomic_set(&ve->mnt_avail_nr, MNT_MAX_NR_DEFAULT);
>
> #ifdef CONFIG_COREDUMP
> @@ -825,6 +841,7 @@ static struct cgroup_subsys_state *ve_create(struct cgroup_subsys_state *parent_
> spin_lock_init(&ve->aio_nr_lock);
> ve->aio_nr = 0;
> ve->aio_max_nr = AIO_MAX_NR_DEFAULT;
> + atomic_set(&ve->aio_failcount, 0);
> #endif
>
> return &ve->css;
> @@ -1065,6 +1082,50 @@ VE_RESOURCE(mnt);
> VE_RESOURCE(netif);
> VE_RESOURCE(bpf_prog);
>
> +static const struct ve_failcount_entry {
> + const char *name;
> + size_t offset;
> +} ve_failcounts[] = {
> +#define VE_FC_ENTRY(name) { #name, offsetof(struct ve_struct, name##_failcount) }
> + VE_FC_ENTRY(netns),
> + VE_FC_ENTRY(mnt),
> + VE_FC_ENTRY(netif),
> + VE_FC_ENTRY(bpf_prog),
> + VE_FC_ENTRY(neigh_tbl),
> +#ifdef CONFIG_AIO
> + VE_FC_ENTRY(aio),
> +#endif
> + {}
> +};
> +
> +static int ve_failcount_read(struct seq_file *sf, void *v)
> +{
> + struct ve_struct *ve = css_to_ve(seq_css(sf));
> + const struct ve_failcount_entry *entry;
> + atomic_t *fc;
> +
> + for (entry = ve_failcounts; entry->name; entry++) {
> + fc = (void *)ve + entry->offset;
> + seq_printf(sf, "%s: %d\n", entry->name, atomic_read(fc));
> + }
> + return 0;
> +}
> +
> +static ssize_t ve_failcount_write(struct kernfs_open_file *of, char *buf,
> + size_t nbytes, loff_t off)
> +{
> + struct ve_struct *ve = css_to_ve(of_css(of));
> + const struct ve_failcount_entry *entry;
> + atomic_t *fc;
Should we allow the container itself to reset the failcount? All other
resource write handlers have a check that return EPERM when we are not
super ve. Here we will allow the container to reset its failcount so it
will no longer be trustworthy information.
--
Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
next prev parent reply other threads:[~2026-08-19 13:16 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 9:07 [Devel] [PATCH VZ10 v6 0/9] Add per-VE failcount support Vladimir Riabchun
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 1/9] ve/ve.{h, c}: Farewell to spaces as indents Vladimir Riabchun
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 2/9] ve/namespace: Fix UAF in alloc_mnt_ns Vladimir Riabchun
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 3/9] ve/fs: Rework per-ve mount count Vladimir Riabchun
2026-08-19 13:16 ` Vasileios Almpanis
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 4/9] selftests/ve: Update ve_ns_owner_test Vladimir Riabchun
2026-08-19 13:16 ` Vasileios Almpanis
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 5/9] ve: Move from global VE mounts limit to per-VE limit Vladimir Riabchun
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 6/9] ve/ve.c: Generate VE resource accessors using macros Vladimir Riabchun
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 7/9] ve: Introduce per-VE failcount Vladimir Riabchun
2026-08-19 13:16 ` Vasileios Almpanis [this message]
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 8/9] selftests/ve: Add more helpers Vladimir Riabchun
2026-08-19 9:07 ` [Devel] [PATCH VZ10 v6 9/9] selftests/ve: Add mount accounting selftest Vladimir Riabchun
2026-08-19 13:16 ` Vasileios Almpanis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178714537779.798038.4175166408746452014.b4-review@b4 \
--to=vasileios.almpanis@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.