From 30b6ddc44cd46b9671af584f57c0e36f61145464 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Mon, 9 Sep 2019 09:40:06 +0200 Subject: [PATCH] vircgroup: introduce virCgroupV2DevicesAvailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no exact way how to figure out whether BPF devices support is compiled into kernel. One way is to check kernel configure options but this is not reliable as it may not be available. Let's try to do syscall to which will list BPF cgroup device programs. Signed-off-by: Pavel Hrdina Reviewed-by: Ján Tomko --- configure.ac | 3 +- src/libvirt_private.syms | 3 ++ src/util/Makefile.inc.am | 2 + src/util/vircgroupv2.c | 8 +++- src/util/vircgroupv2devices.c | 69 +++++++++++++++++++++++++++++++++++ src/util/vircgroupv2devices.h | 24 ++++++++++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 src/util/vircgroupv2devices.c create mode 100644 src/util/vircgroupv2devices.h diff --git a/configure.ac b/configure.ac index be450e25b6..ef521e370c 100644 --- a/configure.ac +++ b/configure.ac @@ -883,7 +883,8 @@ AC_CHECK_DECLS([clock_serv_t, host_get_clock_service, clock_get_time], # Check if we have new enough kernel to support BPF devices for cgroups v2 if test "$with_linux" = "yes"; then - AC_CHECK_DECLS([BPF_PROG_QUERY], [], [], [#include ]) + AC_CHECK_DECLS([BPF_PROG_QUERY, BPF_CGROUP_DEVICE], + [], [], [#include ]) fi # Check if we need to look for ifconfig diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c3414b5002..c933277918 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1716,6 +1716,9 @@ virCgroupV1Register; # util/vircgroupv2.h virCgroupV2Register; +# util/vircgroupv2devices.h +virCgroupV2DevicesAvailable; + # util/virclosecallbacks.h virCloseCallbacksGet; virCloseCallbacksGetConn; diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am index 23c186f8b9..0855f152fd 100644 --- a/src/util/Makefile.inc.am +++ b/src/util/Makefile.inc.am @@ -35,6 +35,8 @@ UTIL_SOURCES = \ util/vircgroupv1.h \ util/vircgroupv2.c \ util/vircgroupv2.h \ + util/vircgroupv2devices.c \ + util/vircgroupv2devices.h \ util/virclosecallbacks.c \ util/virclosecallbacks.h \ util/vircommand.c \ diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c index ca053e84b4..cb5d9946a0 100644 --- a/src/util/vircgroupv2.c +++ b/src/util/vircgroupv2.c @@ -33,6 +33,7 @@ #include "vircgroup.h" #include "vircgroupbackend.h" #include "vircgroupv2.h" +#include "vircgroupv2devices.h" #include "virerror.h" #include "virfile.h" #include "virlog.h" @@ -301,6 +302,9 @@ virCgroupV2DetectControllers(virCgroupPtr group, * exists with usage stats. */ group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT; + if (virCgroupV2DevicesAvailable(group)) + group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_DEVICES; + if (controllers >= 0) group->unified.controllers &= controllers; @@ -445,8 +449,10 @@ virCgroupV2MakeGroup(virCgroupPtr parent, continue; /* Controllers that are implicitly enabled if available. */ - if (i == VIR_CGROUP_CONTROLLER_CPUACCT) + if (i == VIR_CGROUP_CONTROLLER_CPUACCT || + i == VIR_CGROUP_CONTROLLER_DEVICES) { continue; + } rc = virCgroupV2EnableController(group, parent, i, false); if (rc < 0) { diff --git a/src/util/vircgroupv2devices.c b/src/util/vircgroupv2devices.c new file mode 100644 index 0000000000..8641645810 --- /dev/null +++ b/src/util/vircgroupv2devices.c @@ -0,0 +1,69 @@ +/* + * vircgroupv2devices.c: methods for cgroups v2 BPF devices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ +#include + +#if HAVE_DECL_BPF_CGROUP_DEVICE +# include +# include +# include +# include +# include +#endif /* !HAVE_DECL_BPF_CGROUP_DEVICE */ + +#include "internal.h" + +#define LIBVIRT_VIRCGROUPPRIV_H_ALLOW +#include "vircgrouppriv.h" + +#include "virbpf.h" +#include "vircgroup.h" +#include "vircgroupv2devices.h" +#include "virfile.h" +#include "virlog.h" + +VIR_LOG_INIT("util.cgroup"); + +#define VIR_FROM_THIS VIR_FROM_CGROUP + +#if HAVE_DECL_BPF_CGROUP_DEVICE +bool +virCgroupV2DevicesAvailable(virCgroupPtr group) +{ + VIR_AUTOCLOSE cgroupfd = -1; + unsigned int progCnt = 0; + + cgroupfd = open(group->unified.mountPoint, O_RDONLY); + if (cgroupfd < 0) { + VIR_DEBUG("failed to open cgroup '%s'", group->unified.mountPoint); + return false; + } + + if (virBPFQueryProg(cgroupfd, 0, BPF_CGROUP_DEVICE, &progCnt, NULL) < 0) { + VIR_DEBUG("failed to query cgroup progs"); + return false; + } + + return true; +} +#else /* !HAVE_DECL_BPF_CGROUP_DEVICE */ +bool +virCgroupV2DevicesAvailable(virCgroupPtr group G_GNUC_UNUSED) +{ + return false; +} +#endif /* !HAVE_DECL_BPF_CGROUP_DEVICE */ diff --git a/src/util/vircgroupv2devices.h b/src/util/vircgroupv2devices.h new file mode 100644 index 0000000000..2448a8890f --- /dev/null +++ b/src/util/vircgroupv2devices.h @@ -0,0 +1,24 @@ +/* + * vircgroupv2devices.h: methods for cgroups v2 BPF devices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#pragma once + +#include "vircgroup.h" + +bool +virCgroupV2DevicesAvailable(virCgroupPtr group);