[lxc-devel] [lxcfs/master] bindings: port cpuset to new cgroup getters and implement cgroup2 sup…
brauner on Github
lxc-bot at linuxcontainers.org
Mon Feb 24 09:36:51 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 376 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200224/f168d2d1/attachment.bin>
-------------- next part --------------
From 560712b0c8d976e05f787e0a4166128edf6553ce Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at 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.brauner at 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); \
More information about the lxc-devel
mailing list