mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
vircgroup: introduce virCgroupV2DevicesDetectProg
This function will be called if libvirtd was restarted while some domains were running. It will try to detect existing programs attached to the guest cgroup. Signed-off-by: Pavel Hrdina <phrdina@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
48423a0b5d
commit
ce11a5c59f
@ -1719,6 +1719,7 @@ virCgroupV2Register;
|
||||
# util/vircgroupv2devices.h
|
||||
virCgroupV2DevicesAttachProg;
|
||||
virCgroupV2DevicesAvailable;
|
||||
virCgroupV2DevicesDetectProg;
|
||||
|
||||
# util/virclosecallbacks.h
|
||||
virCloseCallbacksGet;
|
||||
|
@ -322,6 +322,110 @@ virCgroupV2DevicesAttachProg(virCgroupPtr group,
|
||||
VIR_FORCE_CLOSE(mapfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virCgroupV2DevicesCountMapEntries(int mapfd)
|
||||
{
|
||||
int ret = 0;
|
||||
int rc;
|
||||
uint64_t key = 0;
|
||||
uint64_t prevKey = 0;
|
||||
|
||||
while ((rc = virBPFGetNextElem(mapfd, &prevKey, &key)) == 0) {
|
||||
ret++;
|
||||
prevKey = key;
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
# define MAX_PROG_IDS 10
|
||||
|
||||
int
|
||||
virCgroupV2DevicesDetectProg(virCgroupPtr group)
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
VIR_AUTOCLOSE cgroupfd = -1;
|
||||
unsigned int progcnt = 0;
|
||||
unsigned int progids[MAX_PROG_IDS] = { 0 };
|
||||
int progfd = -1;
|
||||
int mapfd = -1;
|
||||
int nitems = -1;
|
||||
struct bpf_prog_info progInfo = { 0 };
|
||||
struct bpf_map_info mapInfo = { 0 };
|
||||
g_autofree unsigned int *mapIDs = NULL;
|
||||
|
||||
if (group->unified.devices.progfd > 0 && group->unified.devices.mapfd > 0)
|
||||
return 0;
|
||||
|
||||
if (virCgroupPathOfController(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
||||
NULL, &path) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cgroupfd = open(path, O_RDONLY);
|
||||
if (cgroupfd < 0) {
|
||||
virReportSystemError(errno, _("unable to open '%s'"), path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virBPFQueryProg(cgroupfd, MAX_PROG_IDS, BPF_CGROUP_DEVICE,
|
||||
&progcnt, progids) < 0) {
|
||||
virReportSystemError(errno, "%s", _("unable to query cgroup BPF progs"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (progcnt == 0)
|
||||
return 0;
|
||||
|
||||
/* No need to have alternate code, this function will not be called
|
||||
* if compiled with old kernel. */
|
||||
progfd = virBPFGetProg(progids[0]);
|
||||
if (progfd < 0) {
|
||||
virReportSystemError(errno, "%s", _("failed to get cgroup BPF prog FD"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virBPFGetProgInfo(progfd, &progInfo, &mapIDs) < 0) {
|
||||
virReportSystemError(errno, "%s", _("failed to get cgroup BPF prog info"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (progInfo.nr_map_ids == 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("no map for cgroup BPF prog"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
mapfd = virBPFGetMap(mapIDs[0]);
|
||||
if (mapfd < 0) {
|
||||
virReportSystemError(errno, "%s", _("failed to get cgroup BPF map FD"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virBPFGetMapInfo(mapfd, &mapInfo) < 0) {
|
||||
virReportSystemError(errno, "%s", _("failed to get cgroup BPF map info"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
nitems = virCgroupV2DevicesCountMapEntries(mapfd);
|
||||
if (nitems < 0) {
|
||||
virReportSystemError(errno, "%s", _("failed to count cgroup BPF map items"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
group->unified.devices.progfd = progfd;
|
||||
group->unified.devices.mapfd = mapfd;
|
||||
group->unified.devices.max = mapInfo.max_entries;
|
||||
group->unified.devices.count = nitems;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !HAVE_DECL_BPF_CGROUP_DEVICE */
|
||||
bool
|
||||
virCgroupV2DevicesAvailable(virCgroupPtr group G_GNUC_UNUSED)
|
||||
@ -340,4 +444,14 @@ virCgroupV2DevicesAttachProg(virCgroupPtr group G_GNUC_UNUSED,
|
||||
"with this kernel"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virCgroupV2DevicesDetectProg(virCgroupPtr group G_GNUC_UNUSED)
|
||||
{
|
||||
virReportSystemError(ENOSYS, "%s",
|
||||
_("cgroups v2 BPF devices not supported "
|
||||
"with this kernel"));
|
||||
return -1;
|
||||
}
|
||||
#endif /* !HAVE_DECL_BPF_CGROUP_DEVICE */
|
||||
|
@ -27,3 +27,6 @@ int
|
||||
virCgroupV2DevicesAttachProg(virCgroupPtr group,
|
||||
int mapfd,
|
||||
size_t max);
|
||||
|
||||
int
|
||||
virCgroupV2DevicesDetectProg(virCgroupPtr group);
|
||||
|
Loading…
x
Reference in New Issue
Block a user