The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxcfs/pull/323

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 77f4399a76b3b3730d561e1efcecb7d5f3346e27 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@ubuntu.com>
Date: Mon, 24 Feb 2020 12:01:07 +0100
Subject: [PATCH 1/2] bindings: port cpuview to new cgroup getters

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
 bindings.c       | 25 +++----------------------
 bindings.h       |  1 -
 cgroups/cgfsng.c | 19 +++++++++++++++++++
 cgroups/cgroup.h |  3 +++
 sysfs_fuse.c     |  6 +++---
 5 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/bindings.c b/bindings.c
index 7ac3ff1..ce9a511 100644
--- a/bindings.c
+++ b/bindings.c
@@ -412,7 +412,7 @@ static void lock_mutex(pthread_mutex_t *l)
        }
 }
 
-static struct cgroup_ops *cgroup_ops;
+struct cgroup_ops *cgroup_ops;
 
 static int cgroup_mount_ns_fd = -1;
 
@@ -3667,24 +3667,6 @@ static double exact_cpu_count(const char *cg)
        return rv;
 }
 
-/*
- * Determine whether CPU views should be used or not.
- */
-bool use_cpuview(const char *cg)
-{
-       int cfd;
-
-       cfd = find_mounted_controller("cpu");
-       if (cfd < 0)
-               return false;
-
-       cfd = find_mounted_controller("cpuacct");
-       if (cfd < 0)
-               return false;
-
-       return true;
-}
-
 /*
  * check whether this is a '^processor" line in /proc/cpuinfo
  */
@@ -3736,8 +3718,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
        if (!cpuset)
                goto err;
 
-       use_view = use_cpuview(cg);
-
+       use_view = cgroup_ops->can_use_cpuview(cgroup_ops);
        if (use_view)
                max_cpus = max_cpu_count(cg);
 
@@ -4865,7 +4846,7 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
                goto err;
        }
 
-       if (use_cpuview(cg) && cg_cpu_usage) {
+       if (cgroup_ops->can_use_cpuview(cgroup_ops) && cg_cpu_usage) {
                total_len = cpuview_proc_stat(cg, cpuset, cg_cpu_usage, 
cg_cpu_usage_size,
                                f, d->buf, d->buflen);
                goto out;
diff --git a/bindings.h b/bindings.h
index 229d64c..d41994f 100644
--- a/bindings.h
+++ b/bindings.h
@@ -79,7 +79,6 @@ extern int read_file_fuse(const char *path, char *buf, size_t 
size,
                          struct file_info *d);
 extern void prune_init_slice(char *cg);
 extern char *get_cpuset(const char *cg);
-extern bool use_cpuview(const char *cg);
 extern int max_cpu_count(const char *cg);
 extern void do_release_file_info(struct fuse_file_info *fi);
 extern int cpu_number_in_cpuset(const char *cpuset);
diff --git a/cgroups/cgfsng.c b/cgroups/cgfsng.c
index 60ac136..8d972b7 100644
--- a/cgroups/cgfsng.c
+++ b/cgroups/cgfsng.c
@@ -794,6 +794,24 @@ static int cgfsng_get_io_wait_time(struct cgroup_ops *ops, 
const char *cgroup,
        return cgfsng_get_io(ops, cgroup, "blkio.io_wait_time_recursive", 
value);
 }
 
+static bool cgfsng_can_use_cpuview(struct cgroup_ops *ops)
+{
+       struct hierarchy *cpu, *cpuacct;
+
+       if (pure_unified_layout(ops))
+               return false;
+
+       cpu = ops->get_hierarchy(ops, "cpu");
+       if (!cpu || is_unified_hierarchy(cpu))
+               return false;
+
+       cpuacct = ops->get_hierarchy(ops, "cpuacct");
+       if (!cpuacct || is_unified_hierarchy(cpuacct))
+               return false;
+
+       return true;
+}
+
 /* At startup, parse_hierarchies finds all the info we need about cgroup
  * mountpoints and current cgroups, and stores it in @d.
  */
@@ -999,6 +1017,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
 
        /* cpuset */
        cgfsng_ops->get_cpuset_cpus = cgfsng_get_cpuset_cpus;
+       cgfsng_ops->can_use_cpuview = cgfsng_can_use_cpuview;
 
        /* blkio */
        cgfsng_ops->get_io_service_bytes        = cgfsng_get_io_service_bytes;
diff --git a/cgroups/cgroup.h b/cgroups/cgroup.h
index 4221221..e955e75 100644
--- a/cgroups/cgroup.h
+++ b/cgroups/cgroup.h
@@ -138,6 +138,7 @@ struct cgroup_ops {
        /* cpuset */
        int (*get_cpuset_cpus)(struct cgroup_ops *ops, const char *cgroup,
                               char **value);
+       bool (*can_use_cpuview)(struct cgroup_ops *ops);
 
        /* io */
        int (*get_io_service_bytes)(struct cgroup_ops *ops, const char *cgroup,
@@ -152,6 +153,8 @@ struct cgroup_ops {
                                char **value);
 };
 
+extern struct cgroup_ops *cgroup_ops;
+
 extern struct cgroup_ops *cgroup_init(void);
 extern void cgroup_exit(struct cgroup_ops *ops);
 
diff --git a/sysfs_fuse.c b/sysfs_fuse.c
index d2b187b..f6bf203 100644
--- a/sysfs_fuse.c
+++ b/sysfs_fuse.c
@@ -31,7 +31,8 @@
 #include <sys/vfs.h>
 
 #include "bindings.h"
-#include "config.h" // for VERSION
+#include "cgroups/cgroup.h"
+#include "config.h"
 #include "sysfs_fuse.h"
 
 static int sys_devices_system_cpu_online_read(char *buf, size_t size,
@@ -72,8 +73,7 @@ static int sys_devices_system_cpu_online_read(char *buf, 
size_t size,
        if (!cpuset)
                goto err;
 
-       use_view = use_cpuview(cg);
-
+       use_view = cgroup_ops->can_use_cpuview(cgroup_ops);
        if (use_view)
                max_cpus = max_cpu_count(cg);
 

From 54a6d46a8e9e33cbbc9fa380ff9e5954a4fb088d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@ubuntu.com>
Date: Mon, 24 Feb 2020 12:56:05 +0100
Subject: [PATCH 2/2] bindings: use more cleanup macros

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
 bindings.c | 530 +++++++++++++++++++++++------------------------------
 1 file changed, 226 insertions(+), 304 deletions(-)

diff --git a/bindings.c b/bindings.c
index ce9a511..9561b8c 100644
--- a/bindings.c
+++ b/bindings.c
@@ -214,6 +214,7 @@ static struct load_node *locate_node(char *cg, int locate)
                f = f->next;
        return f;
 }
+
 /* Delete the load_node n and return the next node of it. */
 static struct load_node *del_node(struct load_node *n, int locate)
 {
@@ -227,18 +228,17 @@ static struct load_node *del_node(struct load_node *n, 
int locate)
                n->next->pre = n->pre;
        }
        g = n->next;
-       free(n->cg);
-       free(n);
+       free_disarm(n->cg);
+       free_disarm(n);
        pthread_rwlock_unlock(&load_hash[locate].rdlock);
        return g;
 }
 
 static void load_free(void)
 {
-       int i;
        struct load_node *f, *p;
 
-       for (i = 0; i < LOAD_SIZE; i++) {
+       for (int i = 0; i < LOAD_SIZE; i++) {
                pthread_mutex_lock(&load_hash[i].lock);
                pthread_rwlock_wrlock(&load_hash[i].rilock);
                pthread_rwlock_wrlock(&load_hash[i].rdlock);
@@ -251,12 +251,14 @@ static void load_free(void)
                        pthread_rwlock_destroy(&load_hash[i].rdlock);
                        continue;
                }
-               for (f = load_hash[i].next; f; ) {
-                       free(f->cg);
+
+               for (f = load_hash[i].next; f;) {
+                       free_disarm(f->cg);
                        p = f->next;
-                       free(f);
+                       free_disarm(f);
                        f = p;
                }
+
                pthread_mutex_unlock(&load_hash[i].lock);
                pthread_mutex_destroy(&load_hash[i].lock);
                pthread_rwlock_unlock(&load_hash[i].rilock);
@@ -302,7 +304,7 @@ static bool cpuview_init_head(struct cg_proc_stat_head 
**head)
 
        if (pthread_rwlock_init(&(*head)->lock, NULL) != 0) {
                lxcfs_error("%s\n", "Failed to initialize list lock");
-               free(*head);
+               free_disarm(*head);
                return false;
        }
 
@@ -325,10 +327,8 @@ static bool init_cpuview()
 
 err:
        for (i = 0; i < CPUVIEW_HASH_SIZE; i++) {
-               if (proc_stat_history[i]) {
-                       free(proc_stat_history[i]);
-                       proc_stat_history[i] = NULL;
-               }
+               if (proc_stat_history[i])
+                       free_disarm(proc_stat_history[i]);
        }
 
        return false;
@@ -337,10 +337,10 @@ static bool init_cpuview()
 static void free_proc_stat_node(struct cg_proc_stat *node)
 {
        pthread_mutex_destroy(&node->lock);
-       free(node->cg);
-       free(node->usage);
-       free(node->view);
-       free(node);
+       free_disarm(node->cg);
+       free_disarm(node->usage);
+       free_disarm(node->view);
+       free_disarm(node);
 }
 
 static void cpuview_free_head(struct cg_proc_stat_head *head)
@@ -361,7 +361,7 @@ static void cpuview_free_head(struct cg_proc_stat_head 
*head)
        }
 
        pthread_rwlock_destroy(&head->lock);
-       free(head);
+       free_disarm(head);
 }
 
 static void free_cpuview()
@@ -465,7 +465,7 @@ static void remove_initpid(struct pidns_init_store *e)
        h = HASH(e->ino);
        if (pidns_hash_table[h] == e) {
                pidns_hash_table[h] = e->next;
-               free(e);
+               free_disarm(e);
                return;
        }
 
@@ -473,7 +473,7 @@ static void remove_initpid(struct pidns_init_store *e)
        while (tmp) {
                if (tmp->next == e) {
                        tmp->next = e->next;
-                       free(e);
+                       free_disarm(e);
                        return;
                }
                tmp = tmp->next;
@@ -514,7 +514,7 @@ static void prune_initpid_store(void)
                                else
                                        pidns_hash_table[i] = e->next;
                                e = e->next;
-                               free(delme);
+                               free_disarm(delme);
                        } else {
                                prev = e;
                                e = e->next;
@@ -1086,8 +1086,8 @@ void free_key(struct cgfs_files *k)
 {
        if (!k)
                return;
-       free(k->name);
-       free(k);
+       free_disarm(k->name);
+       free_disarm(k);
 }
 
 void free_keys(struct cgfs_files **keys)
@@ -1099,7 +1099,7 @@ void free_keys(struct cgfs_files **keys)
        for (i = 0; keys[i]; i++) {
                free_key(keys[i]);
        }
-       free(keys);
+       free_disarm(keys);
 }
 
 bool cgfs_param_exist(const char *controller, const char *cgroup, const char 
*file)
@@ -2057,16 +2057,11 @@ void do_release_file_info(struct fuse_file_info *fi)
 
        fi->fh = 0;
 
-       free(f->controller);
-       f->controller = NULL;
-       free(f->cgroup);
-       f->cgroup = NULL;
-       free(f->file);
-       f->file = NULL;
-       free(f->buf);
-       f->buf = NULL;
-       free(f);
-       f = NULL;
+       free_disarm(f->controller);
+       free_disarm(f->cgroup);
+       free_disarm(f->file);
+       free_disarm(f->buf);
+       free_disarm(f);
 }
 
 int cg_releasedir(const char *path, struct fuse_file_info *fi)
@@ -3259,11 +3254,13 @@ static void get_blkio_io_value(char *str, unsigned 
major, unsigned minor, char *
 
 int read_file_fuse(const char *path, char *buf, size_t size, struct file_info 
*d)
 {
-       size_t linelen = 0, total_len = 0, rv = 0;
-       char *line = NULL;
+       __do_free char *line = NULL;
+       __do_fclose FILE *f = NULL;
+       size_t linelen = 0, total_len = 0;
        char *cache = d->buf;
        size_t cache_size = d->buflen;
-       FILE *f = fopen(path, "r");
+
+       f = fopen(path, "r");
        if (!f)
                return 0;
 
@@ -3271,13 +3268,11 @@ int read_file_fuse(const char *path, char *buf, size_t 
size, struct file_info *d
                ssize_t l = snprintf(cache, cache_size, "%s", line);
                if (l < 0) {
                        perror("Error writing to cache");
-                       rv = 0;
-                       goto err;
+                       return 0;
                }
                if (l >= cache_size) {
                        lxcfs_error("%s\n", "Internal error: truncated write to 
cache.");
-                       rv = 0;
-                       goto err;
+                       return 0;
                }
                cache += l;
                cache_size -= l;
@@ -3290,13 +3285,10 @@ int read_file_fuse(const char *path, char *buf, size_t 
size, struct file_info *d
 
        /* read from off 0 */
        memcpy(buf, d->buf, total_len);
-       rv = total_len;
-  err:
-       fclose(f);
-       free(line);
-       if (d->size > rv)
-               d->cached = d->size - rv;
-       return rv;
+
+       if (d->size > total_len)
+               d->cached = d->size - total_len;
+       return total_len;
 }
 
 /*
@@ -3570,24 +3562,18 @@ static bool cpuline_in_cpuset(const char *line, const 
char *cpuset)
  */
 static bool read_cpu_cfs_param(const char *cg, const char *param, int64_t 
*value)
 {
-       bool rv = false;
-       char file[11 + 6 + 1]; // cpu.cfs__us + quota/period + \0
-       char *str = NULL;
+       __do_free char *str = NULL;
+       char file[11 + 6 + 1]; /* cpu.cfs__us + quota/period + \0 */
 
-       sprintf(file, "cpu.cfs_%s_us", param);
+       snprintf(file, sizeof(file), "cpu.cfs_%s_us", param);
 
        if (!cgroup_ops->get(cgroup_ops, "cpu", cg, file, &str))
-               goto err;
+               return false;
 
        if (sscanf(str, "%ld", value) != 1)
-               goto err;
-
-       rv = true;
+               return false;
 
-err:
-       if (str)
-               free(str);
-       return rv;
+       return true;
 }
 
 /*
@@ -3680,29 +3666,32 @@ static bool is_processor_line(const char *line)
 }
 
 static int proc_cpuinfo_read(char *buf, size_t size, off_t offset,
-               struct fuse_file_info *fi)
+                            struct fuse_file_info *fi)
 {
+       __do_free char *cg = NULL, *cpuset = NULL, *line = NULL;
+       __do_fclose FILE *f = NULL;
        struct fuse_context *fc = fuse_get_context();
        struct file_info *d = (struct file_info *)fi->fh;
-       char *cg;
-       char *cpuset = NULL;
-       char *line = NULL;
-       size_t linelen = 0, total_len = 0, rv = 0;
+       size_t linelen = 0, total_len = 0;
        bool am_printing = false, firstline = true, is_s390x = false;
        int curcpu = -1, cpu, max_cpus = 0;
        bool use_view;
        char *cache = d->buf;
        size_t cache_size = d->buflen;
-       FILE *f = NULL;
 
        if (offset){
+               int left;
+
                if (offset > d->size)
                        return -EINVAL;
+
                if (!d->cached)
                        return 0;
-               int left = d->size - offset;
+
+               left = d->size - offset;
                total_len = left > size ? size: left;
                memcpy(buf, cache + offset, total_len);
+
                return total_len;
        }
 
@@ -3716,7 +3705,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
 
        cpuset = get_cpuset(cg);
        if (!cpuset)
-               goto err;
+               return 0;
 
        use_view = cgroup_ops->can_use_cpuview(cgroup_ops);
        if (use_view)
@@ -3724,7 +3713,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
 
        f = fopen("/proc/cpuinfo", "r");
        if (!f)
-               goto err;
+               return 0;
 
        while (getline(&line, &linelen, f) != -1) {
                ssize_t l;
@@ -3747,13 +3736,11 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
                                l = snprintf(cache, cache_size, "processor      
: %d\n", curcpu);
                                if (l < 0) {
                                        perror("Error writing to cache");
-                                       rv = 0;
-                                       goto err;
+                                       return 0;
                                }
                                if (l >= cache_size) {
                                        lxcfs_error("%s\n", "Internal error: 
truncated write to cache.");
-                                       rv = 0;
-                                       goto err;
+                                       return 0;
                                }
                                cache += l;
                                cache_size -= l;
@@ -3769,18 +3756,16 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
                        curcpu ++;
                        p = strchr(line, ':');
                        if (!p || !*p)
-                               goto err;
+                               return 0;
                        p++;
                        l = snprintf(cache, cache_size, "processor %d:%s", 
curcpu, p);
                        if (l < 0) {
                                perror("Error writing to cache");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
                        if (l >= cache_size) {
                                lxcfs_error("%s\n", "Internal error: truncated 
write to cache.");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
                        cache += l;
                        cache_size -= l;
@@ -3792,13 +3777,11 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
                        l = snprintf(cache, cache_size, "%s", line);
                        if (l < 0) {
                                perror("Error writing to cache");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
                        if (l >= cache_size) {
                                lxcfs_error("%s\n", "Internal error: truncated 
write to cache.");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
                        cache += l;
                        cache_size -= l;
@@ -3807,34 +3790,35 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
        }
 
        if (is_s390x) {
-               char *origcache = d->buf;
+               __do_free char *origcache = d->buf;
                ssize_t l;
-               do {
-                       d->buf = malloc(d->buflen);
-               } while (!d->buf);
+
+               d->buf = malloc(d->buflen);
+               if (!d->buf) {
+                       d->buf = move_ptr(origcache);
+                       return 0;
+               }
+
                cache = d->buf;
                cache_size = d->buflen;
                total_len = 0;
                l = snprintf(cache, cache_size, "vendor_id       : IBM/S390\n");
-               if (l < 0 || l >= cache_size) {
-                       free(origcache);
-                       goto err;
-               }
+               if (l < 0 || l >= cache_size)
+                       return 0;
+
                cache_size -= l;
                cache += l;
                total_len += l;
                l = snprintf(cache, cache_size, "# processors    : %d\n", 
curcpu + 1);
-               if (l < 0 || l >= cache_size) {
-                       free(origcache);
-                       goto err;
-               }
+               if (l < 0 || l >= cache_size)
+                       return 0;
+
                cache_size -= l;
                cache += l;
                total_len += l;
                l = snprintf(cache, cache_size, "%s", origcache);
-               free(origcache);
                if (l < 0 || l >= cache_size)
-                       goto err;
+                       return 0;
                total_len += l;
        }
 
@@ -3844,14 +3828,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, 
off_t offset,
 
        /* read from off 0 */
        memcpy(buf, d->buf, total_len);
-       rv = total_len;
-err:
-       if (f)
-               fclose(f);
-       free(line);
-       free(cpuset);
-       free(cg);
-       return rv;
+       return total_len;
 }
 
 static uint64_t get_reaper_start_time(pid_t pid)
@@ -3996,13 +3973,14 @@ static double get_reaper_age(pid_t pid)
  */
 static int read_cpuacct_usage_all(char *cg, char *cpuset, struct cpuacct_usage 
**return_usage, int *size)
 {
+       __do_free char *usage_str = NULL;
+       __do_free struct cpuacct_usage *cpu_usage = NULL;
        int cpucount = get_nprocs_conf();
-       struct cpuacct_usage *cpu_usage;
-       int rv = 0, i, j, ret;
+       int read_pos = 0, read_cnt=0;
+       int i, j, ret;
        int cg_cpu;
        uint64_t cg_user, cg_system;
        int64_t ticks_per_sec;
-       char *usage_str = NULL;
 
        ticks_per_sec = sysconf(_SC_CLK_TCK);
 
@@ -4020,23 +3998,21 @@ static int read_cpuacct_usage_all(char *cg, char 
*cpuset, struct cpuacct_usage *
 
        memset(cpu_usage, 0, sizeof(struct cpuacct_usage) * cpucount);
        if (!cgroup_ops->get(cgroup_ops, "cpuacct", cg, "cpuacct.usage_all", 
&usage_str)) {
-               // read cpuacct.usage_percpu instead
+               char *data = NULL;
+               int i = 0, read_pos = 0, read_cnt=0;
+               size_t sz = 0, asz = 0;
+
+               /* read cpuacct.usage_percpu instead. */
                lxcfs_v("failed to read cpuacct.usage_all. reading 
cpuacct.usage_percpu instead\n%s", "");
-               if (!cgroup_ops->get(cgroup_ops, "cpuacct", cg, 
"cpuacct.usage_percpu", &usage_str)) {
-                       rv = -1;
-                       goto err;
-               }
+               if (!cgroup_ops->get(cgroup_ops, "cpuacct", cg, 
"cpuacct.usage_percpu", &usage_str))
+                       return -1;
                lxcfs_v("usage_str: %s\n", usage_str);
 
-               // convert cpuacct.usage_percpu into cpuacct.usage_all
+               /* convert cpuacct.usage_percpu into cpuacct.usage_all. */
                lxcfs_v("converting cpuacct.usage_percpu into 
cpuacct.usage_all\n%s", "");
 
-               char *data = NULL;
-               size_t sz = 0, asz = 0;
-
                must_strcat(&data, &sz, &asz, "cpu user system\n");
 
-               int i = 0, read_pos = 0, read_cnt=0;
                while (sscanf(usage_str + read_pos, "%lu %n", &cg_user, 
&read_cnt) > 0) {
                        lxcfs_debug("i: %d, cg_user: %lu, read_pos: %d, 
read_cnt: %d\n", i, cg_user, read_pos, read_cnt);
                        must_strcat(&data, &sz, &asz, "%d %lu 0\n", i, cg_user);
@@ -4044,18 +4020,15 @@ static int read_cpuacct_usage_all(char *cg, char 
*cpuset, struct cpuacct_usage *
                        read_pos += read_cnt;
                }
 
-               free(usage_str);
                usage_str = data;
 
                lxcfs_v("usage_str: %s\n", usage_str);
        }
 
-       int read_pos = 0, read_cnt=0;
        if (sscanf(usage_str, "cpu user system\n%n", &read_cnt) != 0) {
                lxcfs_error("read_cpuacct_usage_all reading first line from "
                                "%s/cpuacct.usage_all failed.\n", cg);
-               rv = -1;
-               goto err;
+               return -1;
        }
 
        read_pos += read_cnt;
@@ -4070,8 +4043,7 @@ static int read_cpuacct_usage_all(char *cg, char *cpuset, 
struct cpuacct_usage *
                if (ret != 3) {
                        lxcfs_error("read_cpuacct_usage_all reading from 
%s/cpuacct.usage_all "
                                        "failed.\n", cg);
-                       rv = -1;
-                       goto err;
+                       return -1;
                }
 
                read_pos += read_cnt;
@@ -4082,20 +4054,9 @@ static int read_cpuacct_usage_all(char *cg, char 
*cpuset, struct cpuacct_usage *
                j++;
        }
 
-       rv = 0;
-       *return_usage = cpu_usage;
+       *return_usage = move_ptr(cpu_usage);
        *size = cpucount;
-
-err:
-       if (usage_str)
-               free(usage_str);
-
-       if (rv != 0) {
-               free(cpu_usage);
-               *return_usage = NULL;
-       }
-
-       return rv;
+       return 0;
 }
 
 static unsigned long diff_cpu_usage(struct cpuacct_usage *older, struct 
cpuacct_usage *newer, struct cpuacct_usage *diff, int cpu_count)
@@ -4323,8 +4284,7 @@ static struct cg_proc_stat *add_proc_stat_node(struct 
cg_proc_stat *new_node)
 
 static bool expand_proc_stat_node(struct cg_proc_stat *node, int cpu_count)
 {
-       struct cpuacct_usage *new_usage, *new_view;
-       int i;
+       __do_free struct cpuacct_usage *new_usage = NULL, *new_view = NULL;
 
        /* Allocate new memory */
        new_usage = malloc(sizeof(struct cpuacct_usage) * cpu_count);
@@ -4332,13 +4292,11 @@ static bool expand_proc_stat_node(struct cg_proc_stat 
*node, int cpu_count)
                return false;
 
        new_view = malloc(sizeof(struct cpuacct_usage) * cpu_count);
-       if (!new_view) {
-               free(new_usage);
+       if (!new_view)
                return false;
-       }
 
        /* Copy existing data & initialize new elements */
-       for (i = 0; i < cpu_count; i++) {
+       for (int i = 0; i < cpu_count; i++) {
                if (i < node->cpu_count) {
                        new_usage[i].user = node->usage[i].user;
                        new_usage[i].system = node->usage[i].system;
@@ -4359,10 +4317,10 @@ static bool expand_proc_stat_node(struct cg_proc_stat 
*node, int cpu_count)
        }
 
        free(node->usage);
-       free(node->view);
+       node->usage = move_ptr(new_usage);
 
-       node->usage = new_usage;
-       node->view = new_view;
+       free(node->view);
+       node->view = move_ptr(new_view);
        node->cpu_count = cpu_count;
 
        return true;
@@ -4420,19 +4378,23 @@ static void reset_proc_stat_node(struct cg_proc_stat 
*node, struct cpuacct_usage
        node->cpu_count = cpu_count;
 }
 
-static int cpuview_proc_stat(const char *cg, const char *cpuset, struct 
cpuacct_usage *cg_cpu_usage, int cg_cpu_usage_size, FILE *f, char *buf, size_t 
buf_size)
+static int cpuview_proc_stat(const char *cg, const char *cpuset,
+                            struct cpuacct_usage *cg_cpu_usage,
+                            int cg_cpu_usage_size, FILE *f, char *buf,
+                            size_t buf_size)
 {
-       char *line = NULL;
-       size_t linelen = 0, total_len = 0, rv = 0, l;
+       __do_free char *line = NULL;
+       __do_free struct cpuacct_usage *diff = NULL;
+       size_t linelen = 0, total_len = 0, l;
        int curcpu = -1; /* cpu numbering starts at 0 */
        int physcpu, i;
        int max_cpus = max_cpu_count(cg), cpu_cnt = 0;
-       unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq 
= 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
+       unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0,
+                     irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 
0;
        unsigned long user_sum = 0, system_sum = 0, idle_sum = 0;
        unsigned long user_surplus = 0, system_surplus = 0;
        unsigned long total_sum, threshold;
        struct cg_proc_stat *stat_node;
-       struct cpuacct_usage *diff = NULL;
        int nprocs = get_nprocs_conf();
 
        if (cg_cpu_usage_size < nprocs)
@@ -4446,10 +4408,10 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
 
                if (strlen(line) == 0)
                        continue;
-               if (sscanf(line, "cpu%9[^ ]", cpu_char) != 1) {
-                       /* not a ^cpuN line containing a number N */
+
+               /* not a ^cpuN line containing a number N */
+               if (sscanf(line, "cpu%9[^ ]", cpu_char) != 1)
                        break;
-               }
 
                if (sscanf(cpu_char, "%d", &physcpu) != 1)
                        continue;
@@ -4461,9 +4423,8 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
                cpu_cnt ++;
 
                if (!cpu_in_cpuset(physcpu, cpuset)) {
-                       for (i = curcpu; i <= physcpu; i++) {
+                       for (i = curcpu; i <= physcpu; i++)
                                cg_cpu_usage[i].online = false;
-                       }
                        continue;
                }
 
@@ -4514,14 +4475,12 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
 
        if (!stat_node) {
                lxcfs_error("unable to find/create stat node for %s\n", cg);
-               rv = 0;
-               goto err;
+               return 0;
        }
 
        diff = malloc(sizeof(struct cpuacct_usage) * nprocs);
        if (!diff) {
-               rv = 0;
-               goto err;
+               return 0;
        }
 
        /*
@@ -4560,6 +4519,13 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
 
        /* Calculate usage counters of visible CPUs */
        if (max_cpus > 0) {
+               unsigned long diff_user = 0;
+               unsigned long diff_system = 0;
+               unsigned long diff_idle = 0;
+               unsigned long max_diff_idle = 0;
+               unsigned long max_diff_idle_index = 0;
+               double exact_cpus;
+
                /* threshold = maximum usage per cpu, including idle */
                threshold = total_sum / cpu_cnt * max_cpus;
 
@@ -4576,21 +4542,15 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
                                continue;
 
                        /* Add user */
-                       add_cpu_usage(
-                                       &user_surplus,
-                                       &diff[curcpu],
-                                       &diff[curcpu].user,
-                                       threshold);
+                       add_cpu_usage(&user_surplus, &diff[curcpu],
+                                     &diff[curcpu].user, threshold);
 
                        if (diff[curcpu].user + diff[curcpu].system >= 
threshold)
                                continue;
 
                        /* If there is still room, add system */
-                       add_cpu_usage(
-                                       &system_surplus,
-                                       &diff[curcpu],
-                                       &diff[curcpu].system,
-                                       threshold);
+                       add_cpu_usage(&system_surplus, &diff[curcpu],
+                                     &diff[curcpu].system, threshold);
                }
 
                if (user_surplus > 0)
@@ -4598,11 +4558,6 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
                if (system_surplus > 0)
                        lxcfs_debug("leftover system: %lu for %s\n", 
system_surplus, cg);
 
-               unsigned long diff_user = 0;
-               unsigned long diff_system = 0;
-               unsigned long diff_idle = 0;
-               unsigned long max_diff_idle = 0;
-               unsigned long max_diff_idle_index = 0;
                for (curcpu = 0, i = -1; curcpu < nprocs; curcpu++) {
                        if (!stat_node->usage[curcpu].online)
                                continue;
@@ -4632,11 +4587,12 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
                }
                lxcfs_v("total. diff_user: %lu, diff_system: %lu, diff_idle: 
%lu\n", diff_user, diff_system, diff_idle);
 
-               // revise cpu usage view to support partial cpu case
-               double exact_cpus = exact_cpu_count(cg);
+               /* revise cpu usage view to support partial cpu case. */
+               exact_cpus = exact_cpu_count(cg);
                if (exact_cpus < (double)max_cpus){
-                       lxcfs_v("revising cpu usage view to match the exact cpu 
count [%f]\n", exact_cpus);
                        unsigned long delta = (unsigned 
long)((double)(diff_user + diff_system + diff_idle) * (1 - exact_cpus / 
(double)max_cpus));
+
+                       lxcfs_v("revising cpu usage view to match the exact cpu 
count [%f]\n", exact_cpus);
                        lxcfs_v("delta: %lu\n", delta);
                        lxcfs_v("idle_sum before: %lu\n", idle_sum);
                        idle_sum = idle_sum > delta ? idle_sum - delta : 0;
@@ -4672,13 +4628,11 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
 
        if (l < 0) {
                perror("Error writing to cache");
-               rv = 0;
-               goto err;
+               return 0;
        }
        if (l >= buf_size) {
                lxcfs_error("%s\n", "Internal error: truncated write to 
cache.");
-               rv = 0;
-               goto err;
+               return 0;
        }
 
        buf += l;
@@ -4704,14 +4658,12 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
 
                if (l < 0) {
                        perror("Error writing to cache");
-                       rv = 0;
-                       goto err;
+                       return 0;
 
                }
                if (l >= buf_size) {
                        lxcfs_error("%s\n", "Internal error: truncated write to 
cache.");
-                       rv = 0;
-                       goto err;
+                       return 0;
                }
 
                buf += l;
@@ -4724,14 +4676,12 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
 
        if (l < 0) {
                perror("Error writing to cache");
-               rv = 0;
-               goto err;
+               return 0;
 
        }
        if (l >= buf_size) {
                lxcfs_error("%s\n", "Internal error: truncated write to 
cache.");
-               rv = 0;
-               goto err;
+               return 0;
        }
 
        buf += l;
@@ -4743,52 +4693,43 @@ static int cpuview_proc_stat(const char *cg, const char 
*cpuset, struct cpuacct_
                l = snprintf(buf, buf_size, "%s", line);
                if (l < 0) {
                        perror("Error writing to cache");
-                       rv = 0;
-                       goto err;
+                       return 0;
                }
                if (l >= buf_size) {
                        lxcfs_error("%s\n", "Internal error: truncated write to 
cache.");
-                       rv = 0;
-                       goto err;
+                       return 0;
                }
                buf += l;
                buf_size -= l;
                total_len += l;
        }
 
-       rv = total_len;
-
-err:
        if (stat_node)
                pthread_mutex_unlock(&stat_node->lock);
-       if (line)
-               free(line);
-       if (diff)
-               free(diff);
-       return rv;
+       return total_len;
 }
 
 #define CPUALL_MAX_SIZE (BUF_RESERVE_SIZE / 2)
 static int proc_stat_read(char *buf, size_t size, off_t offset,
-               struct fuse_file_info *fi)
+                         struct fuse_file_info *fi)
 {
+       __do_free char *cg = NULL, *cpuset = NULL, *line = NULL;
+       __do_free struct cpuacct_usage *cg_cpu_usage = NULL;
+       __do_fclose FILE *f = NULL;
        struct fuse_context *fc = fuse_get_context();
        struct file_info *d = (struct file_info *)fi->fh;
-       char *cg;
-       char *cpuset = NULL;
-       char *line = NULL;
-       size_t linelen = 0, total_len = 0, rv = 0;
+       size_t linelen = 0, total_len = 0;
        int curcpu = -1; /* cpu numbering starts at 0 */
        int physcpu = 0;
-       unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq 
= 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
-       unsigned long user_sum = 0, nice_sum = 0, system_sum = 0, idle_sum = 0, 
iowait_sum = 0,
-                                       irq_sum = 0, softirq_sum = 0, steal_sum 
= 0, guest_sum = 0, guest_nice_sum = 0;
+       unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0,
+                     irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 
0;
+       unsigned long user_sum = 0, nice_sum = 0, system_sum = 0, idle_sum = 0,
+                     iowait_sum = 0, irq_sum = 0, softirq_sum = 0,
+                     steal_sum = 0, guest_sum = 0, guest_nice_sum = 0;
        char cpuall[CPUALL_MAX_SIZE];
        /* reserve for cpu all */
        char *cache = d->buf + CPUALL_MAX_SIZE;
        size_t cache_size = d->buflen - CPUALL_MAX_SIZE;
-       FILE *f = NULL;
-       struct cpuacct_usage *cg_cpu_usage = NULL;
        int cg_cpu_usage_size = 0;
 
        if (offset){
@@ -4824,7 +4765,7 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
 
        cpuset = get_cpuset(cg);
        if (!cpuset)
-               goto err;
+               return 0;
 
        /*
         * Read cpuacct.usage_all for all CPUs.
@@ -4838,12 +4779,12 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
 
        f = fopen("/proc/stat", "r");
        if (!f)
-               goto err;
+               return 0;
 
        //skip first line
        if (getline(&line, &linelen, f) < 0) {
                lxcfs_error("%s\n", "proc_stat_read read first line failed.");
-               goto err;
+               return 0;
        }
 
        if (cgroup_ops->can_use_cpuview(cgroup_ops) && cg_cpu_usage) {
@@ -4866,13 +4807,11 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
                        l = snprintf(cache, cache_size, "%s", line);
                        if (l < 0) {
                                perror("Error writing to cache");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
                        if (l >= cache_size) {
                                lxcfs_error("%s\n", "Internal error: truncated 
write to cache.");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
                        cache += l;
                        cache_size -= l;
@@ -4905,14 +4844,12 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
                        l = snprintf(cache, cache_size, "cpu%d%s", curcpu, c);
                        if (l < 0) {
                                perror("Error writing to cache");
-                               rv = 0;
-                               goto err;
+                               return 0;
 
                        }
                        if (l >= cache_size) {
                                lxcfs_error("%s\n", "Internal error: truncated 
write to cache.");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
 
                        cache += l;
@@ -4946,14 +4883,12 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
 
                        if (l < 0) {
                                perror("Error writing to cache");
-                               rv = 0;
-                               goto err;
+                               return 0;
 
                        }
                        if (l >= cache_size) {
                                lxcfs_error("%s\n", "Internal error: truncated 
write to cache.");
-                               rv = 0;
-                               goto err;
+                               return 0;
                        }
 
                        cache += l;
@@ -5010,17 +4945,7 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
                total_len = size;
 
        memcpy(buf, d->buf, total_len);
-       rv = total_len;
-
-err:
-       if (f)
-               fclose(f);
-       if (cg_cpu_usage)
-               free(cg_cpu_usage);
-       free(line);
-       free(cpuset);
-       free(cg);
-       return rv;
+       return total_len;
 }
 
 /* This function retrieves the busy time of a group of tasks by looking at
@@ -5032,27 +4957,24 @@ static int proc_stat_read(char *buf, size_t size, off_t 
offset,
  */
 static double get_reaper_busy(pid_t task)
 {
-       pid_t initpid = lookup_initpid_in_store(task);
-       char *cgroup = NULL, *usage_str = NULL;
+       __do_free char *cgroup = NULL, *usage_str = NULL;
        unsigned long usage = 0;
-       double res = 0;
+       pid_t initpid;
 
+       initpid = lookup_initpid_in_store(task);
        if (initpid <= 0)
                return 0;
 
        cgroup = get_pid_cgroup(initpid, "cpuacct");
        if (!cgroup)
-               goto out;
+               return 0;
        prune_init_slice(cgroup);
-       if (!cgroup_ops->get(cgroup_ops, "cpuacct", cgroup, "cpuacct.usage", 
&usage_str))
-               goto out;
-       usage = strtoul(usage_str, NULL, 10);
-       res = (double)usage / 1000000000;
+       if (!cgroup_ops->get(cgroup_ops, "cpuacct", cgroup, "cpuacct.usage",
+                            &usage_str))
+               return 0;
 
-out:
-       free(cgroup);
-       free(usage_str);
-       return res;
+       usage = strtoul(usage_str, NULL, 10);
+       return ((double)usage / 1000000000);
 }
 
 #if RELOADTEST
@@ -5370,81 +5292,79 @@ static int proc_swaps_read(char *buf, size_t size, 
off_t offset,
  */
 static int calc_pid(char ***pid_buf, char *dpath, int depth, int sum, int cfd)
 {
-       DIR *dir;
-       int fd;
+       __do_free char *path = NULL;
+       __do_close_prot_errno int fd = -EBADF;
+       __do_fclose FILE *f = NULL;
+       __do_closedir DIR *dir = NULL;
        struct dirent *file;
-       FILE *f = NULL;
        size_t linelen = 0;
        char *line = NULL;
        int pd;
-       char *path_dir, *path;
        char **pid;
 
        /* path = dpath + "/cgroup.procs" + /0 */
-       do {
-               path = malloc(strlen(dpath) + 20);
-       } while (!path);
+       path = malloc(strlen(dpath) + 20);
+       if (!path)
+               return sum;
 
        strcpy(path, dpath);
-       fd = openat(cfd, path, O_RDONLY);
+       fd = openat(cfd, path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
        if (fd < 0)
-               goto out;
+               return sum;
 
-       dir = fdopendir(fd);
-       if (dir == NULL) {
-               close(fd);
-               goto out;
-       }
+       dir = fdopendir(move_fd(fd));
+       if (!dir)
+               return sum;
 
        while (((file = readdir(dir)) != NULL) && depth > 0) {
-               if (strncmp(file->d_name, ".", 1) == 0)
+               if (strcmp(file->d_name, ".") == 0)
                        continue;
-               if (strncmp(file->d_name, "..", 1) == 0)
+
+               if (strcmp(file->d_name, "..") == 0)
                        continue;
+
                if (file->d_type == DT_DIR) {
+                       __do_free char *path_dir = NULL;
+
                        /* path + '/' + d_name +/0 */
-                       do {
-                               path_dir = malloc(strlen(path) + 2 + 
sizeof(file->d_name));
-                       } while (!path_dir);
+                       path_dir = malloc(strlen(path) + 2 + 
sizeof(file->d_name));
+                       if (!path_dir)
+                               return sum;
+
                        strcpy(path_dir, path);
                        strcat(path_dir, "/");
                        strcat(path_dir, file->d_name);
                        pd = depth - 1;
                        sum = calc_pid(pid_buf, path_dir, pd, sum, cfd);
-                       free(path_dir);
                }
        }
-       closedir(dir);
 
        strcat(path, "/cgroup.procs");
        fd = openat(cfd, path, O_RDONLY);
        if (fd < 0)
-               goto out;
+               return sum;
 
-       f = fdopen(fd, "r");
-       if (!f) {
-               close(fd);
-               goto out;
-       }
+       f = fdopen(move_fd(fd), "r");
+       if (!f)
+               return sum;
 
        while (getline(&line, &linelen, f) != -1) {
-               do {
-                       pid = realloc(*pid_buf, sizeof(char *) * (sum + 1));
-               } while (!pid);
+               pid = realloc(*pid_buf, sizeof(char *) * (sum + 1));
+               if (!pid)
+                       return sum;
                *pid_buf = pid;
-               do {
-                       *(*pid_buf + sum) = malloc(strlen(line) + 1);
-               } while (*(*pid_buf + sum) == NULL);
+
+               *(*pid_buf + sum) = malloc(strlen(line) + 1);
+               if (!*(*pid_buf + sum))
+                       return sum;
+
                strcpy(*(*pid_buf + sum), line);
                sum++;
        }
-       fclose(f);
-out:
-       if (line)
-               free(line);
-       free(path);
+
        return sum;
 }
+
 /*
  * calc_load calculates the load according to the following formula:
  * load1 = load0 * exp + active * (1 - exp)
@@ -5474,25 +5394,26 @@ calc_load(unsigned long load, unsigned long exp, 
unsigned long active)
  */
 static int refresh_load(struct load_node *p, char *path)
 {
-       FILE *f = NULL;
+       __do_free char *line = NULL;
        char **idbuf;
        char proc_path[256];
        int i, ret, run_pid = 0, total_pid = 0, last_pid = 0;
-       char *line = NULL;
        size_t linelen = 0;
        int sum, length;
-       DIR *dp;
        struct dirent *file;
 
-       do {
-               idbuf = malloc(sizeof(char *));
-       } while (!idbuf);
+       idbuf = malloc(sizeof(char *));
+       if (!idbuf)
+               return -1;
+
        sum = calc_pid(&idbuf, path, DEPTH_DIR, 0, p->cfd);
        /*  normal exit  */
        if (sum == 0)
                goto out;
 
        for (i = 0; i < sum; i++) {
+               __do_closedir DIR *dp = NULL;
+
                /*clean up '\n' */
                length = strlen(idbuf[i])-1;
                idbuf[i][length] = '\0';
@@ -5510,6 +5431,8 @@ static int refresh_load(struct load_node *p, char *path)
                        continue;
                }
                while ((file = readdir(dp)) != NULL) {
+                       __do_fclose FILE *f = NULL;
+
                        if (strncmp(file->d_name, ".", 1) == 0)
                                continue;
                        if (strncmp(file->d_name, "..", 1) == 0)
@@ -5524,9 +5447,9 @@ static int refresh_load(struct load_node *p, char *path)
                                lxcfs_error("%s\n", "snprintf() failed in 
refresh_load.");
                                i = sum;
                                sum = -1;
-                               closedir(dp);
                                goto err_out;
                        }
+
                        f = fopen(proc_path, "r");
                        if (f != NULL) {
                                while (getline(&line, &linelen, f) != -1) {
@@ -5534,12 +5457,11 @@ static int refresh_load(struct load_node *p, char *path)
                                        if ((line[0] == 'S') && (line[1] == 
't'))
                                                break;
                                }
+
                        if ((line[7] == 'R') || (line[7] == 'D'))
                                run_pid++;
-                       fclose(f);
                        }
                }
-               closedir(dp);
        }
        /*Calculate the loadavg.*/
        p->avenrun[0] = calc_load(p->avenrun[0], EXP_1, run_pid);
@@ -5549,7 +5471,6 @@ static int refresh_load(struct load_node *p, char *path)
        p->total_pid = total_pid;
        p->last_pid = last_pid;
 
-       free(line);
 err_out:
        for (; i > 0; i--)
                free(idbuf[i-1]);
@@ -5557,13 +5478,13 @@ static int refresh_load(struct load_node *p, char *path)
        free(idbuf);
        return sum;
 }
+
 /*
  * Traverse the hash table and update it.
  */
 void *load_begin(void *arg)
 {
 
-       char *path = NULL;
        int i, sum, length, ret;
        struct load_node *f;
        int first_node;
@@ -5583,11 +5504,13 @@ void *load_begin(void *arg)
                        f = load_hash[i].next;
                        first_node = 1;
                        while (f) {
+                               __do_free char *path = NULL;
+
                                length = strlen(f->cg) + 2;
-                               do {
                                        /* strlen(f->cg) + '.' or '' + \0 */
-                                       path = malloc(length);
-                               } while (!path);
+                               path = malloc(length);
+                               if  (!path)
+                                       goto out;
 
                                ret = snprintf(path, length, "%s%s", 
dot_or_empty(f->cg), f->cg);
                                if (ret < 0 || ret > length - 1) {
@@ -5595,13 +5518,12 @@ void *load_begin(void *arg)
                                        lxcfs_error("Refresh node %s failed for 
snprintf().\n", f->cg);
                                        goto out;
                                }
+
                                sum = refresh_load(f, path);
-                               if (sum == 0) {
+                               if (sum == 0)
                                        f = del_node(f, i);
-                               } else {
+                               else
 out:                                   f = f->next;
-                               }
-                               free(path);
                                /* load_hash[i].lock locks only on the first 
node.*/
                                if (first_node == 1) {
                                        first_node = 0;
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to