systemd/0061-virt-move-caching-of-v...

299 lines
8.4 KiB
Diff

From 48a66a7f6a23ee71bcf54da5bd0bbd69a0710582 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 31 Oct 2013 16:23:06 +0100
Subject: [PATCH] virt: move caching of virtualization check results into
detect_vm() and detect_container()
After all, we ended up calling detect_container() more often than
detect_virtualization(), hence the former one should cache the results,
since the latter is only a wrapper around the former.
---
src/detect-virt/detect-virt.c | 2 +-
src/shared/virt.c | 180 ++++++++++++++++++++----------------------
2 files changed, 87 insertions(+), 95 deletions(-)
diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c
index bd3ee45..72ff2a8 100644
--- a/src/detect-virt/detect-virt.c
+++ b/src/detect-virt/detect-virt.c
@@ -114,8 +114,8 @@ static int parse_argv(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
const char *id = NULL;
- int r;
int retval = EXIT_SUCCESS;
+ int r;
/* This is mostly intended to be used for scripts which want
* to detect whether we are being run in a virtualized
diff --git a/src/shared/virt.c b/src/shared/virt.c
index 4f8134a..537ccda 100644
--- a/src/shared/virt.c
+++ b/src/shared/virt.c
@@ -60,6 +60,9 @@ int detect_vm(const char **id) {
/* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
"Microsoft Hv\0" "microsoft\0";
+ static __thread int cached_found = -1;
+ static __thread const char *cached_id = NULL;
+
uint32_t eax, ecx;
union {
uint32_t sig32[3];
@@ -69,6 +72,15 @@ int detect_vm(const char **id) {
const char *j, *k;
bool hypervisor;
_cleanup_free_ char *hvtype = NULL;
+ const char *_id = NULL;
+
+ if (_likely_(cached_found >= 0)) {
+
+ if (id)
+ *id = cached_id;
+
+ return cached_found;
+ }
/* Try high-level hypervisor sysfs file first:
*
@@ -76,10 +88,9 @@ int detect_vm(const char **id) {
r = read_one_line_file("/sys/hypervisor/type", &hvtype);
if (r >= 0) {
if (streq(hvtype, "xen")) {
- if (id)
- *id = "xen";
-
- return 1;
+ _id = "xen";
+ r = 1;
+ goto finish;
}
} else if (r != -ENOENT)
return r;
@@ -125,17 +136,14 @@ int detect_vm(const char **id) {
NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
if (streq(sig.text, j)) {
-
- if (id)
- *id = k;
-
- return 1;
+ _id = k;
+ r = 1;
+ goto finish;
}
}
for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
_cleanup_free_ char *s = NULL;
- const char *found = NULL;
r = read_one_line_file(dmi_vendors[i], &s);
if (r < 0) {
@@ -146,22 +154,17 @@ int detect_vm(const char **id) {
}
NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
- if (startswith(s, j))
- found = k;
-
- if (found) {
- if (id)
- *id = found;
-
- return 1;
- }
+ if (startswith(s, j)) {
+ _id = k;
+ r = 1;
+ goto finish;
+ }
}
if (hypervisor || hvtype) {
- if (id)
- *id = "other";
-
- return 1;
+ _id = "other";
+ r = 1;
+ goto finish;
}
#endif
@@ -171,17 +174,40 @@ int detect_vm(const char **id) {
if (r < 0)
return r;
if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
- *id = "uml";
- return 1;
+ _id = "uml";
+ r = 1;
+ goto finish;
}
- return 0;
+ r = 0;
+
+finish:
+ cached_found = r;
+
+ cached_id = _id;
+ if (id)
+ *id = _id;
+
+ return r;
}
int detect_container(const char **id) {
+
+ static __thread int cached_found = -1;
+ static __thread const char *cached_id = NULL;
+
_cleanup_free_ char *e = NULL;
+ const char *_id = NULL;
int r;
+ if (_likely_(cached_found >= 0)) {
+
+ if (id)
+ *id = cached_id;
+
+ return cached_found;
+ }
+
/* Unfortunately many of these operations require root access
* in one way or another */
@@ -189,95 +215,61 @@ int detect_container(const char **id) {
if (r < 0)
return r;
if (r > 0) {
-
- if (id)
- *id = "chroot";
-
- return 1;
+ _id = "chroot";
+ goto finish;
}
/* /proc/vz exists in container and outside of the container,
* /proc/bc only outside of the container. */
if (access("/proc/vz", F_OK) >= 0 &&
access("/proc/bc", F_OK) < 0) {
-
- if (id)
- *id = "openvz";
-
- return 1;
+ _id = "openvz";
+ r = 1;
+ goto finish;
}
r = getenv_for_pid(1, "container", &e);
- if (r <= 0)
+ if (r < 0)
return r;
+ if (r == 0)
+ goto finish;
/* We only recognize a selected few here, since we want to
* enforce a redacted namespace */
- if (streq(e, "lxc")) {
- if (id)
- *id = "lxc";
- } else if (streq(e, "lxc-libvirt")) {
- if (id)
- *id = "lxc-libvirt";
- } else if (streq(e, "systemd-nspawn")) {
- if (id)
- *id = "systemd-nspawn";
- } else {
- if (id)
- *id = "other";
- }
+ if (streq(e, "lxc"))
+ _id ="lxc";
+ else if (streq(e, "lxc-libvirt"))
+ _id = "lxc-libvirt";
+ else if (streq(e, "systemd-nspawn"))
+ _id = "systemd-nspawn";
+ else
+ _id = "other";
+
+finish:
+ cached_found = r;
+
+ cached_id = _id;
+ if (id)
+ *id = _id;
return r;
}
/* Returns a short identifier for the various VM/container implementations */
Virtualization detect_virtualization(const char **id) {
-
- static __thread Virtualization cached_virt = _VIRTUALIZATION_INVALID;
- static __thread const char *cached_id = NULL;
-
- const char *_id;
int r;
- Virtualization v;
-
- if (_likely_(cached_virt >= 0)) {
-
- if (id && cached_virt > 0)
- *id = cached_id;
- return cached_virt;
- }
-
- r = detect_container(&_id);
- if (r < 0) {
- v = r;
- goto finish;
- } else if (r > 0) {
- v = VIRTUALIZATION_CONTAINER;
- goto finish;
- }
-
- r = detect_vm(&_id);
- if (r < 0) {
- v = r;
- goto finish;
- } else if (r > 0) {
- v = VIRTUALIZATION_VM;
- goto finish;
- }
-
- v = VIRTUALIZATION_NONE;
-
-finish:
- if (v > 0) {
- cached_id = _id;
-
- if (id)
- *id = _id;
- }
+ r = detect_container(id);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return VIRTUALIZATION_CONTAINER;
- if (v >= 0)
- cached_virt = v;
+ r = detect_vm(id);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return VIRTUALIZATION_VM;
- return v;
+ return VIRTUALIZATION_NONE;
}