mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
openvz: read vmguarpages/privvmpages to set memory tunables
This commit is contained in:
parent
fd2b41574e
commit
1cbe658bea
@ -129,6 +129,46 @@ int openvzExtractVersion(struct openvz_driver *driver)
|
||||
}
|
||||
|
||||
|
||||
/* Parse config values of the form barrier:limit into barrier and limit */
|
||||
static int
|
||||
openvzParseBarrierLimit(const char* value,
|
||||
unsigned long long *barrier,
|
||||
unsigned long long *limit)
|
||||
{
|
||||
char *token;
|
||||
char *saveptr = NULL;
|
||||
char *str = strdup(value);
|
||||
|
||||
if (str == NULL) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
token = strtok_r(str, ":", &saveptr);
|
||||
if (token == NULL) {
|
||||
goto error;
|
||||
} else {
|
||||
if (barrier != NULL) {
|
||||
if (virStrToLong_ull(token, NULL, 10, barrier))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
token = strtok_r(NULL, ":", &saveptr);
|
||||
if (token == NULL) {
|
||||
goto error;
|
||||
} else {
|
||||
if (limit != NULL) {
|
||||
if (virStrToLong_ull(token, NULL, 10, limit))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
VIR_FREE(str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int openvzDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_OPENVZ;
|
||||
@ -423,6 +463,80 @@ error:
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openvzReadMemConf(virDomainDefPtr def, int veid)
|
||||
{
|
||||
int ret;
|
||||
char *temp = NULL;
|
||||
unsigned long long barrier, limit;
|
||||
const char *param;
|
||||
unsigned long kb_per_pages;
|
||||
|
||||
kb_per_pages = sysconf(_SC_PAGESIZE);
|
||||
if (kb_per_pages > 0) {
|
||||
kb_per_pages /= 1024;
|
||||
} else {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Can't determine page size"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Memory allocation guarantee */
|
||||
param = "VMGUARPAGES";
|
||||
ret = openvzReadVPSConfigParam(veid, param, &temp);
|
||||
if (ret < 0) {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not read '%s' from config for container %d"),
|
||||
param, veid);
|
||||
goto error;
|
||||
} else if (ret > 0) {
|
||||
ret = openvzParseBarrierLimit(temp, &barrier, NULL);
|
||||
if (ret < 0) {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not parse barrier of '%s' "
|
||||
"from config for container %d"), param, veid);
|
||||
goto error;
|
||||
}
|
||||
if (barrier == LONG_MAX)
|
||||
def->mem.min_guarantee = 0ull;
|
||||
else
|
||||
def->mem.min_guarantee = barrier * kb_per_pages;
|
||||
}
|
||||
|
||||
/* Memory hard and soft limits */
|
||||
param = "PRIVVMPAGES";
|
||||
ret = openvzReadVPSConfigParam(veid, param, &temp);
|
||||
if (ret < 0) {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not read '%s' from config for container %d"),
|
||||
param, veid);
|
||||
goto error;
|
||||
} else if (ret > 0) {
|
||||
ret = openvzParseBarrierLimit(temp, &barrier, &limit);
|
||||
if (ret < 0) {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not parse barrier and limit of '%s' "
|
||||
"from config for container %d"), param, veid);
|
||||
goto error;
|
||||
}
|
||||
if (barrier == LONG_MAX)
|
||||
def->mem.soft_limit = 0ull;
|
||||
else
|
||||
def->mem.soft_limit = barrier * kb_per_pages;
|
||||
|
||||
if (limit == LONG_MAX)
|
||||
def->mem.hard_limit = 0ull;
|
||||
else
|
||||
def->mem.hard_limit = limit * kb_per_pages;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
error:
|
||||
VIR_FREE(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Free all memory associated with a openvz_driver structure */
|
||||
void
|
||||
openvzFreeDriver(struct openvz_driver *driver)
|
||||
@ -535,6 +649,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
|
||||
|
||||
openvzReadNetworkConf(dom->def, veid);
|
||||
openvzReadFSConf(dom->def, veid);
|
||||
openvzReadMemConf(dom->def, veid);
|
||||
|
||||
virUUIDFormat(dom->def->uuid, uuidstr);
|
||||
if (virHashAddEntry(driver->domains.objs, uuidstr, dom) < 0)
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nodeinfo.h"
|
||||
#include "memory.h"
|
||||
#include "virfile.h"
|
||||
#include "virtypedparam.h"
|
||||
#include "logging.h"
|
||||
#include "command.h"
|
||||
#include "viruri.h"
|
||||
@ -65,6 +66,8 @@
|
||||
#define CMDBUF_LEN 1488
|
||||
#define CMDOP_LEN 288
|
||||
|
||||
#define OPENVZ_NB_MEM_PARAM 3
|
||||
|
||||
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
|
||||
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
|
||||
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
|
||||
@ -1631,6 +1634,223 @@ cleanup:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openvzDomainGetBarrierLimit(virDomainPtr domain,
|
||||
const char *param,
|
||||
unsigned long long *barrier,
|
||||
unsigned long long *limit)
|
||||
{
|
||||
int status, ret = -1;
|
||||
char *endp, *output = NULL;
|
||||
const char *tmp;
|
||||
virCommandPtr cmd = virCommandNewArgList(VZLIST, "--no-header", NULL);
|
||||
|
||||
virCommandSetOutputBuffer(cmd, &output);
|
||||
virCommandAddArgFormat(cmd, "-o%s.b,%s.l", param, param);
|
||||
virCommandAddArg(cmd, domain->name);
|
||||
if (virCommandRun(cmd, &status)) {
|
||||
openvzError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Failed to get %s for %s: %d"), param, domain->name,
|
||||
status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmp = output;
|
||||
virSkipSpaces(&tmp);
|
||||
if (virStrToLong_ull(tmp, &endp, 10, barrier) < 0) {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Can't parse limit from "VZLIST" output '%s'"), output);
|
||||
goto cleanup;
|
||||
}
|
||||
tmp = endp;
|
||||
virSkipSpaces(&tmp);
|
||||
if (virStrToLong_ull(tmp, &endp, 10, limit) < 0) {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Can't parse barrier from "VZLIST" output '%s'"), output);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
VIR_FREE(output);
|
||||
virCommandFree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openvzDomainSetBarrierLimit(virDomainPtr domain,
|
||||
const char *param,
|
||||
unsigned long long barrier,
|
||||
unsigned long long limit)
|
||||
{
|
||||
int status, ret = -1;
|
||||
virCommandPtr cmd = virCommandNewArgList(VZCTL, "--quiet", "set", NULL);
|
||||
|
||||
/* LONG_MAX indicates unlimited so reject larger values */
|
||||
if (barrier > LONG_MAX || limit > LONG_MAX) {
|
||||
openvzError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Failed to set %s for %s: value too large"), param,
|
||||
domain->name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
virCommandAddArg(cmd, domain->name);
|
||||
virCommandAddArgFormat(cmd, "--%s", param);
|
||||
virCommandAddArgFormat(cmd, "%llu:%llu", barrier, limit);
|
||||
virCommandAddArg(cmd, "--save");
|
||||
if (virCommandRun(cmd, &status)) {
|
||||
openvzError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Failed to set %s for %s: %d"), param, domain->name,
|
||||
status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
virCommandFree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openvzDomainGetMemoryParameters(virDomainPtr domain,
|
||||
virTypedParameterPtr params,
|
||||
int *nparams,
|
||||
unsigned int flags)
|
||||
{
|
||||
int i, result = -1;
|
||||
const char *name;
|
||||
long kb_per_pages;
|
||||
unsigned long long barrier, limit, val;
|
||||
|
||||
virCheckFlags(0, -1);
|
||||
|
||||
kb_per_pages = sysconf(_SC_PAGESIZE);
|
||||
if (kb_per_pages > 0) {
|
||||
kb_per_pages /= 1024;
|
||||
} else {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Can't determine page size"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (*nparams == 0) {
|
||||
*nparams = OPENVZ_NB_MEM_PARAM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i <= *nparams; i++) {
|
||||
virMemoryParameterPtr param = ¶ms[i];
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
name = "privvmpages";
|
||||
if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
|
||||
goto cleanup;
|
||||
|
||||
val = (limit == LONG_MAX) ? 0ull : limit * kb_per_pages;
|
||||
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
|
||||
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
name = "privvmpages";
|
||||
if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
|
||||
goto cleanup;
|
||||
|
||||
val = (barrier == LONG_MAX) ? 0ull : barrier * kb_per_pages;
|
||||
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
|
||||
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
name = "vmguarpages";
|
||||
if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
|
||||
goto cleanup;
|
||||
|
||||
val = (barrier == LONG_MAX) ? 0ull : barrier * kb_per_pages;
|
||||
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_MIN_GUARANTEE,
|
||||
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*nparams > OPENVZ_NB_MEM_PARAM)
|
||||
*nparams = OPENVZ_NB_MEM_PARAM;
|
||||
result = 0;
|
||||
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openvzDomainSetMemoryParameters(virDomainPtr domain,
|
||||
virTypedParameterPtr params,
|
||||
int nparams,
|
||||
unsigned int flags)
|
||||
{
|
||||
int i, result = -1;
|
||||
long kb_per_pages;
|
||||
|
||||
kb_per_pages = sysconf(_SC_PAGESIZE);
|
||||
if (kb_per_pages > 0) {
|
||||
kb_per_pages /= 1024;
|
||||
} else {
|
||||
openvzError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Can't determine page size"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
virCheckFlags(0, -1);
|
||||
if (virTypedParameterArrayValidate(params, nparams,
|
||||
VIR_DOMAIN_MEMORY_HARD_LIMIT,
|
||||
VIR_TYPED_PARAM_ULLONG,
|
||||
VIR_DOMAIN_MEMORY_SOFT_LIMIT,
|
||||
VIR_TYPED_PARAM_ULLONG,
|
||||
VIR_DOMAIN_MEMORY_MIN_GUARANTEE,
|
||||
VIR_TYPED_PARAM_ULLONG,
|
||||
NULL) < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < nparams; i++) {
|
||||
virTypedParameterPtr param = ¶ms[i];
|
||||
unsigned long long barrier, limit;
|
||||
|
||||
if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
|
||||
if (openvzDomainGetBarrierLimit(domain, "privvmpages",
|
||||
&barrier, &limit) < 0)
|
||||
goto cleanup;
|
||||
limit = params[i].value.ul / kb_per_pages;
|
||||
if (openvzDomainSetBarrierLimit(domain, "privvmpages",
|
||||
barrier, limit) < 0)
|
||||
goto cleanup;
|
||||
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
|
||||
if (openvzDomainGetBarrierLimit(domain, "privvmpages",
|
||||
&barrier, &limit) < 0)
|
||||
goto cleanup;
|
||||
barrier = params[i].value.ul / kb_per_pages;
|
||||
if (openvzDomainSetBarrierLimit(domain, "privvmpages",
|
||||
barrier, limit) < 0)
|
||||
goto cleanup;
|
||||
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) {
|
||||
barrier = params[i].value.ul / kb_per_pages;
|
||||
if (openvzDomainSetBarrierLimit(domain, "vmguarpages",
|
||||
barrier, LONG_MAX) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason)
|
||||
{
|
||||
@ -1752,6 +1972,8 @@ static virDriver openvzDriver = {
|
||||
.domainDestroy = openvzDomainShutdown, /* 0.3.1 */
|
||||
.domainDestroyFlags = openvzDomainShutdownFlags, /* 0.9.4 */
|
||||
.domainGetOSType = openvzGetOSType, /* 0.3.1 */
|
||||
.domainGetMemoryParameters = openvzDomainGetMemoryParameters, /* 0.9.12 */
|
||||
.domainSetMemoryParameters = openvzDomainSetMemoryParameters, /* 0.9.12 */
|
||||
.domainGetInfo = openvzDomainGetInfo, /* 0.3.1 */
|
||||
.domainGetState = openvzDomainGetState, /* 0.9.2 */
|
||||
.domainSetVcpus = openvzDomainSetVcpus, /* 0.4.6 */
|
||||
|
26
tests/domainschemadata/domain-openvz-simple.xml
Normal file
26
tests/domainschemadata/domain-openvz-simple.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<domain type='openvz'>
|
||||
<name>100</name>
|
||||
<uuid>7109d234-f5a8-30a6-5dd2-39ca85ce3958</uuid>
|
||||
<memory unit='KiB'>0</memory>
|
||||
<currentMemory unit='KiB'>0</currentMemory>
|
||||
<memtune>
|
||||
<hard_limit unit='KiB'>278528</hard_limit>
|
||||
<soft_limit unit='KiB'>262144</soft_limit>
|
||||
<min_guarantee unit='KiB'>135168</min_guarantee>
|
||||
</memtune>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type>exe</type>
|
||||
<init>/sbin/init</init>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>destroy</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<filesystem type='template' accessmode='passthrough'>
|
||||
<source name='debian'/>
|
||||
<target dir='/'/>
|
||||
</filesystem>
|
||||
</devices>
|
||||
</domain>
|
Loading…
Reference in New Issue
Block a user