The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxcfs/pull/321
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) === …port Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 560712b0c8d976e05f787e0a4166128edf6553ce Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Mon, 24 Feb 2020 10:35:50 +0100 Subject: [PATCH] bindings: port cpuset to new cgroup getters and implement cgroup2 support Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- bindings.c | 9 +++-- cgroups/cgfsng.c | 75 +++++++++++++++++++++++++++++++++++++++++- cgroups/cgroup.h | 4 +++ cgroups/cgroup_utils.c | 53 +++++++++++++++++++++++++++++ cgroups/cgroup_utils.h | 7 ++++ memory_utils.h | 8 +++++ 6 files changed, 152 insertions(+), 4 deletions(-) diff --git a/bindings.c b/bindings.c index 52fbb87..35c1e42 100644 --- a/bindings.c +++ b/bindings.c @@ -3543,11 +3543,14 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, */ char *get_cpuset(const char *cg) { - char *answer; + char *value = NULL; + int ret; - if (!cgroup_ops->get(cgroup_ops, "cpuset", cg, "cpuset.cpus", &answer)) + ret = cgroup_ops->get_cpuset_cpus(cgroup_ops, cg, &value); + if (ret < 0) return NULL; - return answer; + + return value; } bool cpu_in_cpuset(int cpu, const char *cpuset); diff --git a/cgroups/cgfsng.c b/cgroups/cgfsng.c index 426ad8a..558f0f5 100644 --- a/cgroups/cgfsng.c +++ b/cgroups/cgfsng.c @@ -666,6 +666,77 @@ static int cgfsng_get_memory_stats(struct cgroup_ops *ops, const char *cgroup, return cgfsng_get_memory(ops, cgroup, "memory.stat", value); } +static char *readat_cpuset(int cgroup_fd) +{ + __do_free char *val = NULL; + + val = readat_file(cgroup_fd, "cpuset.cpus"); + if (val && strcmp(val, "") != 0) + return move_ptr(val); + + free_disarm(val); + val = readat_file(cgroup_fd, "cpuset.cpus.effective"); + if (val && strcmp(val, "") != 0) + return move_ptr(val); + + return NULL; +} + +static int cgfsng_get_cpuset_cpus(struct cgroup_ops *ops, const char *cgroup, + char **value) +{ + __do_close_prot_errno int cgroup_fd = -EBADF; + __do_free char *path = NULL; + char *v; + struct hierarchy *h; + int ret; + + h = ops->get_hierarchy(ops, "cpuset"); + if (!h) + return -1; + + if (!is_unified_hierarchy(h)) + ret = CGROUP_SUPER_MAGIC; + else + ret = CGROUP2_SUPER_MAGIC; + + *value = NULL; + path = must_make_path(*cgroup == '/' ? "." : "", cgroup, NULL); + cgroup_fd = openat_safe(h->fd, path); + if (cgroup_fd < 0) { + return -1; + } + v = readat_cpuset(cgroup_fd); + if (v) { + *value = v; + return ret; + } + + /* + * cpuset.cpus and cpuset.cpus.effective are empty so we need to look + * the nearest ancestor with a non-empty cpuset.cpus{.effective} file. + */ + for (;;) { + int fd; + + fd = openat_safe(cgroup_fd, "../"); + if (fd < 0 || !is_cgroup_fd(fd)) { + fprintf(stderr, "2222: %s\n", strerror(errno)); + return -1; + } + + close_prot_errno_replace(cgroup_fd, fd); + + v = readat_cpuset(fd); + if (v) { + *value = v; + return ret; + } + } + + return -1; +} + /* At startup, parse_hierarchies finds all the info we need about cgroup * mountpoints and current cgroups, and stores it in @d. */ @@ -862,7 +933,6 @@ struct cgroup_ops *cgfsng_ops_init(void) cgfsng_ops->mount = cgfsng_mount; cgfsng_ops->nrtasks = cgfsng_nrtasks; - /* memory */ cgfsng_ops->get_memory_stats = cgfsng_get_memory_stats; cgfsng_ops->get_memory_max = cgfsng_get_memory_max; @@ -870,5 +940,8 @@ struct cgroup_ops *cgfsng_ops_init(void) cgfsng_ops->get_memory_current = cgfsng_get_memory_current; cgfsng_ops->get_memory_swap_current = cgfsng_get_memory_swap_current; + /* cpuset */ + cgfsng_ops->get_cpuset_cpus = cgfsng_get_cpuset_cpus; + return move_ptr(cgfsng_ops); } diff --git a/cgroups/cgroup.h b/cgroups/cgroup.h index e367aff..29fe5ba 100644 --- a/cgroups/cgroup.h +++ b/cgroups/cgroup.h @@ -134,6 +134,10 @@ struct cgroup_ops { char **value); int (*get_memory_swap_max)(struct cgroup_ops *ops, const char *cgroup, char **value); + + /* cpuset */ + int (*get_cpuset_cpus)(struct cgroup_ops *ops, const char *cgroup, + char **value); }; extern struct cgroup_ops *cgroup_init(void); diff --git a/cgroups/cgroup_utils.c b/cgroups/cgroup_utils.c index e5b2707..957d2e1 100644 --- a/cgroups/cgroup_utils.c +++ b/cgroups/cgroup_utils.c @@ -62,6 +62,23 @@ int unified_cgroup_hierarchy(void) return 0; } +bool is_cgroup_fd(int fd) +{ + + int ret; + struct statfs fs; + + ret = fstatfs(fd, &fs); + if (ret) + return false; + + if (is_fs_type(&fs, CGROUP2_SUPER_MAGIC) || + is_fs_type(&fs, CGROUP_SUPER_MAGIC)) + return true; + + return false; +} + void *must_realloc(void *orig, size_t sz) { void *ret; @@ -724,3 +741,39 @@ bool mkdir_p(const char *dir, mode_t mode) return true; } + +char *must_append_path(char *first, ...) +{ + char *cur; + size_t full_len; + va_list args; + char *dest = first; + size_t buf_len; + size_t cur_len; + + full_len = strlen(first); + cur_len = full_len; + + va_start(args, first); + while ((cur = va_arg(args, char *)) != NULL) { + buf_len = strlen(cur); + + full_len += buf_len; + if (cur[0] != '/') + full_len++; + + dest = must_realloc(dest, full_len + 1); + + if (cur[0] != '/') { + memcpy(dest + cur_len, "/", 1); + cur_len++; + } + + memcpy(dest + cur_len, cur, buf_len); + cur_len += buf_len; + } + va_end(args); + + dest[cur_len] = '\0'; + return dest; +} diff --git a/cgroups/cgroup_utils.h b/cgroups/cgroup_utils.h index 1db8a57..2a4cc17 100644 --- a/cgroups/cgroup_utils.h +++ b/cgroups/cgroup_utils.h @@ -69,5 +69,12 @@ extern char *cg_hybrid_get_current_cgroup(char *basecginfo, const char *controller, int type); extern char *cg_legacy_get_current_cgroup(pid_t pid, const char *controller); extern bool mkdir_p(const char *dir, mode_t mode); +extern char *must_append_path(char *first, ...); +extern bool is_cgroup_fd(int fd); + +static inline int openat_safe(int fd, const char *path) +{ + return openat(fd, path, O_DIRECTORY | O_RDONLY | O_CLOEXEC | O_NOFOLLOW); +} #endif /* __LXC_CGROUP_UTILS_H */ diff --git a/memory_utils.h b/memory_utils.h index ac00b10..a97c243 100644 --- a/memory_utils.h +++ b/memory_utils.h @@ -37,6 +37,14 @@ static inline void __auto_closedir__(DIR **d) fd = -EBADF; \ } +#define close_prot_errno_replace(fd, new_fd) \ + if (fd >= 0) { \ + int _e_ = errno; \ + close(fd); \ + errno = _e_; \ + fd = new_fd; \ + } + #define free_disarm(ptr) \ ({ \ free(ptr); \
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel