Move resctrl-related code from conf/capabilities to util/virresctrl

It doesn't access anything from conf/ and ti will be needed to use
from other util/ places.  This split makes the separation clearer.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Martin Kletzander 2017-07-25 16:03:11 +02:00
parent ab0e027ffe
commit af4270400a
8 changed files with 245 additions and 145 deletions

View File

@ -132,6 +132,7 @@ typedef enum {
VIR_FROM_PERF = 65, /* Error from perf */
VIR_FROM_LIBSSH = 66, /* Error from libssh connection transport */
VIR_FROM_RESCTRL = 67, /* Error from resource control */
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_DOMAIN_LAST

View File

@ -167,6 +167,7 @@ UTIL_SOURCES = \
util/virprocess.c util/virprocess.h \
util/virqemu.c util/virqemu.h \
util/virrandom.h util/virrandom.c \
util/virresctrl.h util/virresctrl.c \
util/virrotatingfile.h util/virrotatingfile.c \
util/virscsi.c util/virscsi.h \
util/virscsihost.c util/virscsihost.h \

View File

@ -31,8 +31,6 @@
#include <unistd.h>
#include "capabilities.h"
#include "c-ctype.h"
#include "count-one-bits.h"
#include "cpu_conf.h"
#include "domain_conf.h"
#include "physmem.h"
@ -52,7 +50,6 @@
#define VIR_FROM_THIS VIR_FROM_CAPABILITIES
#define SYSFS_SYSTEM_PATH "/sys/devices/system"
#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl"
VIR_LOG_INIT("conf.capabilities")
@ -1539,12 +1536,6 @@ VIR_ENUM_IMPL(virCacheKernel, VIR_CACHE_TYPE_LAST,
"Instruction",
"Data")
/* Our naming for cache types and scopes */
VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST,
"both",
"code",
"data")
bool
virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a,
virCapsHostCacheBankPtr b)
@ -1571,111 +1562,6 @@ virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr)
VIR_FREE(ptr);
}
/*
* This function tests which TYPE of cache control is supported
* Return values are:
* -1: not supported
* 0: CAT
* 1: CDP
*/
static int
virCapabilitiesGetCacheControlType(virCapsHostCacheBankPtr bank)
{
int ret = -1;
char *path = NULL;
if (virAsprintf(&path,
SYSFS_RESCTRL_PATH "/info/L%u",
bank->level) < 0)
return -1;
if (virFileExists(path)) {
ret = 0;
} else {
VIR_FREE(path);
/*
* If CDP is enabled, there will be both CODE and DATA, but it's enough
* to check one of those only.
*/
if (virAsprintf(&path,
SYSFS_RESCTRL_PATH "/info/L%uCODE",
bank->level) < 0)
return -1;
if (virFileExists(path))
ret = 1;
}
VIR_FREE(path);
return ret;
}
static int
virCapabilitiesGetCacheControl(virCapsHostCacheBankPtr bank,
virCacheType scope)
{
int ret = -1;
char *tmp = NULL;
char *path = NULL;
char *cbm_mask = NULL;
char *type_upper = NULL;
unsigned int bits = 0;
unsigned int min_cbm_bits = 0;
virCapsHostCacheControlPtr control;
if (VIR_ALLOC(control) < 0)
goto cleanup;
if (scope != VIR_CACHE_TYPE_BOTH &&
virStringToUpper(&type_upper, virCacheTypeToString(scope)) < 0)
goto cleanup;
if (virFileReadValueUint(&control->max_allocation,
SYSFS_RESCTRL_PATH "/info/L%u%s/num_closids",
bank->level,
type_upper ? type_upper : "") < 0)
goto cleanup;
if (virFileReadValueString(&cbm_mask,
SYSFS_RESCTRL_PATH
"/info/L%u%s/cbm_mask",
bank->level,
type_upper ? type_upper: "") < 0)
goto cleanup;
if (virFileReadValueUint(&min_cbm_bits,
SYSFS_RESCTRL_PATH "/info/L%u%s/min_cbm_bits",
bank->level,
type_upper ? type_upper : "") < 0)
goto cleanup;
virStringTrimOptionalNewline(cbm_mask);
for (tmp = cbm_mask; *tmp != '\0'; tmp++) {
if (c_isxdigit(*tmp))
bits += count_one_bits(virHexToBin(*tmp));
}
control->granularity = bank->size / bits;
if (min_cbm_bits != 1)
control->min = min_cbm_bits * control->granularity;
control->scope = scope;
if (VIR_APPEND_ELEMENT(bank->controls,
bank->ncontrols,
control) < 0)
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(path);
VIR_FREE(cbm_mask);
VIR_FREE(type_upper);
VIR_FREE(control);
return ret;
}
int
virCapabilitiesInitCaches(virCapsPtr caps)
{
@ -1760,17 +1646,27 @@ virCapabilitiesInitCaches(virCapsPtr caps)
SYSFS_SYSTEM_PATH, pos, ent->d_name) < 0)
goto cleanup;
typeret = virCapabilitiesGetCacheControlType(bank);
typeret = virResctrlGetCacheControlType(bank->level);
if (typeret == 0) {
if (virCapabilitiesGetCacheControl(bank,
VIR_CACHE_TYPE_BOTH) < 0)
if (virResctrlGetCacheInfo(bank->level,
bank->size,
VIR_CACHE_TYPE_BOTH,
&bank->controls,
&bank->ncontrols) < 0)
goto cleanup;
} else if (typeret == 1) {
if (virCapabilitiesGetCacheControl(bank,
VIR_CACHE_TYPE_CODE) < 0 ||
virCapabilitiesGetCacheControl(bank,
VIR_CACHE_TYPE_DATA) < 0)
if (virResctrlGetCacheInfo(bank->level,
bank->size,
VIR_CACHE_TYPE_CODE,
&bank->controls,
&bank->ncontrols) < 0)
goto cleanup;
if (virResctrlGetCacheInfo(bank->level,
bank->size,
VIR_CACHE_TYPE_DATA,
&bank->controls,
&bank->ncontrols) < 0)
goto cleanup;
}

View File

@ -30,6 +30,7 @@
# include "virarch.h"
# include "virmacaddr.h"
# include "virobject.h"
# include "virresctrl.h"
# include <libxml/xpath.h>
@ -138,29 +139,6 @@ struct _virCapsHostSecModel {
virCapsHostSecModelLabelPtr labels;
};
typedef enum {
VIR_CACHE_TYPE_BOTH,
VIR_CACHE_TYPE_CODE,
VIR_CACHE_TYPE_DATA,
VIR_CACHE_TYPE_LAST
} virCacheType;
VIR_ENUM_DECL(virCache);
typedef struct _virCapsHostCacheControl virCapsHostCacheControl;
typedef virCapsHostCacheControl *virCapsHostCacheControlPtr;
struct _virCapsHostCacheControl {
/* Smallest possible increase of the allocation size in bytes */
unsigned long long granularity;
/* Minimal allocatable size in bytes (if different from granularity) */
unsigned long long min;
/* Type of the allocation */
virCacheType scope;
/* Maximum number of simultaneous allocations */
unsigned int max_allocation;
};
typedef struct _virCapsHostCacheBank virCapsHostCacheBank;
typedef virCapsHostCacheBank *virCapsHostCacheBankPtr;
struct _virCapsHostCacheBank {
@ -170,7 +148,7 @@ struct _virCapsHostCacheBank {
virCacheType type; /* Data, Instruction or Unified */
virBitmapPtr cpus; /* All CPUs that share this bank */
size_t ncontrols;
virCapsHostCacheControlPtr *controls;
virResctrlPtr *controls;
};
typedef struct _virCapsHost virCapsHost;

View File

@ -2465,6 +2465,13 @@ virRandomGenerateWWN;
virRandomInt;
# util/virresctrl.h
virCacheTypeFromString;
virCacheTypeToString;
virResctrlGetCacheControlType;
virResctrlGetCacheInfo;
# util/virrotatingfile.h
virRotatingFileReaderConsume;
virRotatingFileReaderFree;

View File

@ -139,6 +139,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
"Perf", /* 65 */
"Libssh transport layer",
"Resource control",
)

153
src/util/virresctrl.c Normal file
View File

@ -0,0 +1,153 @@
/*
* virresctrl.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "virresctrl.h"
#include "c-ctype.h"
#include "count-one-bits.h"
#include "viralloc.h"
#include "virfile.h"
#include "virlog.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_RESCTRL
VIR_LOG_INIT("util.virresctrl")
#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl"
/* Resctrl is short for Resource Control. It might be implemented for various
* resources, but at the time of this writing this is only supported for cache
* allocation technology (aka CAT). Hence the reson for leaving 'Cache' out of
* all the structure and function names for now (can be added later if needed.
*/
/* Our naming for cache types and scopes */
VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST,
"both",
"code",
"data")
int
virResctrlGetCacheInfo(unsigned int level,
unsigned long long size,
virCacheType scope,
virResctrlPtr **controls,
size_t *ncontrols)
{
int ret = -1;
char *tmp = NULL;
char *path = NULL;
char *cbm_mask = NULL;
char *type_upper = NULL;
unsigned int bits = 0;
unsigned int min_cbm_bits = 0;
virResctrlPtr control;
if (VIR_ALLOC(control) < 0)
goto cleanup;
if (scope != VIR_CACHE_TYPE_BOTH &&
virStringToUpper(&type_upper, virCacheTypeToString(scope)) < 0)
goto cleanup;
if (virFileReadValueUint(&control->max_allocation,
SYSFS_RESCTRL_PATH "/info/L%u%s/num_closids",
level,
type_upper ? type_upper : "") < 0)
goto cleanup;
if (virFileReadValueString(&cbm_mask,
SYSFS_RESCTRL_PATH
"/info/L%u%s/cbm_mask",
level,
type_upper ? type_upper: "") < 0)
goto cleanup;
if (virFileReadValueUint(&min_cbm_bits,
SYSFS_RESCTRL_PATH "/info/L%u%s/min_cbm_bits",
level,
type_upper ? type_upper : "") < 0)
goto cleanup;
virStringTrimOptionalNewline(cbm_mask);
for (tmp = cbm_mask; *tmp != '\0'; tmp++) {
if (c_isxdigit(*tmp))
bits += count_one_bits(virHexToBin(*tmp));
}
control->granularity = size / bits;
if (min_cbm_bits != 1)
control->min = min_cbm_bits * control->granularity;
control->scope = scope;
if (VIR_APPEND_ELEMENT(*controls, *ncontrols, control) < 0)
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(path);
VIR_FREE(cbm_mask);
VIR_FREE(type_upper);
VIR_FREE(control);
return ret;
}
/*
* This function tests which TYPE of cache control is supported
* Return values are:
* -1: not supported
* 0: CAT
* 1: CDP
*/
int
virResctrlGetCacheControlType(unsigned int level)
{
int ret = -1;
char *path = NULL;
if (virAsprintf(&path,
SYSFS_RESCTRL_PATH "/info/L%u",
level) < 0)
return -1;
if (virFileExists(path)) {
ret = 0;
} else {
VIR_FREE(path);
/*
* If CDP is enabled, there will be both CODE and DATA, but it's enough
* to check one of those only.
*/
if (virAsprintf(&path,
SYSFS_RESCTRL_PATH "/info/L%uCODE",
level) < 0)
return -1;
if (virFileExists(path))
ret = 1;
}
VIR_FREE(path);
return ret;
}

63
src/util/virresctrl.h Normal file
View File

@ -0,0 +1,63 @@
/*
* virresctrl.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __VIR_RESCTRL_H__
# define __VIR_RESCTRL_H__
# include "internal.h"
# include "virbitmap.h"
# include "virutil.h"
typedef enum {
VIR_CACHE_TYPE_BOTH,
VIR_CACHE_TYPE_CODE,
VIR_CACHE_TYPE_DATA,
VIR_CACHE_TYPE_LAST
} virCacheType;
VIR_ENUM_DECL(virCache);
typedef struct _virResctrl virResctrl;
typedef virResctrl *virResctrlPtr;
struct _virResctrl {
/* Smallest possible increase of the allocation size in bytes */
unsigned long long granularity;
/* Minimal allocatable size in bytes (if different from granularity) */
unsigned long long min;
/* Type of the allocation */
virCacheType scope;
/* Maximum number of simultaneous allocations */
unsigned int max_allocation;
};
int
virResctrlGetCacheInfo(unsigned int level,
unsigned long long size,
virCacheType scope,
virResctrlPtr **controls,
size_t *ncontrols);
int
virResctrlGetCacheControlType(unsigned int level);
#endif /* __VIR_RESCTRL_H__ */