[lxc-devel] [lxc/master] Don't busy loop on freeze with cgroupv2

Blub on Github lxc-bot at linuxcontainers.org
Fri May 15 13:17:53 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200515/d5b31366/attachment.bin>
-------------- next part --------------
From 9d1c51d19e4db3ea0ae2f7b1dfc9024e3e6b6d4d Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 15 May 2020 15:06:38 +0200
Subject: [PATCH 1/3] mainloop: add lxc_mainloop_add_handler_events

in order to be able to listen for EPOLLPRI

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/mainloop.c | 15 ++++++++++++---
 src/lxc/mainloop.h |  4 ++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c
index 6d4c5935ae..d5ae2a67a0 100644
--- a/src/lxc/mainloop.c
+++ b/src/lxc/mainloop.c
@@ -59,8 +59,10 @@ int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
 	}
 }
 
-int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
-			     lxc_mainloop_callback_t callback, void *data)
+int lxc_mainloop_add_handler_events(struct lxc_epoll_descr *descr, int fd,
+				    int events,
+				    lxc_mainloop_callback_t callback,
+				    void *data)
 {
 	__do_free struct mainloop_handler *handler = NULL;
 	__do_free struct lxc_list *item = NULL;
@@ -77,7 +79,7 @@ int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
 	handler->fd = fd;
 	handler->data = data;
 
-	ev.events = EPOLLIN;
+	ev.events = events;
 	ev.data.ptr = handler;
 
 	if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
@@ -92,6 +94,13 @@ int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
 	return 0;
 }
 
+int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
+			     lxc_mainloop_callback_t callback, void *data)
+{
+	return lxc_mainloop_add_handler_events(descr, fd, EPOLLIN, callback,
+					       data);
+}
+
 int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd)
 {
 	struct mainloop_handler *handler;
diff --git a/src/lxc/mainloop.h b/src/lxc/mainloop.h
index 8afac60d35..e6ab9a6d9e 100644
--- a/src/lxc/mainloop.h
+++ b/src/lxc/mainloop.h
@@ -22,6 +22,10 @@ typedef int (*lxc_mainloop_callback_t)(int fd, uint32_t event, void *data,
 
 extern int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms);
 
+extern int lxc_mainloop_add_handler_events(struct lxc_epoll_descr *descr,
+					   int fd, int events,
+					   lxc_mainloop_callback_t callback,
+					   void *data);
 extern int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
 				    lxc_mainloop_callback_t callback,
 				    void *data);

From 443be56560ee9b3c80d35d995520825e3c4c5672 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 15 May 2020 15:07:07 +0200
Subject: [PATCH 2/3] cgfsng: deduplicate freeze code

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/cgroups/cgfsng.c | 65 ++++++++++++----------------------------
 1 file changed, 19 insertions(+), 46 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 892fd915bb..7136d27a87 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2042,7 +2042,11 @@ static int freezer_cgroup_events_cb(int fd, uint32_t events, void *cbdata,
 	return LXC_MAINLOOP_CONTINUE;
 }
 
-static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
+static int cg_unified_freeze_do(struct cgroup_ops *ops, int timeout,
+				const char *state_string,
+				int state_num,
+				const char *epoll_error,
+				const char *wait_error)
 {
 	__do_close int fd = -EBADF;
 	call_cleaner(lxc_mainloop_close) struct lxc_epoll_descr *descr_ptr = NULL;
@@ -2067,26 +2071,33 @@ static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
 
 		ret = lxc_mainloop_open(&descr);
 		if (ret)
-			return log_error_errno(-1, errno, "Failed to create epoll instance to wait for container freeze");
+			return log_error_errno(-1, errno, "%s", epoll_error);
 
 		/* automatically cleaned up now */
 		descr_ptr = &descr;
 
-		ret = lxc_mainloop_add_handler(&descr, fd, freezer_cgroup_events_cb, INT_TO_PTR((int){1}));
+		ret = lxc_mainloop_add_handler(&descr, fd, freezer_cgroup_events_cb, INT_TO_PTR(state_num));
 		if (ret < 0)
 			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
 	}
 
-	ret = lxc_write_openat(h->container_full_path, "cgroup.freeze", "1", 1);
+	ret = lxc_write_openat(h->container_full_path, "cgroup.freeze", state_string, 1);
 	if (ret < 0)
 		return log_error_errno(-1, errno, "Failed to open cgroup.freeze file");
 
 	if (timeout != 0 && lxc_mainloop(&descr, timeout))
-		return log_error_errno(-1, errno, "Failed to wait for container to be frozen");
+		return log_error_errno(-1, errno, "%s", wait_error);
 
 	return 0;
 }
 
+static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
+{
+	return cg_unified_freeze_do(ops, timeout, "1", 1,
+		"Failed to create epoll instance to wait for container freeze",
+		"Failed to wait for container to be frozen");
+}
+
 __cgfsng_ops static int cgfsng_freeze(struct cgroup_ops *ops, int timeout)
 {
 	if (!ops->hierarchies)
@@ -2112,47 +2123,9 @@ static int cg_legacy_unfreeze(struct cgroup_ops *ops)
 
 static int cg_unified_unfreeze(struct cgroup_ops *ops, int timeout)
 {
-	__do_close int fd = -EBADF;
-	call_cleaner(lxc_mainloop_close)struct lxc_epoll_descr *descr_ptr = NULL;
-	int ret;
-	struct lxc_epoll_descr descr;
-	struct hierarchy *h;
-
-	h = ops->unified;
-	if (!h)
-		return ret_set_errno(-1, ENOENT);
-
-	if (!h->container_full_path)
-		return ret_set_errno(-1, EEXIST);
-
-	if (timeout != 0) {
-		__do_free char *events_file = NULL;
-
-		events_file = must_make_path(h->container_full_path, "cgroup.events", NULL);
-		fd = open(events_file, O_RDONLY | O_CLOEXEC);
-		if (fd < 0)
-			return log_error_errno(-1, errno, "Failed to open cgroup.events file");
-
-		ret = lxc_mainloop_open(&descr);
-		if (ret)
-			return log_error_errno(-1, errno, "Failed to create epoll instance to wait for container unfreeze");
-
-		/* automatically cleaned up now */
-		descr_ptr = &descr;
-
-		ret = lxc_mainloop_add_handler(&descr, fd, freezer_cgroup_events_cb, INT_TO_PTR((int){0}));
-		if (ret < 0)
-			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
-	}
-
-	ret = lxc_write_openat(h->container_full_path, "cgroup.freeze", "0", 1);
-	if (ret < 0)
-		return log_error_errno(-1, errno, "Failed to open cgroup.freeze file");
-
-	if (timeout != 0 && lxc_mainloop(&descr, timeout))
-		return log_error_errno(-1, errno, "Failed to wait for container to be unfrozen");
-
-	return 0;
+	return cg_unified_freeze_do(ops, timeout, "0", 0,
+		"Failed to create epoll instance to wait for container unfreeze",
+		"Failed to wait for container to be unfrozen");
 }
 
 __cgfsng_ops static int cgfsng_unfreeze(struct cgroup_ops *ops, int timeout)

From 385e58e8a8664d43175f64b8d44900ff651cec0f Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 15 May 2020 15:07:35 +0200
Subject: [PATCH 3/3] cgfsng: use EPOLLPRI when polling cgroup.events

EPOLLIN will always be true and therefore end up
busy-looping

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/cgroups/cgfsng.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 7136d27a87..f7af7c0a50 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -27,6 +27,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/epoll.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -2076,7 +2077,7 @@ static int cg_unified_freeze_do(struct cgroup_ops *ops, int timeout,
 		/* automatically cleaned up now */
 		descr_ptr = &descr;
 
-		ret = lxc_mainloop_add_handler(&descr, fd, freezer_cgroup_events_cb, INT_TO_PTR(state_num));
+		ret = lxc_mainloop_add_handler_events(&descr, fd, EPOLLPRI, freezer_cgroup_events_cb, INT_TO_PTR(state_num));
 		if (ret < 0)
 			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
 	}


More information about the lxc-devel mailing list