summaryrefslogtreecommitdiffstats
path: root/src/hardware
diff options
context:
space:
mode:
authorPeter Schiffer <pschiffe@redhat.com>2013-05-07 19:49:41 +0200
committerPeter Schiffer <pschiffe@redhat.com>2013-05-07 19:49:41 +0200
commit1c3bd366f82d4f53c76b89f8fff9359356781622 (patch)
tree2f7dbc5d915daf47391af01abd43f5c87b775c87 /src/hardware
parent7f5607358182d779cf5d3355d4f8d0e3a3f8e607 (diff)
downloadopenlmi-providers-1c3bd366f82d4f53c76b89f8fff9359356781622.tar.gz
openlmi-providers-1c3bd366f82d4f53c76b89f8fff9359356781622.tar.xz
openlmi-providers-1c3bd366f82d4f53c76b89f8fff9359356781622.zip
Hardware: Better support for multi CPU systems and kvm guests.
Changes: * Fixed problem when CPU ID from dmidecode is not unique * Use cache info from sysfs if dmi cpu info is available, but not dmi cache * When using sysfs cache, create all caches for every CPU * Fixed physical memory tag when serial number field is missing in dmidecode output * Tiny clean-up Hardware provider was tested in kvm guest with pegasus and this patch is result of the test. Now, thanks to the all fallback options, hardware provider works fine in this environment with and without selinux enabled.
Diffstat (limited to 'src/hardware')
-rw-r--r--src/hardware/LMI_AssociatedProcessorCacheMemoryProvider.c130
-rw-r--r--src/hardware/LMI_ProcessorProvider.c1
-rw-r--r--src/hardware/dmidecode.c23
-rw-r--r--src/hardware/sysfs.c78
-rw-r--r--src/hardware/sysfs.h2
-rw-r--r--src/hardware/utils.c46
-rw-r--r--src/hardware/utils.h11
7 files changed, 217 insertions, 74 deletions
diff --git a/src/hardware/LMI_AssociatedProcessorCacheMemoryProvider.c b/src/hardware/LMI_AssociatedProcessorCacheMemoryProvider.c
index 3d06a65..6310ea9 100644
--- a/src/hardware/LMI_AssociatedProcessorCacheMemoryProvider.c
+++ b/src/hardware/LMI_AssociatedProcessorCacheMemoryProvider.c
@@ -89,8 +89,8 @@ static CMPIStatus LMI_AssociatedProcessorCacheMemoryEnumInstances(
dmi_free_cpu_caches(&dmi_cpu_caches, &dmi_cpu_caches_nb);
}
- /* if we don't have dmidecode data */
- if (dmi_cpus_nb < 1 || dmi_cpu_caches_nb < 1) {
+ /* without dmi cpus, we can't use dmi cache */
+ if (dmi_cpus_nb < 1) {
dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
dmi_free_cpu_caches(&dmi_cpu_caches, &dmi_cpu_caches_nb);
@@ -104,6 +104,15 @@ static CMPIStatus LMI_AssociatedProcessorCacheMemoryEnumInstances(
error_msg = "Unable to get processor cache information.";
goto done;
}
+ } else if (dmi_cpu_caches_nb < 1) {
+ /* but we can do OK with dmi cpu and no dmi cache */
+ dmi_free_cpu_caches(&dmi_cpu_caches, &dmi_cpu_caches_nb);
+
+ if (sysfs_get_cpu_caches(&sysfs_cpu_caches, &sysfs_cpu_caches_nb) != 0
+ || sysfs_cpu_caches_nb < 1) {
+ error_msg = "Unable to get processor cache information.";
+ goto done;
+ }
}
if (dmi_cpus_nb > 0) {
@@ -115,7 +124,7 @@ static CMPIStatus LMI_AssociatedProcessorCacheMemoryEnumInstances(
goto done;
}
- /* if we have cpus and caches from dmidecode */
+ /* if we have cpus and caches from dmidecode; */
/* in this case, we can match exactly cpus and caches */
if (dmi_cpus_nb > 0 && dmi_cpu_caches_nb > 0) {
/* loop cpus */
@@ -198,8 +207,7 @@ static CMPIStatus LMI_AssociatedProcessorCacheMemoryEnumInstances(
}
}
} else {
- /* in this case, we match every cache to every cpu, assuming all the */
- /* cpus are the same */
+ /* in this case, we have all caches for every cpu */
/* loop caches */
for (i = 0; i < sysfs_cpu_caches_nb; i++) {
LMI_AssociatedProcessorCacheMemory_Init(&lmi_assoc_cache, _cb, ns);
@@ -214,71 +222,71 @@ static CMPIStatus LMI_AssociatedProcessorCacheMemoryEnumInstances(
LMI_ProcessorCacheMemoryRef_Set_DeviceID(&lmi_cpu_cache,
sysfs_cpu_caches[i].id);
- /* loop cpus */
- for (j = 0; j < cpus_nb; j++) {
- LMI_ProcessorRef_Init(&lmi_cpu, _cb, ns);
- LMI_ProcessorRef_Set_SystemCreationClassName(&lmi_cpu,
- get_system_creation_class_name());
- LMI_ProcessorRef_Set_SystemName(&lmi_cpu, get_system_name());
- LMI_ProcessorRef_Set_CreationClassName(&lmi_cpu,
- ORGID "_" CPU_CLASS_NAME);
-
- if (dmi_cpus_nb > 0) {
- LMI_ProcessorRef_Set_DeviceID(&lmi_cpu, dmi_cpus[j].id);
- } else {
- char cpu_id[LONG_INT_LEN] = "";
- snprintf(cpu_id, LONG_INT_LEN, "%u", j);
- LMI_ProcessorRef_Set_DeviceID(&lmi_cpu, cpu_id);
- }
+ /* determine the right CPU index */
+ j = i / (sysfs_cpu_caches_nb / cpus_nb);
- LMI_AssociatedProcessorCacheMemory_Set_Dependent(
- &lmi_assoc_cache, &lmi_cpu);
- LMI_AssociatedProcessorCacheMemory_Set_Antecedent(
- &lmi_assoc_cache, &lmi_cpu_cache);
-
- cache_level = get_cache_level(sysfs_cpu_caches[i].level);
- if (cache_level == LMI_AssociatedProcessorCacheMemory_Level_Other) {
- char other_level[LONG_INT_LEN];
- snprintf(other_level, LONG_INT_LEN, "%u",
- sysfs_cpu_caches[i].level);
- LMI_AssociatedProcessorCacheMemory_Set_OtherLevelDescription(
- &lmi_assoc_cache, other_level);
- }
- cache_type = get_cache_type(sysfs_cpu_caches[i].type);
- if (cache_type == LMI_AssociatedProcessorCacheMemory_CacheType_Other) {
- LMI_AssociatedProcessorCacheMemory_Set_OtherCacheTypeDescription(
- &lmi_assoc_cache, sysfs_cpu_caches[i].type);
- }
+ LMI_ProcessorRef_Init(&lmi_cpu, _cb, ns);
+ LMI_ProcessorRef_Set_SystemCreationClassName(&lmi_cpu,
+ get_system_creation_class_name());
+ LMI_ProcessorRef_Set_SystemName(&lmi_cpu, get_system_name());
+ LMI_ProcessorRef_Set_CreationClassName(&lmi_cpu,
+ ORGID "_" CPU_CLASS_NAME);
- LMI_AssociatedProcessorCacheMemory_Set_Level(
- &lmi_assoc_cache, cache_level);
- LMI_AssociatedProcessorCacheMemory_Set_CacheType(
- &lmi_assoc_cache, cache_type);
- LMI_AssociatedProcessorCacheMemory_Set_Associativity(
- &lmi_assoc_cache,
- get_cache_associativity_sysfs(
- sysfs_cpu_caches[i].ways_of_assoc));
-
- LMI_AssociatedProcessorCacheMemory_Set_WritePolicy(
- &lmi_assoc_cache,
- LMI_AssociatedProcessorCacheMemory_WritePolicy_Unknown);
- LMI_AssociatedProcessorCacheMemory_Set_ReadPolicy(
- &lmi_assoc_cache,
- LMI_AssociatedProcessorCacheMemory_ReadPolicy_Unknown);
-
- if (sysfs_cpu_caches[i].line_size) {
- LMI_AssociatedProcessorCacheMemory_Set_LineSize(
- &lmi_assoc_cache, sysfs_cpu_caches[i].line_size);
- }
+ if (dmi_cpus_nb > 0) {
+ LMI_ProcessorRef_Set_DeviceID(&lmi_cpu, dmi_cpus[j].id);
+ } else {
+ char cpu_id[LONG_INT_LEN] = "";
+ snprintf(cpu_id, LONG_INT_LEN, "%u", j);
+ LMI_ProcessorRef_Set_DeviceID(&lmi_cpu, cpu_id);
+ }
- KReturnInstance(cr, lmi_assoc_cache);
+ LMI_AssociatedProcessorCacheMemory_Set_Dependent(
+ &lmi_assoc_cache, &lmi_cpu);
+ LMI_AssociatedProcessorCacheMemory_Set_Antecedent(
+ &lmi_assoc_cache, &lmi_cpu_cache);
+
+ cache_level = get_cache_level(sysfs_cpu_caches[i].level);
+ if (cache_level == LMI_AssociatedProcessorCacheMemory_Level_Other) {
+ char other_level[LONG_INT_LEN];
+ snprintf(other_level, LONG_INT_LEN, "%u",
+ sysfs_cpu_caches[i].level);
+ LMI_AssociatedProcessorCacheMemory_Set_OtherLevelDescription(
+ &lmi_assoc_cache, other_level);
+ }
+ cache_type = get_cache_type(sysfs_cpu_caches[i].type);
+ if (cache_type == LMI_AssociatedProcessorCacheMemory_CacheType_Other) {
+ LMI_AssociatedProcessorCacheMemory_Set_OtherCacheTypeDescription(
+ &lmi_assoc_cache, sysfs_cpu_caches[i].type);
}
+
+ LMI_AssociatedProcessorCacheMemory_Set_Level(
+ &lmi_assoc_cache, cache_level);
+ LMI_AssociatedProcessorCacheMemory_Set_CacheType(
+ &lmi_assoc_cache, cache_type);
+ LMI_AssociatedProcessorCacheMemory_Set_Associativity(
+ &lmi_assoc_cache,
+ get_cache_associativity_sysfs(
+ sysfs_cpu_caches[i].ways_of_assoc));
+
+ LMI_AssociatedProcessorCacheMemory_Set_WritePolicy(
+ &lmi_assoc_cache,
+ LMI_AssociatedProcessorCacheMemory_WritePolicy_Unknown);
+ LMI_AssociatedProcessorCacheMemory_Set_ReadPolicy(
+ &lmi_assoc_cache,
+ LMI_AssociatedProcessorCacheMemory_ReadPolicy_Unknown);
+
+ if (sysfs_cpu_caches[i].line_size) {
+ LMI_AssociatedProcessorCacheMemory_Set_LineSize(
+ &lmi_assoc_cache, sysfs_cpu_caches[i].line_size);
+ }
+
+ KReturnInstance(cr, lmi_assoc_cache);
}
}
done:
/* free lscpu only if it was used */
- if (dmi_cpus_nb < 1 || dmi_cpu_caches_nb < 1) {
+ if (dmi_cpus_nb < 1) {
lscpu_free_processor(&lscpu);
}
dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
diff --git a/src/hardware/LMI_ProcessorProvider.c b/src/hardware/LMI_ProcessorProvider.c
index d96c679..b8a30a6 100644
--- a/src/hardware/LMI_ProcessorProvider.c
+++ b/src/hardware/LMI_ProcessorProvider.c
@@ -237,7 +237,6 @@ static CMPIStatus LMI_ProcessorEnumInstances(
done:
free(architecture);
- architecture = NULL;
dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
lscpu_free_processor(&lscpu);
diff --git a/src/hardware/dmidecode.c b/src/hardware/dmidecode.c
index dfff7e3..b3d00ef 100644
--- a/src/hardware/dmidecode.c
+++ b/src/hardware/dmidecode.c
@@ -203,7 +203,13 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* ID */
buf = copy_string_part_after_delim(buffer[i], "ID: ");
if (buf) {
- (*cpus)[curr_cpu].id = buf;
+ char curr_cpu_str[LONG_INT_LEN];
+ snprintf(curr_cpu_str, LONG_INT_LEN, "-%u", curr_cpu);
+ (*cpus)[curr_cpu].id = append_str(buf, curr_cpu_str, NULL);
+ if (!(*cpus)[curr_cpu].id) {
+ ret = -8;
+ goto done;
+ }
buf = NULL;
continue;
}
@@ -745,30 +751,43 @@ short check_dmi_memory_attributes(DmiMemory *memory)
for (i = 0; i < memory->modules_nb; i++) {
if (!memory->modules[i].serial_number) {
- if (!(memory->modules[i].serial_number = strdup(""))) {
+ if (asprintf(&memory->modules[i].serial_number, "%u", i) < 0) {
+ memory->modules[i].serial_number = NULL;
ret = -2;
goto done;
}
+ }
+ if (!memory->modules[i].form_factor) {
if (!(memory->modules[i].form_factor = strdup("Unknown"))) {
ret = -3;
goto done;
}
+ }
+ if (!memory->modules[i].type) {
if (!(memory->modules[i].type = strdup("Unknown"))) {
ret = -4;
goto done;
}
+ }
+ if (!memory->modules[i].bank_label) {
if (!(memory->modules[i].bank_label = strdup(""))) {
ret = -5;
goto done;
}
+ }
+ if (!memory->modules[i].name) {
if (!(memory->modules[i].name = strdup("Memory Module"))) {
ret = -6;
goto done;
}
+ }
+ if (!memory->modules[i].manufacturer) {
if (!(memory->modules[i].manufacturer = strdup(""))) {
ret = -7;
goto done;
}
+ }
+ if (!memory->modules[i].part_number) {
if (!(memory->modules[i].part_number = strdup(""))) {
ret = -8;
goto done;
diff --git a/src/hardware/sysfs.c b/src/hardware/sysfs.c
index 80d360e..565269f 100644
--- a/src/hardware/sysfs.c
+++ b/src/hardware/sysfs.c
@@ -144,11 +144,35 @@ done:
return ret;
}
+/*
+ * Deep copy SysfsCpuCache structure.
+ * @param to destination
+ * @param from source
+ * @return 0 if success, negative value otherwise
+ */
+short copy_sysfs_cpu_cache(SysfsCpuCache *to, const SysfsCpuCache from)
+{
+ *to = from;
+ to->id = strdup(from.id);
+ to->name = strdup(from.name);
+ to->type = strdup(from.type);
+
+ if (!to->id || !to->name || !to->type) {
+ warn("Failed to allocate memory.");
+ return -1;
+ }
+
+ return 0;
+}
+
short sysfs_get_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb)
{
short ret = -1;
unsigned i, level;
char *buf = NULL, *format_str, path[PATH_MAX];
+ DmiProcessor *dmi_cpus = NULL;
+ unsigned dmi_cpus_nb = 0, cpus_nb = 0;
+ LscpuProcessor lscpu;
*caches_nb = 0;
@@ -177,8 +201,27 @@ short sysfs_get_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb)
goto done;
}
+ /* get processor information */
+ if (dmi_get_processors(&dmi_cpus, &dmi_cpus_nb) != 0 || dmi_cpus_nb < 1) {
+ dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
+
+ if (lscpu_get_processor(&lscpu) != 0) {
+ ret = -11;
+ goto done;
+ }
+ }
+ if (dmi_cpus_nb > 0) {
+ cpus_nb = dmi_cpus_nb;
+ } else if (lscpu.processors > 0) {
+ cpus_nb = lscpu.processors;
+ } else {
+ warn("No processor found.");
+ ret = -12;
+ goto done;
+ }
+
/* allocate memory for caches */
- *caches = (SysfsCpuCache *)calloc(*caches_nb, sizeof(SysfsCpuCache));
+ *caches = (SysfsCpuCache *)calloc(*caches_nb * cpus_nb, sizeof(SysfsCpuCache));
if (!(*caches)) {
warn("Failed to allocate memory.");
ret = -4;
@@ -203,13 +246,13 @@ short sysfs_get_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb)
goto done;
}
if (strncmp(buf, "Data", 4) == 0) {
- format_str = "L%ud-%u";
+ format_str = "L%ud";
} else if (strncmp(buf, "Instruction", 11) == 0) {
- format_str = "L%ui-%u";
+ format_str = "L%ui";
} else {
- format_str = "L%u-%u";
+ format_str = "L%u";
}
- if (asprintf(&(*caches)[i].id, format_str, level, i) < 0) {
+ if (asprintf(&(*caches)[i].id, format_str, level) < 0) {
(*caches)[i].id = NULL;
warn("Failed to allocate memory.");
ret = -7;
@@ -253,11 +296,34 @@ short sysfs_get_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb)
}
}
+ /* duplicate all caches for every processor;
+ this assumes that all CPUs in the system are the same */
+ for (i = *caches_nb; i < *caches_nb * cpus_nb; i++) {
+ copy_sysfs_cpu_cache(&(*caches)[i], (*caches)[i % *caches_nb]);
+ }
+ *caches_nb *= cpus_nb;
+
+ /* and give them unique ID */
+ char cache_id[LONG_INT_LEN];
+ for (i = 0; i < *caches_nb; i++) {
+ snprintf(cache_id, LONG_INT_LEN, "-%u", i);
+ (*caches)[i].id = append_str((*caches)[i].id, cache_id, NULL);
+ if (!(*caches)[i].id) {
+ ret = -10;
+ goto done;
+ }
+ }
+
ret = 0;
done:
free(buf);
- buf = NULL;
+
+ /* free lscpu only if it was used */
+ if (dmi_cpus_nb < 1) {
+ lscpu_free_processor(&lscpu);
+ }
+ dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
if (ret != 0) {
sysfs_free_cpu_caches(caches, caches_nb);
diff --git a/src/hardware/sysfs.h b/src/hardware/sysfs.h
index 297a1a7..6ff7085 100644
--- a/src/hardware/sysfs.h
+++ b/src/hardware/sysfs.h
@@ -30,6 +30,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "utils.h"
+#include "dmidecode.h"
+#include "lscpu.h"
#define SYSFS_PATH "/sys/devices/system"
#define SYSFS_CPU_PATH SYSFS_PATH "/cpu"
diff --git a/src/hardware/utils.c b/src/hardware/utils.c
index 8c1b63e..1d80411 100644
--- a/src/hardware/utils.c
+++ b/src/hardware/utils.c
@@ -104,7 +104,6 @@ short read_fp_to_2d_buffer(FILE *fp, char ***buffer, unsigned *buffer_size)
done:
free(line);
- line = NULL;
if (ret != 0) {
free_2d_buffer(&tmp_buffer, &tmp_buffer_lines);
@@ -249,7 +248,7 @@ char *trim(const char *str, const char *delims)
delims = default_delims;
}
- /* trim start of the string */
+ /* trim beginning of the string */
while (strchr(delims, str[0]) && str[0] != '\0') {
str++;
}
@@ -262,7 +261,7 @@ char *trim(const char *str, const char *delims)
}
/* shorten length of string if there are trailing white spaces */
- while (strchr(delims, str[l - 1]) && l != 0) {
+ while (strchr(delims, str[l - 1]) && l > 0) {
l--;
}
@@ -366,7 +365,6 @@ short explode(const char *str, const char *delims, char ***buffer, unsigned *buf
done:
free(trimmed_str);
- trimmed_str = NULL;
if (ret != 0) {
free_2d_buffer(&tmp_buffer, &tmp_buffer_size);
@@ -374,3 +372,43 @@ done:
return ret;
}
+
+char *append_str(char *str, ...)
+{
+ va_list ap;
+ size_t len, newlen;
+ char *next, *end;
+
+ if (str) {
+ len = strlen(str);
+ } else {
+ len = 0;
+ }
+
+ /* count final length */
+ va_start(ap, str);
+ newlen = len + 1;
+ while ((next = va_arg(ap, char *))) {
+ newlen += strlen(next);
+ }
+ va_end(ap);
+
+ /* reallocate string */
+ char *temp = (char *)realloc(str, newlen);
+ if (!temp) {
+ warn("Failed to allocate memory.");
+ return NULL;
+ }
+ str = temp;
+ end = str + len;
+
+ /* append parameters */
+ va_start(ap, str);
+ while ((next = va_arg(ap, char *))) {
+ strcpy(end, next);
+ end += strlen(next);
+ }
+ va_end(ap);
+
+ return str;
+}
diff --git a/src/hardware/utils.h b/src/hardware/utils.h
index 933c042..2a1a690 100644
--- a/src/hardware/utils.h
+++ b/src/hardware/utils.h
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <stdarg.h>
#include "globals.h"
#define LONG_INT_LEN 21 /* 64 bit unsigned int can has 20 decimals + \0 */
@@ -109,5 +110,15 @@ char *trim(const char *str, const char *delims);
*/
short explode(const char *str, const char *delims, char ***buffer, unsigned *buffer_size);
+/*
+ * Append strings to the first string parameter.
+ * @param str string where the rest of params will be appended. Can be NULL.
+ * When appending, str will be reallocated to the correct size.
+ * Last parameter must be NULL.
+ * @return pointer to the final string (same as str, if it wasn't NULL). In case
+ * of any problem, NULL is returned.
+ */
+char *append_str(char *str, ...);
+
#endif /* UTILS_H_ */