for <code><memory></code>. For backwards
compatibility, output is always in
KiB. <span class='since'><code>unit</code>
- since 0.9.11</span></dd>
+ since 0.9.11</span>
+ Possible values for all *_limit parameters are in range from 0 to
+ VIR_DOMAIN_MEMORY_PARAM_UNLIMITED.</dd>
<dt><code>hard_limit</code></dt>
<dd> The optional <code>hard_limit</code> element is the maximum memory
the guest can use. The units for this value are kibibytes (i.e. blocks
if (!(ret->numa = virDomainNumaNew()))
goto error;
+ ret->mem.hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+ ret->mem.soft_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+ ret->mem.swap_hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+
return ret;
error:
}
+/**
+ * virDomainParseMemoryLimit:
+ *
+ * @xpath: XPath to memory amount
+ * @units_xpath: XPath to units attribute
+ * @ctxt: XPath context
+ * @mem: scaled memory amount is stored here
+ *
+ * Parse a memory element or attribute located at @xpath within @ctxt, and
+ * store the result into @mem, in blocks of 1024. The value is scaled by
+ * units located at @units_xpath (or the 'unit' attribute under @xpath if
+ * @units_xpath is NULL). If units are not present, he default scale of 1024
+ * is used. The value must not exceed VIR_DOMAIN_MEMORY_PARAM_UNLIMITED
+ * once scaled.
+ *
+ * This helper should be used only on *_limit memory elements.
+ *
+ * Return 0 on success, -1 on failure after issuing error.
+ */
+static int
+virDomainParseMemoryLimit(const char *xpath,
+ const char *units_xpath,
+ xmlXPathContextPtr ctxt,
+ unsigned long long *mem)
+{
+ int ret;
+ unsigned long long bytes;
+
+ ret = virDomainParseScaledValue(xpath, units_xpath, ctxt, &bytes, 1024,
+ VIR_DOMAIN_MEMORY_PARAM_UNLIMITED << 10,
+ false);
+
+ if (ret < 0)
+ return -1;
+
+ if (ret == 0)
+ *mem = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+ else
+ *mem = virMemoryLimitTruncate(VIR_DIV_UP(bytes, 1024));
+
+ return 0;
+}
+
+
static int
virDomainControllerModelTypeFromString(const virDomainControllerDef *def,
const char *model)
VIR_FREE(nodes);
/* Extract other memory tunables */
- if (virDomainParseMemory("./memtune/hard_limit[1]", NULL, ctxt,
- &def->mem.hard_limit, false, false) < 0)
+ if (virDomainParseMemoryLimit("./memtune/hard_limit[1]", NULL, ctxt,
+ &def->mem.hard_limit) < 0)
goto error;
- if (virDomainParseMemory("./memtune/soft_limit[1]", NULL, ctxt,
- &def->mem.soft_limit, false, false) < 0)
+ if (virDomainParseMemoryLimit("./memtune/soft_limit[1]", NULL, ctxt,
+ &def->mem.soft_limit) < 0)
goto error;
if (virDomainParseMemory("./memtune/min_guarantee[1]", NULL, ctxt,
&def->mem.min_guarantee, false, false) < 0)
goto error;
- if (virDomainParseMemory("./memtune/swap_hard_limit[1]", NULL, ctxt,
- &def->mem.swap_hard_limit, false, false) < 0)
+ if (virDomainParseMemoryLimit("./memtune/swap_hard_limit[1]", NULL, ctxt,
+ &def->mem.swap_hard_limit) < 0)
goto error;
n = virXPathULong("string(./vcpu[1])", ctxt, &count);
}
/* add memtune only if there are any */
- if ((def->mem.hard_limit &&
- def->mem.hard_limit != VIR_DOMAIN_MEMORY_PARAM_UNLIMITED) ||
- (def->mem.soft_limit &&
- def->mem.soft_limit != VIR_DOMAIN_MEMORY_PARAM_UNLIMITED) ||
- (def->mem.swap_hard_limit &&
- def->mem.swap_hard_limit != VIR_DOMAIN_MEMORY_PARAM_UNLIMITED) ||
+ if (virMemoryLimitIsSet(def->mem.hard_limit) ||
+ virMemoryLimitIsSet(def->mem.soft_limit) ||
+ virMemoryLimitIsSet(def->mem.swap_hard_limit) ||
def->mem.min_guarantee) {
virBufferAddLit(buf, "<memtune>\n");
virBufferAdjustIndent(buf, 2);
- if (def->mem.hard_limit) {
+ if (virMemoryLimitIsSet(def->mem.hard_limit)) {
virBufferAsprintf(buf, "<hard_limit unit='KiB'>"
"%llu</hard_limit>\n", def->mem.hard_limit);
}
- if (def->mem.soft_limit) {
+ if (virMemoryLimitIsSet(def->mem.soft_limit)) {
virBufferAsprintf(buf, "<soft_limit unit='KiB'>"
"%llu</soft_limit>\n", def->mem.soft_limit);
}
virBufferAsprintf(buf, "<min_guarantee unit='KiB'>"
"%llu</min_guarantee>\n", def->mem.min_guarantee);
}
- if (def->mem.swap_hard_limit) {
+ if (virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
virBufferAsprintf(buf, "<swap_hard_limit unit='KiB'>"
"%llu</swap_hard_limit>\n", def->mem.swap_hard_limit);
}
* Change all or a subset of the memory tunables.
* This function may require privileged access to the hypervisor.
*
+ * Possible values for all *_limit memory tunables are in range from 0 to
+ * VIR_DOMAIN_MEMORY_PARAM_UNLIMITED.
+ *
* Returns -1 in case of error, 0 in case of success.
*/
int
# util/virutil.h
-virCompareLimitUlong;
virDoubleToStr;
virEnumFromString;
virEnumToString;
if (virCgroupSetMemory(cgroup, def->mem.max_balloon) < 0)
goto cleanup;
- if (def->mem.hard_limit &&
- virCgroupSetMemoryHardLimit(cgroup, def->mem.hard_limit) < 0)
- goto cleanup;
+ if (virMemoryLimitIsSet(def->mem.hard_limit))
+ if (virCgroupSetMemoryHardLimit(cgroup, def->mem.hard_limit) < 0)
+ goto cleanup;
- if (def->mem.soft_limit &&
- virCgroupSetMemorySoftLimit(cgroup, def->mem.soft_limit) < 0)
- goto cleanup;
+ if (virMemoryLimitIsSet(def->mem.soft_limit))
+ if (virCgroupSetMemorySoftLimit(cgroup, def->mem.soft_limit) < 0)
+ goto cleanup;
- if (def->mem.swap_hard_limit &&
- virCgroupSetMemSwapHardLimit(cgroup, def->mem.swap_hard_limit) < 0)
- goto cleanup;
+ if (virMemoryLimitIsSet(def->mem.swap_hard_limit))
+ if (virCgroupSetMemSwapHardLimit(cgroup, def->mem.swap_hard_limit) < 0)
+ goto cleanup;
ret = 0;
cleanup:
if (set_hard_limit)
mem_limit = hard_limit;
- if (virCompareLimitUlong(mem_limit, swap_limit) > 0) {
+ if (mem_limit > swap_limit) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("memory hard_limit tunable value must be lower "
"than or equal to swap_hard_limit"));
LXC_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
/* set hard limit before swap hard limit if decreasing it */
- if (virCompareLimitUlong(vm->def->mem.hard_limit, hard_limit) > 0) {
+ if (vm->def->mem.hard_limit > hard_limit) {
LXC_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
/* inhibit changing the limit a second time */
set_hard_limit = false;
case 0: /* fill memory hard limit here */
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
val = vmdef->mem.hard_limit;
- val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
} else if (virCgroupGetMemoryHardLimit(priv->cgroup, &val) < 0) {
goto cleanup;
}
case 1: /* fill memory soft limit here */
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
val = vmdef->mem.soft_limit;
- val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
} else if (virCgroupGetMemorySoftLimit(priv->cgroup, &val) < 0) {
goto cleanup;
}
case 2: /* fill swap hard limit here */
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
val = vmdef->mem.swap_hard_limit;
- val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
} else if (virCgroupGetMemSwapHardLimit(priv->cgroup, &val) < 0) {
goto cleanup;
}
*ptr = '\0';
if (STREQ(line, "MemTotal") &&
- (def->mem.hard_limit || def->mem.max_balloon)) {
+ (virMemoryLimitIsSet(def->mem.hard_limit) ||
+ def->mem.max_balloon)) {
virBufferAsprintf(new_meminfo, "MemTotal: %8llu kB\n",
meminfo.memtotal);
} else if (STREQ(line, "MemFree") &&
- (def->mem.hard_limit || def->mem.max_balloon)) {
+ (virMemoryLimitIsSet(def->mem.hard_limit) ||
+ def->mem.max_balloon)) {
virBufferAsprintf(new_meminfo, "MemFree: %8llu kB\n",
(meminfo.memtotal - meminfo.memusage));
} else if (STREQ(line, "Buffers")) {
} else if (STREQ(line, "Unevictable")) {
virBufferAsprintf(new_meminfo, "Unevictable: %8llu kB\n",
meminfo.unevictable);
- } else if (STREQ(line, "SwapTotal") && def->mem.swap_hard_limit) {
+ } else if (STREQ(line, "SwapTotal") &&
+ virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
virBufferAsprintf(new_meminfo, "SwapTotal: %8llu kB\n",
(meminfo.swaptotal - meminfo.memtotal));
- } else if (STREQ(line, "SwapFree") && def->mem.swap_hard_limit) {
+ } else if (STREQ(line, "SwapFree") &&
+ virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
virBufferAsprintf(new_meminfo, "SwapFree: %8llu kB\n",
(meminfo.swaptotal - meminfo.memtotal -
meminfo.swapusage + meminfo.memusage));
return -1;
size = size / 1024;
def->mem.max_balloon = size;
- def->mem.hard_limit = size;
+ def->mem.hard_limit = virMemoryLimitTruncate(size);
}
if ((value = virConfGetValue(properties,
if (lxcConvertSize(value->str, &size) < 0)
return -1;
- def->mem.soft_limit = size / 1024;
+ def->mem.soft_limit = virMemoryLimitTruncate(size / 1024);
}
if ((value = virConfGetValue(properties,
if (lxcConvertSize(value->str, &size) < 0)
return -1;
- def->mem.swap_hard_limit = size / 1024;
+ def->mem.swap_hard_limit = virMemoryLimitTruncate(size / 1024);
}
return 0;
}
goto error;
}
if (barrier == LONG_MAX)
- def->mem.soft_limit = 0ull;
+ def->mem.soft_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
else
def->mem.soft_limit = barrier * kb_per_pages;
if (limit == LONG_MAX)
- def->mem.hard_limit = 0ull;
+ def->mem.hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
else
def->mem.hard_limit = limit * kb_per_pages;
}
if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
goto cleanup;
- val = (limit == LONG_MAX) ? 0ull : limit * kb_per_pages;
+ val = (limit == LONG_MAX) ? VIR_DOMAIN_MEMORY_PARAM_UNLIMITED : limit * kb_per_pages;
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
VIR_TYPED_PARAM_ULLONG, val) < 0)
goto cleanup;
if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
goto cleanup;
- val = (barrier == LONG_MAX) ? 0ull : barrier * kb_per_pages;
+ val = (barrier == LONG_MAX) ? VIR_DOMAIN_MEMORY_PARAM_UNLIMITED : barrier * kb_per_pages;
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
VIR_TYPED_PARAM_ULLONG, val) < 0)
goto cleanup;
qemuDomainObjPrivatePtr priv = vm->privateData;
if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
- if (vm->def->mem.hard_limit != 0 ||
- vm->def->mem.soft_limit != 0 ||
- vm->def->mem.swap_hard_limit != 0) {
+ if (virMemoryLimitIsSet(vm->def->mem.hard_limit) ||
+ virMemoryLimitIsSet(vm->def->mem.soft_limit) ||
+ virMemoryLimitIsSet(vm->def->mem.swap_hard_limit)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Memory cgroup is not available on this host"));
return -1;
}
}
- if (vm->def->mem.hard_limit != 0 &&
- virCgroupSetMemoryHardLimit(priv->cgroup, vm->def->mem.hard_limit) < 0)
- return -1;
+ if (virMemoryLimitIsSet(vm->def->mem.hard_limit))
+ if (virCgroupSetMemoryHardLimit(priv->cgroup, vm->def->mem.hard_limit) < 0)
+ return -1;
- if (vm->def->mem.soft_limit != 0 &&
- virCgroupSetMemorySoftLimit(priv->cgroup, vm->def->mem.soft_limit) < 0)
- return -1;
+ if (virMemoryLimitIsSet(vm->def->mem.soft_limit))
+ if (virCgroupSetMemorySoftLimit(priv->cgroup, vm->def->mem.soft_limit) < 0)
+ return -1;
- if (vm->def->mem.swap_hard_limit != 0 &&
- virCgroupSetMemSwapHardLimit(priv->cgroup, vm->def->mem.swap_hard_limit) < 0)
- return -1;
+ if (virMemoryLimitIsSet(vm->def->mem.swap_hard_limit))
+ if (virCgroupSetMemSwapHardLimit(priv->cgroup, vm->def->mem.swap_hard_limit) < 0)
+ return -1;
return 0;
}
/* If we have no cgroups then we can have no tunings that
* require them */
- if (def->mem.hard_limit || def->mem.soft_limit ||
- def->mem.min_guarantee || def->mem.swap_hard_limit) {
+ if (virMemoryLimitIsSet(def->mem.hard_limit) ||
+ virMemoryLimitIsSet(def->mem.soft_limit) ||
+ def->mem.min_guarantee ||
+ virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Memory tuning is not available in session mode"));
goto error;
* space just to be safe (some finer tuning might be
* nice, though).
*/
- memKB = def->mem.hard_limit ?
+ memKB = virMemoryLimitIsSet(def->mem.hard_limit) ?
def->mem.hard_limit : def->mem.max_balloon + 1024 * 1024;
virCommandSetMaxMemLock(cmd, memKB * 1024);
}
#undef VIR_GET_LIMIT_PARAMETER
- /* Swap hard limit must be greater than hard limit.
- * Note that limit of 0 denotes unlimited */
+ /* Swap hard limit must be greater than hard limit. */
if (set_swap_hard_limit || set_hard_limit) {
unsigned long long mem_limit = vm->def->mem.hard_limit;
unsigned long long swap_limit = vm->def->mem.swap_hard_limit;
if (set_hard_limit)
mem_limit = hard_limit;
- if (virCompareLimitUlong(mem_limit, swap_limit) > 0) {
+ if (mem_limit > swap_limit) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("memory hard_limit tunable value must be lower "
"than or equal to swap_hard_limit"));
QEMU_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
/* set hard limit before swap hard limit if decreasing it */
- if (virCompareLimitUlong(vm->def->mem.hard_limit, hard_limit) > 0) {
+ if (vm->def->mem.hard_limit > hard_limit) {
QEMU_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
/* inhibit changing the limit a second time */
set_hard_limit = false;
switch (i) {
case 0: /* fill memory hard limit here */
value = persistentDef->mem.hard_limit;
- value = value ? value : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
VIR_TYPED_PARAM_ULLONG, value) < 0)
goto cleanup;
case 1: /* fill memory soft limit here */
value = persistentDef->mem.soft_limit;
- value = value ? value : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
VIR_TYPED_PARAM_ULLONG, value) < 0)
goto cleanup;
case 2: /* fill swap hard limit here */
value = persistentDef->mem.swap_hard_limit;
- value = value ? value : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
VIR_TYPED_PARAM_ULLONG, value) < 0)
goto cleanup;
* Kibibytes, but virProcessSetMaxMemLock expects the value in
* bytes.
*/
- memKB = vm->def->mem.hard_limit
+ memKB = virMemoryLimitIsSet(vm->def->mem.hard_limit)
? vm->def->mem.hard_limit
: vm->def->mem.max_balloon + (1024 * 1024);
virProcessSetMaxMemLock(vm->pid, memKB * 1024);
QEMU_MIGRATION_COOKIE_NBD)))
goto cleanup;
- if (STREQ_NULLABLE(protocol, "rdma") && !vm->def->mem.hard_limit) {
+ if (STREQ_NULLABLE(protocol, "rdma") &&
+ !virMemoryLimitIsSet(vm->def->mem.hard_limit)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot start RDMA migration with no memory hard "
"limit set"));
"with this QEMU binary"));
goto cleanup;
}
- if (!vm->def->mem.hard_limit) {
+ if (!virMemoryLimitIsSet(vm->def->mem.hard_limit)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot start RDMA migration with no memory hard "
"limit set"));
#endif /* __linux__ */
-/**
- * virCompareLimitUlong:
- *
- * Compare two unsigned long long numbers. Value '0' of the arguments has a
- * special meaning of 'unlimited' and thus greater than any other value.
- *
- * Returns 0 if the numbers are equal, -1 if b is greater, 1 if a is greater.
- */
-int
-virCompareLimitUlong(unsigned long long a, unsigned long long b)
-{
- if (a == b)
- return 0;
-
- if (!b)
- return -1;
-
- if (a == 0 || a > b)
- return 1;
-
- return -1;
-}
-
/**
* virParseOwnershipIds:
*
char *virFindFCHostCapableVport(const char *sysfs_prefix);
-int virCompareLimitUlong(unsigned long long a, unsigned long long b);
-
int virParseOwnershipIds(const char *label, uid_t *uidPtr, gid_t *gidPtr);
const char *virGetEnvBlockSUID(const char *name);
<currentMemory unit='KiB'>219136</currentMemory>
<memtune>
<hard_limit unit='KiB'>512000</hard_limit>
- <soft_limit unit='bytes'>131071999</soft_limit>
+ <soft_limit unit='bytes'>0</soft_limit>
<swap_hard_limit unit='KB'>1048576</swap_hard_limit>
</memtune>
<vcpu placement='static'>1</vcpu>
<currentMemory unit='KiB'>219136</currentMemory>
<memtune>
<hard_limit unit='KiB'>512000</hard_limit>
- <soft_limit unit='KiB'>128000</soft_limit>
+ <soft_limit unit='KiB'>0</soft_limit>
<swap_hard_limit unit='KiB'>1024000</swap_hard_limit>
</memtune>
<vcpu placement='static'>1</vcpu>