<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Jul 11, 2017 at 9:25 AM, Martin Kletzander <span dir="ltr"><<a href="mailto:mkletzan@redhat.com" target="_blank">mkletzan@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thu, Jul 06, 2017 at 05:03:31PM +0200, Juan Hernandez wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Currently the scan of the /proc/mounts file used to find cgroup mount<br>
points doesn't take into account that mount points may hidden by other<br>
mount points. For, example in certain Kubernetes environments the<br>
/proc/mounts contains the following lines:<br>
<br>
 cgroup /sys/fs/cgroup/net_prio,net_cl<wbr>s cgroup ...<br>
 tmpfs /sys/fs/cgroup tmpfs ...<br>
 cgroup /sys/fs/cgroup/net_cls,net_pri<wbr>o cgroup ...<br>
<br>
In this particular environment the first mount point is hidden by the<br>
second one. The correct mount point is the third one, but libvirt will<br>
never process it because it only checks the first mount point for each<br>
controller (net_cls in this case). So libvirt will try to use the first<br>
mount point, which doesn't actually exist, and the complete detection<br>
process will fail.<br>
<br>
To avoid that issue this patch changes the virCgroupDetectMountsFromFile<br>
function so that when there are duplicates it takes the information from<br>
the last line in /proc/mounts. This requires removing the previous<br>
explicit condition to skip duplicates, and adding code to free the<br>
memory used by the processing of duplicated lines.<br>
<br>
Related-To: <a href="https://bugzilla.redhat.com/1468214" rel="noreferrer" target="_blank">https://bugzilla.redhat.com/14<wbr>68214</a><br>
Related-To: <a href="https://github.com/kubevirt/libvirt/issues/4" rel="noreferrer" target="_blank">https://github.com/kubevirt/li<wbr>bvirt/issues/4</a><br>
Signed-off-by: Juan Hernandez <<a href="mailto:jhernand@redhat.com" target="_blank">jhernand@redhat.com</a>><br>
---<br>
src/util/vircgroup.c                | 23 ++++++++++++++---------<br>
tests/vircgroupdata/kubevirt.m<wbr>ounts | 36 ++++++++++++++++++++++++++++++<wbr>++++++<br>
tests/vircgroupdata/kubevirt.p<wbr>arsed | 10 ++++++++++<br>
tests/vircgrouptest.c               |  1 +<br>
4 files changed, 61 insertions(+), 9 deletions(-)<br>
create mode 100644 tests/vircgroupdata/kubevirt.m<wbr>ounts<br>
create mode 100644 tests/vircgroupdata/kubevirt.p<wbr>arsed<br>
<br>
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c<br>
index 5aa1db5..41d90e7 100644<br>
--- a/src/util/vircgroup.c<br>
+++ b/src/util/vircgroup.c<br>
@@ -397,6 +397,7 @@ virCgroupDetectMountsFromFile(<wbr>virCgroupPtr group,<br>
            const char *typestr = virCgroupControllerTypeToStrin<wbr>g(i);<br>
            int typelen = strlen(typestr);<br>
            char *tmp = entry.mnt_opts;<br>
+            struct virCgroupController *controller = &group->controllers[i];<br>
            while (tmp) {<br>
                char *next = strchr(tmp, ',');<br>
                int len;<br>
@@ -406,18 +407,21 @@ virCgroupDetectMountsFromFile(<wbr>virCgroupPtr group,<br>
                } else {<br>
                    len = strlen(tmp);<br>
                }<br>
-                /* NB, the same controller can appear >1 time in mount list<br>
-                 * due to bind mounts from one location to another. Pick the<br>
-                 * first entry only<br>
-                 */<br>
-                if (typelen == len && STREQLEN(typestr, tmp, len) &&<br>
-                    !group->controllers[i].mountPo<wbr>int) {<br>
+<br>
+                if (typelen == len && STREQLEN(typestr, tmp, len)) {<br>
                    char *linksrc;<br>
                    struct stat sb;<br>
                    char *tmp2;<br>
<br>
-                    if (VIR_STRDUP(group->controllers<wbr>[i].mountPoint,<br>
-                                   entry.mnt_dir) < 0)<br>
+                    /* Note that the lines in /proc/mounts have the same<br>
+                     * order than the mount operations, and that there may<br>
+                     * be duplicates due to bind mounts. This means<br>
+                     * that the same mount point may be processed more than<br>
+                     * once. We need to save the results of the last one,<br>
+                     * and we need to be careful to release the memory used<br>
+                     * by previous processing. */<br>
+                    VIR_FREE(controller->mountPoin<wbr>t);<br>
</blockquote>
<br></div></div>
You need to free the linkPoint here as well as it is no longer valid if<br>
we are throwing out the previous entry.<br>
<br>
There's also pre-existing leak with linksrc in this function.<div><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+                    if (VIR_STRDUP(controller->mountP<wbr>oint, entry.mnt_dir) < 0)<br>
                        goto error;<br>
<br>
                    tmp2 = strrchr(entry.mnt_dir, '/');<br>
@@ -453,7 +457,8 @@ virCgroupDetectMountsFromFile(<wbr>virCgroupPtr group,<br>
                                VIR_WARN("Expecting a symlink at %s for controller %s",<br>
                                         linksrc, typestr);<br>
                            } else {<br>
-                                group->controllers[i].linkPoin<wbr>t = linksrc;<br>
+                                VIR_FREE(controller->linkPoint<wbr>);<br>
+                                controller->linkPoint = linksrc;<br>
                            }<br>
                        }<br>
                    }<br>
diff --git a/tests/vircgroupdata/kubevirt<wbr>.mounts b/tests/vircgroupdata/kubevirt<wbr>.mounts<br>
new file mode 100644<br>
index 0000000..b0d31bb<br>
--- /dev/null<br>
+++ b/tests/vircgroupdata/kubevirt<wbr>.mounts<br>
@@ -0,0 +1,36 @@<br>
+tmpfs /sys/fs/cgroup tmpfs rw,nosuid,nodev,noexec,relatim<wbr>e,mode=755 0 0<br>
+cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,xattr,release_agent=/usr/<wbr>lib/systemd/systemd-cgroups-<wbr>agent,name=systemd 0 0<br>
+cgroup /sys/fs/cgroup/cpuacct,cpu cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuacct,cpu 0 0<br>
+cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,pids 0 0<br>
+cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,blkio 0 0<br>
+cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuset 0 0<br>
+cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,memory 0 0<br>
+cgroup /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,hugetlb 0 0<br>
+cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,devices 0 0<br>
+cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,freezer 0 0<br>
+cgroup /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,perf_event 0 0<br>
+cgroup /sys/fs/cgroup/net_prio,net_cl<wbr>s cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,net_prio,net_cls 0 0<br>
+tmpfs /host-sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,relatim<wbr>e,mode=755 0 0<br>
+cgroup /host-sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,xattr,release_agent=/usr/<wbr>lib/systemd/systemd-cgroups-<wbr>agent,name=systemd 0 0<br>
+cgroup /host-sys/fs/cgroup/cpu,cpuacc<wbr>t cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuacct,cpu 0 0<br>
+cgroup /host-sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,pids 0 0<br>
+cgroup /host-sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,blkio 0 0<br>
+cgroup /host-sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuset 0 0<br>
+cgroup /host-sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,memory 0 0<br>
+cgroup /host-sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,hugetlb 0 0<br>
+cgroup /host-sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,devices 0 0<br>
+cgroup /host-sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,freezer 0 0<br>
+cgroup /host-sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,perf_event 0 0<br>
+cgroup /host-sys/fs/cgroup/net_cls,ne<wbr>t_prio cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,net_prio,net_cls 0 0<br>
+tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,relatim<wbr>e,mode=755 0 0<br>
+cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,xattr,release_agent=/usr/<wbr>lib/systemd/systemd-cgroups-<wbr>agent,name=systemd 0 0<br>
+cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuacct,cpu 0 0<br>
+cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,pids 0 0<br>
+cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,blkio 0 0<br>
+cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuset 0 0<br>
+cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,memory 0 0<br>
+cgroup /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,hugetlb 0 0<br>
+cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,devices 0 0<br>
+cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,freezer 0 0<br>
+cgroup /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,perf_event 0 0<br>
+cgroup /sys/fs/cgroup/net_cls,net_pri<wbr>o cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,net_prio,net_cls 0 0<br>
</blockquote>
<br></div></div>
It's not clear what we're testing here, I would either add just two<br>
controllers mounted in three places (just keep the net_{cls,prio}) or<br>
copy some existing test and add two lines so that the diff later in the<br>
history shows exactly what is being tested if used with '-C', e.g.:<br>
<br>
diff --git a/tests/vircgroupdata/cgroups2<wbr>.mounts b/tests/vircgroupdata/cgroups4<wbr>.mounts<br>
similarity index 86%<br>
copy from tests/vircgroupdata/cgroups2.m<wbr>ounts<br>
copy to tests/vircgroupdata/cgroups4.m<wbr>ounts<br>
index 21ab867d71ed..2b06c2ea1e16 100644<br>
--- a/tests/vircgroupdata/cgroups2<wbr>.mounts<br>
+++ b/tests/vircgroupdata/cgroups4<wbr>.mounts<br>
@@ -10,8 +10,10 @@ shm /dev/shm tmpfs rw,nosuid,nodev,noexec,relatim<wbr>e 0 0<br>
debugfs /sys/kernel/debug debugfs rw,nosuid,nodev,noexec,relatim<wbr>e 0 0<br>
cgroup_root /sys/fs/cgroup tmpfs rw,nosuid,nodev,noexec,relatim<wbr>e,size=10240k,mode=755 0 0<br>
openrc /sys/fs/cgroup/openrc cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,release_agent=/lib64/rc/sh/<wbr>cgroup-release-agent.sh,name=<wbr>openrc 0 0<br>
+cpuset /some/random/location/cpuset cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuset 0 0<br>
cpuset /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuset 0 0<br>
cpu /sys/fs/cgroup/cpu cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpu 0 0<br>
+cpuacct /some/random/location cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuacct 0 0<br>
cpuacct /sys/fs/cgroup/cpuacct cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,cpuacct 0 0<br>
memory /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,memory 0 0<br>
devices /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,devices 0 0<br>
@@ -20,3 +22,4 @@ blkio /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,blkio 0 0<br>
perf_event /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,perf_event 0 0<br>
hugetlb /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,hugetlb 0 0<br>
binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,nosuid,nodev,noexec,relatim<wbr>e 0 0<br>
+freezer /some/random/location/freezer cgroup rw,nosuid,nodev,noexec,relatim<wbr>e,freezer 0 0<br>
diff --git a/tests/vircgroupdata/cgroups2<wbr>.parsed b/tests/vircgroupdata/cgroups4<wbr>.parsed<br>
similarity index 100%<br>
copy from tests/vircgroupdata/cgroups2.p<wbr>arsed<br>
copy to tests/vircgroupdata/cgroups4.p<wbr>arsed<br>
--<br>
<br>
You see how clear that is from the above diff?<br>
<br>
Other than that I think this works nicely, so ACK if you are OK with the<br>
proposed changes, I'll squash them in and push it.<br>
<br></blockquote><br></div><div class="gmail_quote">Your suggestions look good to me, so ACK, feel free to squash and push Martin.<br><br></div></div></div>