mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 19:41:16 +00:00
virnuma: Introduce virNumaSetPagePoolSize
This internal API can be used to allocate or free some pages in the huge pages pool. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
fa5c5580d6
commit
d1fd4a9b3b
@ -1719,6 +1719,7 @@ virNumaGetPageInfo;
|
|||||||
virNumaGetPages;
|
virNumaGetPages;
|
||||||
virNumaIsAvailable;
|
virNumaIsAvailable;
|
||||||
virNumaNodeIsAvailable;
|
virNumaNodeIsAvailable;
|
||||||
|
virNumaSetPagePoolSize;
|
||||||
virNumaSetupMemoryPolicy;
|
virNumaSetupMemoryPolicy;
|
||||||
|
|
||||||
|
|
||||||
|
@ -841,6 +841,102 @@ virNumaGetPages(int node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virNumaSetPagePoolSize(int node,
|
||||||
|
unsigned int page_size,
|
||||||
|
unsigned long long page_count,
|
||||||
|
bool add)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
char *nr_path = NULL, *nr_buf = NULL;
|
||||||
|
char *end;
|
||||||
|
unsigned long long nr_count;
|
||||||
|
|
||||||
|
if (page_size == sysconf(_SC_PAGESIZE) / 1024) {
|
||||||
|
/* Special case as kernel handles system pages
|
||||||
|
* differently to huge pages. */
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("system pages pool can't be modified"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virNumaGetHugePageInfoPath(&nr_path, node, page_size, "nr_hugepages") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Firstly check, if there's anything for us to do */
|
||||||
|
if (virFileReadAll(nr_path, 1024, &nr_buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virStrToLong_ull(nr_buf, &end, 10, &nr_count) < 0 ||
|
||||||
|
*end != '\n') {
|
||||||
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
_("invalid number '%s' in '%s'"),
|
||||||
|
nr_buf, nr_path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
if (!page_count) {
|
||||||
|
VIR_DEBUG("Nothing left to do: add = true page_count = 0");
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
page_count += nr_count;
|
||||||
|
} else {
|
||||||
|
if (nr_count == page_count) {
|
||||||
|
VIR_DEBUG("Nothing left to do: nr_count = page_count = %llu",
|
||||||
|
page_count);
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Okay, page pool adjustment must be done in two steps. In
|
||||||
|
* first we write the desired number into nr_hugepages file.
|
||||||
|
* Kernel then starts to allocate the pages (return from
|
||||||
|
* write should be postponed until the kernel is finished).
|
||||||
|
* However, kernel may have not been successful and reserved
|
||||||
|
* all the pages we wanted. So do the second read to check.
|
||||||
|
*/
|
||||||
|
VIR_FREE(nr_buf);
|
||||||
|
if (virAsprintf(&nr_buf, "%llu", page_count) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virFileWriteStr(nr_path, nr_buf, 0) < 0) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Unable to write to: %s"), nr_path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And now do the check. */
|
||||||
|
|
||||||
|
VIR_FREE(nr_buf);
|
||||||
|
if (virFileReadAll(nr_path, 1024, &nr_buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virStrToLong_ull(nr_buf, &end, 10, &nr_count) < 0 ||
|
||||||
|
*end != '\n') {
|
||||||
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
_("invalid number '%s' in '%s'"),
|
||||||
|
nr_buf, nr_path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr_count != page_count) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
_("Unable to allocate %llu pages. Allocated only %llu"),
|
||||||
|
page_count, nr_count);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(nr_buf);
|
||||||
|
VIR_FREE(nr_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#else /* #ifdef __linux__ */
|
#else /* #ifdef __linux__ */
|
||||||
int
|
int
|
||||||
virNumaGetPageInfo(int node ATTRIBUTE_UNUSED,
|
virNumaGetPageInfo(int node ATTRIBUTE_UNUSED,
|
||||||
@ -866,4 +962,16 @@ virNumaGetPages(int node ATTRIBUTE_UNUSED,
|
|||||||
_("page info is not supported on this platform"));
|
_("page info is not supported on this platform"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virNumaSetPagePoolSize(int node ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int page_size ATTRIBUTE_UNUSED,
|
||||||
|
unsigned long long page_count ATTRIBUTE_UNUSED,
|
||||||
|
bool add ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("page pool allocation is not supported on this platform"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#endif /* #ifdef __linux__ */
|
#endif /* #ifdef __linux__ */
|
||||||
|
@ -59,4 +59,8 @@ int virNumaGetPages(int node,
|
|||||||
unsigned int **pages_free,
|
unsigned int **pages_free,
|
||||||
size_t *npages)
|
size_t *npages)
|
||||||
ATTRIBUTE_NONNULL(5);
|
ATTRIBUTE_NONNULL(5);
|
||||||
|
int virNumaSetPagePoolSize(int node,
|
||||||
|
unsigned int page_size,
|
||||||
|
unsigned long long page_count,
|
||||||
|
bool add);
|
||||||
#endif /* __VIR_NUMA_H__ */
|
#endif /* __VIR_NUMA_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user