X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fintel_rdt.c;h=fc2a5f1791e49775370b792fbfb3bdac9f16461c;hb=9eb3efd17e10c3bd59aa227d8d11fe60d6d4f303;hp=d8e775f1ca1723e7e65196852429bab2b5f0431c;hpb=e98570d34dfc2a6ba7a16e75b16caf617a6ca067;p=collectd.git diff --git a/src/intel_rdt.c b/src/intel_rdt.c index d8e775f1..fc2a5f17 100644 --- a/src/intel_rdt.c +++ b/src/intel_rdt.c @@ -3,15 +3,15 @@ * * Copyright(c) 2016 Intel Corporation. All rights reserved. * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do - * so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -25,8 +25,8 @@ * Serhiy Pshyk **/ -#include "collectd.h" #include "common.h" +#include "collectd.h" #include @@ -36,6 +36,11 @@ #define RDT_MAX_SOCKET_CORES 64 #define RDT_MAX_CORES (RDT_MAX_SOCKET_CORES * RDT_MAX_SOCKETS) +typedef enum { + UNKNOWN = 0, + CONFIGURATION_ERROR, +} rdt_config_status; + struct rdt_core_group_s { char *desc; size_t num_cores; @@ -56,6 +61,8 @@ typedef struct rdt_ctx_s rdt_ctx_t; static rdt_ctx_t *g_rdt = NULL; +static rdt_config_status g_state = UNKNOWN; + static int isdup(const uint64_t *nums, size_t size, uint64_t val) { for (size_t i = 0; i < size; i++) if (nums[i] == val) @@ -245,14 +252,13 @@ static int cgroup_set(rdt_core_group_t *cg, char *desc, uint64_t *cores, * `item' Config option containing core groups. * `groups' Table of core groups to set values in. * `max_groups' Maximum number of core groups allowed. - * `max_core' Maximum allowed core value. * * RETURN VALUE * On success, the number of core groups set up. On error, appropriate * negative error value. */ static int oconfig_to_cgroups(oconfig_item_t *item, rdt_core_group_t *groups, - size_t max_groups, uint64_t max_core) { + size_t max_groups) { int index = 0; assert(groups != NULL); @@ -265,7 +271,8 @@ static int oconfig_to_cgroups(oconfig_item_t *item, rdt_core_group_t *groups, uint64_t cores[RDT_MAX_CORES] = {0}; char value[DATA_MAX_NAME_LEN]; - if ((item->values[j].value.string == NULL) || (strlen(item->values[j].value.string) == 0)) + if ((item->values[j].value.string == NULL) || + (strlen(item->values[j].value.string) == 0)) continue; sstrncpy(value, item->values[j].value.string, sizeof(value)); @@ -277,14 +284,6 @@ static int oconfig_to_cgroups(oconfig_item_t *item, rdt_core_group_t *groups, return (-EINVAL); } - for (int i = 0; i < n; i++) { - if (cores[i] > max_core) { - ERROR(RDT_PLUGIN ": Core group (%s) contains invalid core id (%d)", - item->values[j].value.string, (int)cores[i]); - return (-EINVAL); - } - } - /* set core group info */ ret = cgroup_set(&groups[index], item->values[j].value.string, cores, n); if (ret < 0) @@ -387,6 +386,15 @@ static int rdt_default_cgroups(void) { return g_rdt->pqos_cpu->num_cores; } +static int rdt_is_core_id_valid(int core_id) { + + for (int i = 0; i < g_rdt->pqos_cpu->num_cores; i++) + if (core_id == g_rdt->pqos_cpu->cores[i].lcore) + return 1; + + return 0; +} + static int rdt_config_cgroups(oconfig_item_t *item) { int n = 0; enum pqos_mon_event events = 0; @@ -399,28 +407,39 @@ static int rdt_config_cgroups(oconfig_item_t *item) { DEBUG(RDT_PLUGIN ": Core groups [%d]:", item->values_num); for (int j = 0; j < item->values_num; j++) { if (item->values[j].type != OCONFIG_TYPE_STRING) { - ERROR(RDT_PLUGIN ": given core group value is not a string [idx=%d]", - j); + ERROR(RDT_PLUGIN ": given core group value is not a string [idx=%d]", j); return (-EINVAL); } DEBUG(RDT_PLUGIN ": [%d]: %s", j, item->values[j].value.string); } - n = oconfig_to_cgroups(item, g_rdt->cgroups, RDT_MAX_CORES, - g_rdt->pqos_cpu->num_cores-1); + n = oconfig_to_cgroups(item, g_rdt->cgroups, g_rdt->pqos_cpu->num_cores); if (n < 0) { rdt_free_cgroups(); ERROR(RDT_PLUGIN ": Error parsing core groups configuration."); return (-EINVAL); } + /* validate configured core id values */ + for (int group_idx = 0; group_idx < n; group_idx++) { + for (int core_idx = 0; core_idx < g_rdt->cgroups[group_idx].num_cores; + core_idx++) { + if (!rdt_is_core_id_valid(g_rdt->cgroups[group_idx].cores[core_idx])) { + ERROR(RDT_PLUGIN ": Core group '%s' contains invalid core id '%d'", + g_rdt->cgroups[group_idx].desc, + (int)g_rdt->cgroups[group_idx].cores[core_idx]); + rdt_free_cgroups(); + return (-EINVAL); + } + } + } + if (n == 0) { /* create default core groups if "Cores" config option is empty */ n = rdt_default_cgroups(); if (n < 0) { rdt_free_cgroups(); - ERROR(RDT_PLUGIN - ": Error creating default core groups configuration."); + ERROR(RDT_PLUGIN ": Error creating default core groups configuration."); return n; } INFO(RDT_PLUGIN @@ -461,6 +480,10 @@ static int rdt_config_cgroups(oconfig_item_t *item) { return (0); } +static void rdt_pqos_log(void *context, const size_t size, const char *msg) { + DEBUG(RDT_PLUGIN ": %s", msg); +} + static int rdt_preinit(void) { int ret; @@ -475,15 +498,12 @@ static int rdt_preinit(void) { return (-ENOMEM); } - /* In case previous instance of the application was not closed properly - * call fini and ignore return code. */ - pqos_fini(); + struct pqos_config pqos = {.fd_log = -1, + .callback_log = rdt_pqos_log, + .context_log = NULL, + .verbose = 0}; - /* TODO: - * stdout should not be used here. Will be reworked when support of log - * callback is added to PQoS library. - */ - ret = pqos_init(&(struct pqos_config){.fd_log = STDOUT_FILENO}); + ret = pqos_init(&pqos); if (ret != PQOS_RETVAL_OK) { ERROR(RDT_PLUGIN ": Error initializing PQoS library!"); goto rdt_preinit_error1; @@ -495,8 +515,7 @@ static int rdt_preinit(void) { goto rdt_preinit_error2; } - ret = pqos_cap_get_type(g_rdt->pqos_cap, PQOS_CAP_TYPE_MON, - &g_rdt->cap_mon); + ret = pqos_cap_get_type(g_rdt->pqos_cap, PQOS_CAP_TYPE_MON, &g_rdt->cap_mon); if (ret == PQOS_RETVAL_PARAM) { ERROR(RDT_PLUGIN ": Error retrieving monitoring capabilities."); goto rdt_preinit_error2; @@ -509,6 +528,9 @@ static int rdt_preinit(void) { goto rdt_preinit_error2; } + /* Reset pqos monitoring groups registers */ + pqos_mon_reset(); + return (0); rdt_preinit_error2: @@ -525,8 +547,14 @@ static int rdt_config(oconfig_item_t *ci) { int ret = 0; ret = rdt_preinit(); - if (ret != 0) - return ret; + if (ret != 0) { + g_state = CONFIGURATION_ERROR; + /* if we return -1 at this point collectd + reports a failure in configuration and + aborts + */ + goto exit; + } for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -534,27 +562,33 @@ static int rdt_config(oconfig_item_t *ci) { if (strcasecmp("Cores", child->key) == 0) { ret = rdt_config_cgroups(child); - if (ret != 0) - return ret; + if (ret != 0) { + g_state = CONFIGURATION_ERROR; + /* if we return -1 at this point collectd + reports a failure in configuration and + aborts + */ + goto exit; + } #if COLLECT_DEBUG rdt_dump_cgroups(); #endif /* COLLECT_DEBUG */ } else { - ERROR(RDT_PLUGIN ": Unknown configuration parameter \"%s\".", - child->key); + ERROR(RDT_PLUGIN ": Unknown configuration parameter \"%s\".", child->key); } } +exit: return (0); } static void rdt_submit_derive(char *cgroup, char *type, char *type_instance, - derive_t value) { + derive_t value) { value_list_t vl = VALUE_LIST_INIT; - vl.values = &(value_t) { .derive = value }; + vl.values = &(value_t){.derive = value}; vl.values_len = 1; sstrncpy(vl.plugin, RDT_PLUGIN, sizeof(vl.plugin)); @@ -567,10 +601,10 @@ static void rdt_submit_derive(char *cgroup, char *type, char *type_instance, } static void rdt_submit_gauge(char *cgroup, char *type, char *type_instance, - gauge_t value) { + gauge_t value) { value_list_t vl = VALUE_LIST_INIT; - vl.values = &(value_t) { .gauge = value }; + vl.values = &(value_t){.gauge = value}; vl.values_len = 1; sstrncpy(vl.plugin, RDT_PLUGIN, sizeof(vl.plugin)); @@ -616,10 +650,10 @@ static int rdt_read(__attribute__((unused)) user_data_t *ud) { rdt_submit_gauge(g_rdt->cgroups[i].desc, "ipc", NULL, pv->ipc); if (g_rdt->cgroups[i].events & mbm_events) { - rdt_submit_derive(g_rdt->cgroups[i].desc, "memory_bandwidth", - "local", pv->mbm_local_delta); - rdt_submit_derive(g_rdt->cgroups[i].desc, "memory_bandwidth", - "remote", pv->mbm_remote_delta); + rdt_submit_derive(g_rdt->cgroups[i].desc, "memory_bandwidth", "local", + pv->mbm_local_delta); + rdt_submit_derive(g_rdt->cgroups[i].desc, "memory_bandwidth", "remote", + pv->mbm_remote_delta); } } @@ -629,6 +663,9 @@ static int rdt_read(__attribute__((unused)) user_data_t *ud) { static int rdt_init(void) { int ret; + if(g_state == CONFIGURATION_ERROR) + return (-1); + ret = rdt_preinit(); if (ret != 0) return ret;