提交 1cbe658b 编写于 作者: G Guido Günther

openvz: read vmguarpages/privvmpages to set memory tunables

上级 fd2b4157
...@@ -129,6 +129,46 @@ int openvzExtractVersion(struct openvz_driver *driver) ...@@ -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) static int openvzDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
{ {
return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_OPENVZ; return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_OPENVZ;
...@@ -423,6 +463,80 @@ error: ...@@ -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 */ /* Free all memory associated with a openvz_driver structure */
void void
openvzFreeDriver(struct openvz_driver *driver) openvzFreeDriver(struct openvz_driver *driver)
...@@ -535,6 +649,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { ...@@ -535,6 +649,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
openvzReadNetworkConf(dom->def, veid); openvzReadNetworkConf(dom->def, veid);
openvzReadFSConf(dom->def, veid); openvzReadFSConf(dom->def, veid);
openvzReadMemConf(dom->def, veid);
virUUIDFormat(dom->def->uuid, uuidstr); virUUIDFormat(dom->def->uuid, uuidstr);
if (virHashAddEntry(driver->domains.objs, uuidstr, dom) < 0) if (virHashAddEntry(driver->domains.objs, uuidstr, dom) < 0)
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#include "nodeinfo.h" #include "nodeinfo.h"
#include "memory.h" #include "memory.h"
#include "virfile.h" #include "virfile.h"
#include "virtypedparam.h"
#include "logging.h" #include "logging.h"
#include "command.h" #include "command.h"
#include "viruri.h" #include "viruri.h"
...@@ -65,6 +66,8 @@ ...@@ -65,6 +66,8 @@
#define CMDBUF_LEN 1488 #define CMDBUF_LEN 1488
#define CMDOP_LEN 288 #define CMDOP_LEN 288
#define OPENVZ_NB_MEM_PARAM 3
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid); static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type); static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
static int openvzDomainGetMaxVcpus(virDomainPtr dom); static int openvzDomainGetMaxVcpus(virDomainPtr dom);
...@@ -1631,6 +1634,223 @@ cleanup: ...@@ -1631,6 +1634,223 @@ cleanup:
return -1; 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 = &params[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 = &params[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 static int
openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason) openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason)
{ {
...@@ -1752,6 +1972,8 @@ static virDriver openvzDriver = { ...@@ -1752,6 +1972,8 @@ static virDriver openvzDriver = {
.domainDestroy = openvzDomainShutdown, /* 0.3.1 */ .domainDestroy = openvzDomainShutdown, /* 0.3.1 */
.domainDestroyFlags = openvzDomainShutdownFlags, /* 0.9.4 */ .domainDestroyFlags = openvzDomainShutdownFlags, /* 0.9.4 */
.domainGetOSType = openvzGetOSType, /* 0.3.1 */ .domainGetOSType = openvzGetOSType, /* 0.3.1 */
.domainGetMemoryParameters = openvzDomainGetMemoryParameters, /* 0.9.12 */
.domainSetMemoryParameters = openvzDomainSetMemoryParameters, /* 0.9.12 */
.domainGetInfo = openvzDomainGetInfo, /* 0.3.1 */ .domainGetInfo = openvzDomainGetInfo, /* 0.3.1 */
.domainGetState = openvzDomainGetState, /* 0.9.2 */ .domainGetState = openvzDomainGetState, /* 0.9.2 */
.domainSetVcpus = openvzDomainSetVcpus, /* 0.4.6 */ .domainSetVcpus = openvzDomainSetVcpus, /* 0.4.6 */
......
<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>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册