mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
Implement schedular tunables API using cgroups
* src/qemu_driver.c: Add driver methods qemuGetSchedulerType, qemuGetSchedulerParameters, qemuSetSchedulerParameters * src/lxc_driver.c: Fix to use unsigned long long consistently for schedular parameters * src/cgroup.h, src/cgroup.c: Fix cpu_shares to take unsigned long long * src/util.c, src/util.h, src/libvirt_private.syms: Add a virStrToDouble helper * src/virsh.c: Fix handling of --set arg to schedinfo command to honour the designated data type of each schedular tunable as declared by the driver
This commit is contained in:
parent
38f6f47be9
commit
55bc5090b9
10
src/cgroup.c
10
src/cgroup.c
@ -790,23 +790,23 @@ int virCgroupAllowDeviceMajor(virCgroupPtr group,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int virCgroupSetCpuShares(virCgroupPtr group, unsigned long shares)
|
||||
int virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares)
|
||||
{
|
||||
return virCgroupSetValueU64(group,
|
||||
VIR_CGROUP_CONTROLLER_CPU,
|
||||
"cpu.shares", (uint64_t)shares);
|
||||
"cpu.shares", shares);
|
||||
}
|
||||
|
||||
int virCgroupGetCpuShares(virCgroupPtr group, unsigned long *shares)
|
||||
int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
|
||||
{
|
||||
return virCgroupGetValueU64(group,
|
||||
VIR_CGROUP_CONTROLLER_CPU,
|
||||
"cpu.shares", (uint64_t *)shares);
|
||||
"cpu.shares", shares);
|
||||
}
|
||||
|
||||
int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage)
|
||||
{
|
||||
return virCgroupGetValueU64(group,
|
||||
VIR_CGROUP_CONTROLLER_CPUACCT,
|
||||
"cpuacct.usage", (uint64_t *)usage);
|
||||
"cpuacct.usage", usage);
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ int virCgroupAllowDeviceMajor(virCgroupPtr group,
|
||||
char type,
|
||||
int major);
|
||||
|
||||
int virCgroupSetCpuShares(virCgroupPtr group, unsigned long shares);
|
||||
int virCgroupGetCpuShares(virCgroupPtr group, unsigned long *shares);
|
||||
int virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares);
|
||||
int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares);
|
||||
|
||||
int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage);
|
||||
|
||||
|
@ -348,6 +348,7 @@ virStrToLong_i;
|
||||
virStrToLong_ll;
|
||||
virStrToLong_ull;
|
||||
virStrToLong_ui;
|
||||
virStrToDouble;
|
||||
virFileLinkPointsTo;
|
||||
virFileResolveLink;
|
||||
saferead;
|
||||
|
@ -1612,9 +1612,14 @@ static int lxcSetSchedulerParameters(virDomainPtr domain,
|
||||
|
||||
for (i = 0; i < nparams; i++) {
|
||||
virSchedParameterPtr param = ¶ms[i];
|
||||
if (param->type != VIR_DOMAIN_SCHED_FIELD_ULLONG) {
|
||||
lxcError(NULL, domain, VIR_ERR_INVALID_ARG,
|
||||
_("invalid type for cpu_shares tunable, expected a 'ullong'"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (STREQ(param->field, "cpu_shares")) {
|
||||
if (virCgroupSetCpuShares(group, params[i].value.ui) != 0)
|
||||
if (virCgroupSetCpuShares(group, params[i].value.ul) != 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
lxcError(NULL, domain, VIR_ERR_INVALID_ARG,
|
||||
@ -1638,7 +1643,7 @@ static int lxcGetSchedulerParameters(virDomainPtr domain,
|
||||
lxc_driver_t *driver = domain->conn->privateData;
|
||||
virCgroupPtr group = NULL;
|
||||
virDomainObjPtr vm = NULL;
|
||||
unsigned long val;
|
||||
unsigned long long val;
|
||||
int ret = -1;
|
||||
|
||||
if (driver->cgroup == NULL)
|
||||
|
@ -5275,6 +5275,151 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static char *qemuGetSchedulerType(virDomainPtr dom,
|
||||
int *nparams)
|
||||
{
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
char *ret;
|
||||
|
||||
if (driver->cgroup == NULL) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nparams)
|
||||
*nparams = 1;
|
||||
|
||||
ret = strdup("posix");
|
||||
if (!ret)
|
||||
virReportOOMError(dom->conn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qemuSetSchedulerParameters(virDomainPtr dom,
|
||||
virSchedParameterPtr params,
|
||||
int nparams)
|
||||
{
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
int i;
|
||||
virCgroupPtr group = NULL;
|
||||
virDomainObjPtr vm = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (driver->cgroup == NULL) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qemuDriverLock(driver);
|
||||
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||
qemuDriverUnlock(driver);
|
||||
|
||||
if (vm == NULL) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("No such domain %s"), dom->uuid);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot find cgroup for domain %s"), vm->def->name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < nparams; i++) {
|
||||
virSchedParameterPtr param = ¶ms[i];
|
||||
|
||||
if (STREQ(param->field, "cpu_shares")) {
|
||||
int rc;
|
||||
if (param->type != VIR_DOMAIN_SCHED_FIELD_ULLONG) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
|
||||
_("invalid type for cpu_shares tunable, expected a 'ullong'"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = virCgroupSetCpuShares(group, params[i].value.ul);
|
||||
if (rc != 0) {
|
||||
virReportSystemError(dom->conn, -rc, "%s",
|
||||
_("unable to set cpu shares tunable"));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
qemudReportError(dom->conn, domain, NULL, VIR_ERR_INVALID_ARG,
|
||||
_("Invalid parameter `%s'"), param->field);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virCgroupFree(&group);
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qemuGetSchedulerParameters(virDomainPtr dom,
|
||||
virSchedParameterPtr params,
|
||||
int *nparams)
|
||||
{
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
virCgroupPtr group = NULL;
|
||||
virDomainObjPtr vm = NULL;
|
||||
unsigned long long val;
|
||||
int ret = -1;
|
||||
int rc;
|
||||
|
||||
if (driver->cgroup == NULL) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*nparams) != 1) {
|
||||
qemudReportError(dom->conn, domain, NULL, VIR_ERR_INVALID_ARG,
|
||||
"%s", _("Invalid parameter count"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qemuDriverLock(driver);
|
||||
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||
qemuDriverUnlock(driver);
|
||||
|
||||
if (vm == NULL) {
|
||||
qemudReportError(dom->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("No such domain %s"), dom->uuid);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot find cgroup for domain %s"), vm->def->name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = virCgroupGetCpuShares(group, &val);
|
||||
if (rc != 0) {
|
||||
virReportSystemError(dom->conn, -rc, "%s",
|
||||
_("unable to get cpu shares tunable"));
|
||||
goto cleanup;
|
||||
}
|
||||
params[0].value.ul = val;
|
||||
strncpy(params[0].field, "cpu_shares", sizeof(params[0].field));
|
||||
params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virCgroupFree(&group);
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* This uses the 'info blockstats' monitor command which was
|
||||
* integrated into both qemu & kvm in late 2007. If the command is
|
||||
* not supported we detect this and return the appropriate error.
|
||||
@ -6248,9 +6393,9 @@ static virDriver qemuDriver = {
|
||||
qemudDomainDetachDevice, /* domainDetachDevice */
|
||||
qemudDomainGetAutostart, /* domainGetAutostart */
|
||||
qemudDomainSetAutostart, /* domainSetAutostart */
|
||||
NULL, /* domainGetSchedulerType */
|
||||
NULL, /* domainGetSchedulerParameters */
|
||||
NULL, /* domainSetSchedulerParameters */
|
||||
qemuGetSchedulerType, /* domainGetSchedulerType */
|
||||
qemuGetSchedulerParameters, /* domainGetSchedulerParameters */
|
||||
qemuSetSchedulerParameters, /* domainSetSchedulerParameters */
|
||||
NULL, /* domainMigratePrepare (v1) */
|
||||
qemudDomainMigratePerform, /* domainMigratePerform */
|
||||
NULL, /* domainMigrateFinish */
|
||||
|
20
src/util.c
20
src/util.c
@ -1479,6 +1479,26 @@ virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *re
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
virStrToDouble(char const *s,
|
||||
char **end_ptr,
|
||||
double *result)
|
||||
{
|
||||
double val;
|
||||
char *p;
|
||||
int err;
|
||||
|
||||
errno = 0;
|
||||
val = strtod(s, &p);
|
||||
err = (errno || (!end_ptr && *p) || p == s);
|
||||
if (end_ptr)
|
||||
*end_ptr = p;
|
||||
if (err)
|
||||
return -1;
|
||||
*result = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virSkipSpaces:
|
||||
* @str: pointer to the char pointer used
|
||||
|
@ -154,6 +154,9 @@ int virStrToLong_ull(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned long long *result);
|
||||
int virStrToDouble(char const *s,
|
||||
char **end_ptr,
|
||||
double *result);
|
||||
|
||||
int virMacAddrCompare (const char *mac1, const char *mac2);
|
||||
|
||||
|
244
src/virsh.c
244
src/virsh.c
@ -1184,26 +1184,112 @@ static const vshCmdOptDef opts_schedinfo[] = {
|
||||
{NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
static int
|
||||
cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd,
|
||||
virSchedParameterPtr param)
|
||||
{
|
||||
int found;
|
||||
char *data;
|
||||
|
||||
/* Legacy 'weight' parameter */
|
||||
if (STREQ(param->field, "weight") &&
|
||||
param->type == VIR_DOMAIN_SCHED_FIELD_UINT &&
|
||||
vshCommandOptBool(cmd, "weight")) {
|
||||
int val;
|
||||
val = vshCommandOptInt(cmd, "weight", &found);
|
||||
if (!found) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid value of weight"));
|
||||
return -1;
|
||||
} else {
|
||||
param->value.ui = val;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Legacy 'cap' parameter */
|
||||
if (STREQ(param->field, "cap") &&
|
||||
param->type == VIR_DOMAIN_SCHED_FIELD_UINT &&
|
||||
vshCommandOptBool(cmd, "cap")) {
|
||||
int val;
|
||||
val = vshCommandOptInt(cmd, "cap", &found);
|
||||
if (!found) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid value of cap"));
|
||||
return -1;
|
||||
} else {
|
||||
param->value.ui = val;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((data = vshCommandOptString(cmd, "set", NULL))) {
|
||||
char *val = strchr(data, '=');
|
||||
int match = 0;
|
||||
if (!val) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid syntax for --set, expecting name=value"));
|
||||
return -1;
|
||||
}
|
||||
*val = '\0';
|
||||
match = STREQ(data, param->field);
|
||||
*val = '=';
|
||||
val++;
|
||||
|
||||
if (!match)
|
||||
return 0;
|
||||
|
||||
switch (param->type) {
|
||||
case VIR_DOMAIN_SCHED_FIELD_INT:
|
||||
if (virStrToLong_i(val, NULL, 10, ¶m->value.i) < 0) {
|
||||
vshError(ctl, FALSE, "%s",
|
||||
_("Invalid value for parameter, expecting an int"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_UINT:
|
||||
if (virStrToLong_ui(val, NULL, 10, ¶m->value.ui) < 0) {
|
||||
vshError(ctl, FALSE, "%s",
|
||||
_("Invalid value for parameter, expecting an unsigned int"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_LLONG:
|
||||
if (virStrToLong_ll(val, NULL, 10, ¶m->value.l) < 0) {
|
||||
vshError(ctl, FALSE, "%s",
|
||||
_("Invalid value for parameter, expecting an long long"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_ULLONG:
|
||||
if (virStrToLong_ull(val, NULL, 10, ¶m->value.ul) < 0) {
|
||||
vshError(ctl, FALSE, "%s",
|
||||
_("Invalid value for parameter, expecting an unsigned long long"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
|
||||
if (virStrToDouble(val, NULL, ¶m->value.d) < 0) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid value for parameter, expecting a double"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
|
||||
param->value.b = STREQ(val, "0") ? 0 : 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
|
||||
{
|
||||
char *schedulertype;
|
||||
char *set;
|
||||
char *param_name = NULL;
|
||||
long long int param_value = 0;
|
||||
virDomainPtr dom;
|
||||
virSchedParameterPtr params = NULL;
|
||||
int i, ret;
|
||||
int nparams = 0;
|
||||
int nr_inputparams = 0;
|
||||
int inputparams = 0;
|
||||
int weightfound = 0;
|
||||
int setfound = 0;
|
||||
int weight = 0;
|
||||
int capfound = 0;
|
||||
int cap = 0;
|
||||
char str_weight[] = "weight";
|
||||
char str_cap[] = "cap";
|
||||
int update = 0;
|
||||
int i, ret;
|
||||
int ret_val = FALSE;
|
||||
|
||||
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
||||
@ -1212,85 +1298,6 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
|
||||
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
|
||||
return FALSE;
|
||||
|
||||
/* Deprecated Xen-only options */
|
||||
if(vshCommandOptBool(cmd, "weight")) {
|
||||
weight = vshCommandOptInt(cmd, "weight", &weightfound);
|
||||
if (!weightfound) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid value of weight"));
|
||||
goto cleanup;
|
||||
} else {
|
||||
nr_inputparams++;
|
||||
}
|
||||
}
|
||||
|
||||
if(vshCommandOptBool(cmd, "cap")) {
|
||||
cap = vshCommandOptInt(cmd, "cap", &capfound);
|
||||
if (!capfound) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid value of cap"));
|
||||
goto cleanup;
|
||||
} else {
|
||||
nr_inputparams++;
|
||||
}
|
||||
}
|
||||
|
||||
if(vshCommandOptBool(cmd, "set")) {
|
||||
set = vshCommandOptString(cmd, "set", &setfound);
|
||||
if (!setfound) {
|
||||
vshError(ctl, FALSE, "%s", _("Error getting param"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
param_name = vshMalloc(ctl, strlen(set) + 1);
|
||||
if (param_name == NULL)
|
||||
goto cleanup;
|
||||
|
||||
if (sscanf(set, "%[^=]=%lli", param_name, ¶m_value) != 2) {
|
||||
vshError(ctl, FALSE, "%s", _("Invalid value of param"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
nr_inputparams++;
|
||||
}
|
||||
|
||||
params = vshMalloc(ctl, sizeof (virSchedParameter) * nr_inputparams);
|
||||
if (params == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (weightfound) {
|
||||
strncpy(params[inputparams].field,str_weight,sizeof(str_weight));
|
||||
params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_UINT;
|
||||
params[inputparams].value.ui = weight;
|
||||
inputparams++;
|
||||
}
|
||||
|
||||
if (capfound) {
|
||||
strncpy(params[inputparams].field,str_cap,sizeof(str_cap));
|
||||
params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_UINT;
|
||||
params[inputparams].value.ui = cap;
|
||||
inputparams++;
|
||||
}
|
||||
/* End Deprecated Xen-only options */
|
||||
|
||||
if (setfound) {
|
||||
strncpy(params[inputparams].field,param_name,sizeof(params[0].field));
|
||||
params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_LLONG;
|
||||
params[inputparams].value.l = param_value;
|
||||
inputparams++;
|
||||
}
|
||||
|
||||
assert (inputparams == nr_inputparams);
|
||||
|
||||
/* Set SchedulerParameters */
|
||||
if (inputparams > 0) {
|
||||
ret = virDomainSetSchedulerParameters(dom, params, inputparams);
|
||||
if (ret == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
free(params);
|
||||
params = NULL;
|
||||
|
||||
/* Print SchedulerType */
|
||||
schedulertype = virDomainGetSchedulerType(dom, &nparams);
|
||||
if (schedulertype!= NULL){
|
||||
@ -1302,21 +1309,38 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Get SchedulerParameters */
|
||||
params = vshMalloc(ctl, sizeof(virSchedParameter)* nparams);
|
||||
if (params == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
for (i = 0; i < nparams; i++){
|
||||
params[i].type = 0;
|
||||
memset (params[i].field, 0, sizeof params[i].field);
|
||||
}
|
||||
ret = virDomainGetSchedulerParameters(dom, params, &nparams);
|
||||
if (ret == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
ret_val = TRUE;
|
||||
if(nparams){
|
||||
if (nparams) {
|
||||
params = vshMalloc(ctl, sizeof(virSchedParameter)* nparams);
|
||||
if (params == NULL)
|
||||
goto cleanup;
|
||||
|
||||
memset(params, 0, sizeof(virSchedParameter)* nparams);
|
||||
ret = virDomainGetSchedulerParameters(dom, params, &nparams);
|
||||
if (ret == -1)
|
||||
goto cleanup;
|
||||
|
||||
/* See if any params are being set */
|
||||
for (i = 0; i < nparams; i++){
|
||||
ret = cmdSchedInfoUpdate(ctl, cmd, &(params[i]));
|
||||
if (ret == -1)
|
||||
goto cleanup;
|
||||
|
||||
if (ret == 1)
|
||||
update = 1;
|
||||
}
|
||||
|
||||
/* Update parameters & refresh data */
|
||||
if (update) {
|
||||
ret = virDomainSetSchedulerParameters(dom, params, nparams);
|
||||
if (ret == -1)
|
||||
goto cleanup;
|
||||
|
||||
ret = virDomainGetSchedulerParameters(dom, params, &nparams);
|
||||
if (ret == -1)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret_val = TRUE;
|
||||
for (i = 0; i < nparams; i++){
|
||||
switch (params[i].type) {
|
||||
case VIR_DOMAIN_SCHED_FIELD_INT:
|
||||
@ -1326,10 +1350,10 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
|
||||
printf("%-15s: %u\n", params[i].field, params[i].value.ui);
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_LLONG:
|
||||
printf("%-15s: %Ld\n", params[i].field, params[i].value.l);
|
||||
printf("%-15s: %lld\n", params[i].field, params[i].value.l);
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_ULLONG:
|
||||
printf("%-15s: %Lu\n", params[i].field, params[i].value.ul);
|
||||
printf("%-15s: %llu\n", params[i].field, params[i].value.ul);
|
||||
break;
|
||||
case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
|
||||
printf("%-15s: %f\n", params[i].field, params[i].value.d);
|
||||
@ -1342,9 +1366,9 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(params);
|
||||
free(param_name);
|
||||
virDomainFree(dom);
|
||||
return ret_val;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user