299 lines
8.4 KiB
Diff
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;
|
||
|
}
|