[libvirt] [PATCH v3 00/11] Introduce worker tuning APIs

since v2: - all getters are now protected by threadpool mutex to prevent torn reads in concurrent execution - some checks in adminDispatchServerGetThreadpoolParameters were redundant, thus were optimizes out - fixed memory leak in adminDispatchServerGetThreadpoolParameters when allocating a newlist although typed params serialization already does that - fixed some cosmetic issues like exporting a function prototype one patch earlier than it should actually be introduced - a mistake that got there by interactive rebase Erik Skultety (11): po: Fix record ordering in POTFILES.in libvirt-host: Move virTypedParam* to libvirt-common admin: Enable usage of typed parameters util: Refactor thread creation by introducing virThreadPoolExpand util: Report system error when virThreadCreateFull fails util: Use a mutex when retrieving threadpool data util: Add more getters to threadpool parameters admin: Prepare admin protocol for future worker related procedures admin: Introduce virAdmServerGethreadPoolParameters admin: Introduce virAdmServerSetThreadPoolParameters virt-admin: Introduce srv-workertune command cfg.mk | 2 +- daemon/admin.c | 88 +++++++++++++ daemon/admin_server.c | 110 +++++++++++++++++ daemon/admin_server.h | 11 ++ include/libvirt/libvirt-admin.h | 71 +++++++++++ include/libvirt/libvirt-common.h.in | 185 ++++++++++++++++++++++++++++ include/libvirt/libvirt-host.h | 186 ---------------------------- po/POTFILES.in | 4 +- src/admin/admin_protocol.x | 54 +++++++- src/admin/admin_remote.c | 77 ++++++++++++ src/admin_protocol-structs | 45 +++++++ src/libvirt-admin.c | 83 +++++++++++++ src/libvirt_admin_private.syms | 3 + src/libvirt_admin_public.syms | 2 + src/libvirt_private.syms | 4 + src/rpc/virnetserver.c | 37 ++++++ src/rpc/virnetserver.h | 13 ++ src/util/virthreadpool.c | 238 +++++++++++++++++++++++++----------- src/util/virthreadpool.h | 8 ++ tools/virt-admin.c | 132 ++++++++++++++++++++ 20 files changed, 1096 insertions(+), 257 deletions(-) -- 2.4.11

Commit a474371f broke ordering of the records. Now if a file required for translation is missing, syntax-check (po-check) will fail and suggest a patch to add the missing file. However, if the ordering is broken, the patch will be understandably inapplicable (cleanly), since the diff isn't against the actual POTFILES.in as is, but against POTFILES.in as it should look like with the required file missing instead. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- po/POTFILES.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 0d7f9f9..5316d4f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,5 +1,5 @@ -daemon/admin_dispatch.h daemon/admin.c +daemon/admin_dispatch.h daemon/libvirtd-config.c daemon/libvirtd.c daemon/qemu_dispatch.h -- 2.4.11

Commits 0472cef6, 9afc115f, 8cd1d546 exported typed params handlers internally, but a commit which would move the public definition from libvirt-host to libvirt-common was missing. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- include/libvirt/libvirt-common.h.in | 185 +++++++++++++++++++++++++++++++++++ include/libvirt/libvirt-host.h | 186 ------------------------------------ 2 files changed, 185 insertions(+), 186 deletions(-) diff --git a/include/libvirt/libvirt-common.h.in b/include/libvirt/libvirt-common.h.in index efbb91b..772e40f 100644 --- a/include/libvirt/libvirt-common.h.in +++ b/include/libvirt/libvirt-common.h.in @@ -120,6 +120,191 @@ typedef enum { # endif } virConnectCloseReason; +/** + * virTypedParameterType: + * + * Express the type of a virTypedParameter + */ +typedef enum { + VIR_TYPED_PARAM_INT = 1, /* integer case */ + VIR_TYPED_PARAM_UINT = 2, /* unsigned integer case */ + VIR_TYPED_PARAM_LLONG = 3, /* long long case */ + VIR_TYPED_PARAM_ULLONG = 4, /* unsigned long long case */ + VIR_TYPED_PARAM_DOUBLE = 5, /* double case */ + VIR_TYPED_PARAM_BOOLEAN = 6, /* boolean(character) case */ + VIR_TYPED_PARAM_STRING = 7, /* string case */ + +# ifdef VIR_ENUM_SENTINELS + VIR_TYPED_PARAM_LAST +# endif +} virTypedParameterType; + +/** + * virTypedParameterFlags: + * + * Flags related to libvirt APIs that use virTypedParameter. + * + * These enums should not conflict with those of virDomainModificationImpact. + */ +typedef enum { + /* 1 << 0 is reserved for virDomainModificationImpact */ + /* 1 << 1 is reserved for virDomainModificationImpact */ + + /* Older servers lacked the ability to handle string typed + * parameters. Attempts to set a string parameter with an older + * server will fail at the client, but attempts to retrieve + * parameters must not return strings from a new server to an + * older client, so this flag exists to identify newer clients to + * newer servers. This flag is automatically set when needed, so + * the user does not have to worry about it; however, manually + * setting the flag can be used to reject servers that cannot + * return typed strings, even if no strings would be returned. + */ + VIR_TYPED_PARAM_STRING_OKAY = 1 << 2, + +} virTypedParameterFlags; + +/** + * VIR_TYPED_PARAM_FIELD_LENGTH: + * + * Macro providing the field length of virTypedParameter name + */ +# define VIR_TYPED_PARAM_FIELD_LENGTH 80 + +/** + * virTypedParameter: + * + * A named parameter, including a type and value. + * + * The types virSchedParameter, virBlkioParameter, and + * virMemoryParameter are aliases of this type, for use when + * targeting libvirt earlier than 0.9.2. + */ +typedef struct _virTypedParameter virTypedParameter; + +struct _virTypedParameter { + char field[VIR_TYPED_PARAM_FIELD_LENGTH]; /* parameter name */ + int type; /* parameter type, virTypedParameterType */ + union { + int i; /* type is INT */ + unsigned int ui; /* type is UINT */ + long long int l; /* type is LLONG */ + unsigned long long int ul; /* type is ULLONG */ + double d; /* type is DOUBLE */ + char b; /* type is BOOLEAN */ + char *s; /* type is STRING, may not be NULL */ + } value; /* parameter value */ +}; + +/** + * virTypedParameterPtr: + * + * a pointer to a virTypedParameter structure. + */ +typedef virTypedParameter *virTypedParameterPtr; + + +virTypedParameterPtr +virTypedParamsGet (virTypedParameterPtr params, + int nparams, + const char *name); +int +virTypedParamsGetInt (virTypedParameterPtr params, + int nparams, + const char *name, + int *value); +int +virTypedParamsGetUInt (virTypedParameterPtr params, + int nparams, + const char *name, + unsigned int *value); +int +virTypedParamsGetLLong (virTypedParameterPtr params, + int nparams, + const char *name, + long long *value); +int +virTypedParamsGetULLong (virTypedParameterPtr params, + int nparams, + const char *name, + unsigned long long *value); +int +virTypedParamsGetDouble (virTypedParameterPtr params, + int nparams, + const char *name, + double *value); +int +virTypedParamsGetBoolean(virTypedParameterPtr params, + int nparams, + const char *name, + int *value); +int +virTypedParamsGetString (virTypedParameterPtr params, + int nparams, + const char *name, + const char **value); +int +virTypedParamsAddInt (virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + int value); +int +virTypedParamsAddUInt (virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + unsigned int value); +int +virTypedParamsAddLLong (virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + long long value); +int +virTypedParamsAddULLong (virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + unsigned long long value); +int +virTypedParamsAddDouble (virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + double value); +int +virTypedParamsAddBoolean(virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + int value); +int +virTypedParamsAddString (virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + const char *value); +int +virTypedParamsAddStringList(virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + const char **values); +int +virTypedParamsAddFromString(virTypedParameterPtr *params, + int *nparams, + int *maxparams, + const char *name, + int type, + const char *value); +void +virTypedParamsClear (virTypedParameterPtr params, + int nparams); +void +virTypedParamsFree (virTypedParameterPtr params, + int nparams); + # ifdef __cplusplus } # endif diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h index 8786fbb..07b5d15 100644 --- a/include/libvirt/libvirt-host.h +++ b/include/libvirt/libvirt-host.h @@ -140,192 +140,6 @@ struct _virSecurityModel { */ typedef virSecurityModel *virSecurityModelPtr; -/* Common data types shared among interfaces with name/type/value lists. */ - -/** - * virTypedParameterType: - * - * Express the type of a virTypedParameter - */ -typedef enum { - VIR_TYPED_PARAM_INT = 1, /* integer case */ - VIR_TYPED_PARAM_UINT = 2, /* unsigned integer case */ - VIR_TYPED_PARAM_LLONG = 3, /* long long case */ - VIR_TYPED_PARAM_ULLONG = 4, /* unsigned long long case */ - VIR_TYPED_PARAM_DOUBLE = 5, /* double case */ - VIR_TYPED_PARAM_BOOLEAN = 6, /* boolean(character) case */ - VIR_TYPED_PARAM_STRING = 7, /* string case */ - -# ifdef VIR_ENUM_SENTINELS - VIR_TYPED_PARAM_LAST -# endif -} virTypedParameterType; - -/** - * virTypedParameterFlags: - * - * Flags related to libvirt APIs that use virTypedParameter. - * - * These enums should not conflict with those of virDomainModificationImpact. - */ -typedef enum { - /* 1 << 0 is reserved for virDomainModificationImpact */ - /* 1 << 1 is reserved for virDomainModificationImpact */ - - /* Older servers lacked the ability to handle string typed - * parameters. Attempts to set a string parameter with an older - * server will fail at the client, but attempts to retrieve - * parameters must not return strings from a new server to an - * older client, so this flag exists to identify newer clients to - * newer servers. This flag is automatically set when needed, so - * the user does not have to worry about it; however, manually - * setting the flag can be used to reject servers that cannot - * return typed strings, even if no strings would be returned. - */ - VIR_TYPED_PARAM_STRING_OKAY = 1 << 2, - -} virTypedParameterFlags; - -/** - * VIR_TYPED_PARAM_FIELD_LENGTH: - * - * Macro providing the field length of virTypedParameter name - */ -# define VIR_TYPED_PARAM_FIELD_LENGTH 80 - -/** - * virTypedParameter: - * - * A named parameter, including a type and value. - * - * The types virSchedParameter, virBlkioParameter, and - * virMemoryParameter are aliases of this type, for use when - * targeting libvirt earlier than 0.9.2. - */ -typedef struct _virTypedParameter virTypedParameter; - -struct _virTypedParameter { - char field[VIR_TYPED_PARAM_FIELD_LENGTH]; /* parameter name */ - int type; /* parameter type, virTypedParameterType */ - union { - int i; /* type is INT */ - unsigned int ui; /* type is UINT */ - long long int l; /* type is LLONG */ - unsigned long long int ul; /* type is ULLONG */ - double d; /* type is DOUBLE */ - char b; /* type is BOOLEAN */ - char *s; /* type is STRING, may not be NULL */ - } value; /* parameter value */ -}; - -/** - * virTypedParameterPtr: - * - * a pointer to a virTypedParameter structure. - */ -typedef virTypedParameter *virTypedParameterPtr; - - -virTypedParameterPtr -virTypedParamsGet (virTypedParameterPtr params, - int nparams, - const char *name); -int -virTypedParamsGetInt (virTypedParameterPtr params, - int nparams, - const char *name, - int *value); -int -virTypedParamsGetUInt (virTypedParameterPtr params, - int nparams, - const char *name, - unsigned int *value); -int -virTypedParamsGetLLong (virTypedParameterPtr params, - int nparams, - const char *name, - long long *value); -int -virTypedParamsGetULLong (virTypedParameterPtr params, - int nparams, - const char *name, - unsigned long long *value); -int -virTypedParamsGetDouble (virTypedParameterPtr params, - int nparams, - const char *name, - double *value); -int -virTypedParamsGetBoolean(virTypedParameterPtr params, - int nparams, - const char *name, - int *value); -int -virTypedParamsGetString (virTypedParameterPtr params, - int nparams, - const char *name, - const char **value); -int -virTypedParamsAddInt (virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - int value); -int -virTypedParamsAddUInt (virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - unsigned int value); -int -virTypedParamsAddLLong (virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - long long value); -int -virTypedParamsAddULLong (virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - unsigned long long value); -int -virTypedParamsAddDouble (virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - double value); -int -virTypedParamsAddBoolean(virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - int value); -int -virTypedParamsAddString (virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - const char *value); -int -virTypedParamsAddStringList(virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - const char **values); -int -virTypedParamsAddFromString(virTypedParameterPtr *params, - int *nparams, - int *maxparams, - const char *name, - int type, - const char *value); -void -virTypedParamsClear (virTypedParameterPtr params, - int nparams); -void -virTypedParamsFree (virTypedParameterPtr params, - int nparams); /* data types related to virNodePtr */ -- 2.4.11

Make all relevant changes to admin protocol, in order to achieve $(subj) Signed-off-by: Erik Skultety <eskultet@redhat.com> --- cfg.mk | 2 +- src/admin/admin_protocol.x | 24 ++++++++++++++++++++++++ src/admin_protocol-structs | 25 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/cfg.mk b/cfg.mk index 8e8586f..61397e8 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1227,7 +1227,7 @@ exclude_file_name_regexp--sc_prohibit_include_public_headers_brackets = \ ^(tools/|examples/|include/libvirt/(virterror|libvirt(-(admin|qemu|lxc))?)\.h$$) exclude_file_name_regexp--sc_prohibit_int_ijk = \ - ^(src/remote_protocol-structs|src/remote/remote_protocol.x|cfg.mk|include/)$ + ^(src/remote_protocol-structs|src/remote/remote_protocol.x|cfg.mk|include/|src/admin_protocol-structs|src/admin/admin_protocol.x)$ exclude_file_name_regexp--sc_prohibit_getenv = \ ^tests/.*\.[ch]$$ diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index 6590980..57dbb6b 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -22,6 +22,7 @@ * Author: Martin Kletzander <mkletzan@redhat.com> */ +%#include <libvirt/libvirt-admin.h> %#include "virxdrdefs.h" /*----- Data types. -----*/ @@ -41,12 +42,35 @@ typedef string admin_nonnull_string<ADMIN_STRING_MAX>; /* A long string, which may be NULL. */ typedef admin_nonnull_string *admin_string; +union admin_typed_param_value switch (int type) { + case VIR_TYPED_PARAM_INT: + int i; + case VIR_TYPED_PARAM_UINT: + unsigned int ui; + case VIR_TYPED_PARAM_LLONG: + hyper l; + case VIR_TYPED_PARAM_ULLONG: + unsigned hyper ul; + case VIR_TYPED_PARAM_DOUBLE: + double d; + case VIR_TYPED_PARAM_BOOLEAN: + int b; + case VIR_TYPED_PARAM_STRING: + admin_nonnull_string s; +}; + +struct admin_typed_param { + admin_nonnull_string field; + admin_typed_param_value value; +}; + /* A server which may NOT be NULL */ struct admin_nonnull_server { admin_nonnull_string name; }; /*----- Protocol. -----*/ + struct admin_connect_open_args { unsigned int flags; }; diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index d8aca06..26c8443 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -1,4 +1,29 @@ /* -*- c -*- */ +enum { + VIR_TYPED_PARAM_INT = 1, + VIR_TYPED_PARAM_UINT = 2, + VIR_TYPED_PARAM_LLONG = 3, + VIR_TYPED_PARAM_ULLONG = 4, + VIR_TYPED_PARAM_DOUBLE = 5, + VIR_TYPED_PARAM_BOOLEAN = 6, + VIR_TYPED_PARAM_STRING = 7, +}; +struct admin_typed_param_value { + int type; + union { + int i; + u_int ui; + int64_t l; + uint64_t ul; + double d; + int b; + admin_nonnull_string s; + } admin_typed_param_value_u; +}; +struct admin_typed_param { + admin_nonnull_string field; + admin_typed_param_value value; +}; struct admin_nonnull_server { admin_nonnull_string name; }; -- 2.4.11

When either creating a threadpool, or creating a new thread to accomplish a job that had been placed into the jobqueue, every time thread-specific data need to be allocated, threadpool needs to be (re)-allocated and thread count indicators updated. Make the code clearer to read by compressing these operations into a more complex one. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- src/util/virthreadpool.c | 109 +++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 65 deletions(-) diff --git a/src/util/virthreadpool.c b/src/util/virthreadpool.c index f640448..8af4ec0 100644 --- a/src/util/virthreadpool.c +++ b/src/util/virthreadpool.c @@ -157,6 +157,43 @@ static void virThreadPoolWorker(void *opaque) virMutexUnlock(&pool->mutex); } +static int +virThreadPoolExpand(virThreadPoolPtr pool, size_t gain, bool priority) +{ + virThreadPtr workers = priority ? pool->prioWorkers : pool->workers; + size_t *curWorkers = priority ? &pool->nPrioWorkers : &pool->nWorkers; + size_t i = 0; + struct virThreadPoolWorkerData *data = NULL; + + if (VIR_EXPAND_N(workers, *curWorkers, gain) < 0) + return -1; + + for (i = 0; i < gain; i++) { + if (VIR_ALLOC(data) < 0) + goto error; + + data->pool = pool; + data->cond = priority ? &pool->prioCond : &pool->cond; + data->priority = priority; + + if (virThreadCreateFull(&workers[i], + false, + virThreadPoolWorker, + pool->jobFuncName, + true, + data) < 0) { + VIR_FREE(data); + goto error; + } + } + + return 0; + + error: + *curWorkers -= gain - i; + return -1; +} + virThreadPoolPtr virThreadPoolNewFull(size_t minWorkers, size_t maxWorkers, @@ -166,8 +203,6 @@ virThreadPoolNewFull(size_t minWorkers, void *opaque) { virThreadPoolPtr pool; - size_t i; - struct virThreadPoolWorkerData *data = NULL; if (minWorkers > maxWorkers) minWorkers = maxWorkers; @@ -188,58 +223,23 @@ virThreadPoolNewFull(size_t minWorkers, if (virCondInit(&pool->quit_cond) < 0) goto error; - if (VIR_ALLOC_N(pool->workers, minWorkers) < 0) - goto error; - pool->minWorkers = minWorkers; pool->maxWorkers = maxWorkers; - for (i = 0; i < minWorkers; i++) { - if (VIR_ALLOC(data) < 0) - goto error; - data->pool = pool; - data->cond = &pool->cond; - - if (virThreadCreateFull(&pool->workers[i], - false, - virThreadPoolWorker, - pool->jobFuncName, - true, - data) < 0) { - goto error; - } - pool->nWorkers++; - } + if (virThreadPoolExpand(pool, minWorkers, false) < 0) + goto error; if (prioWorkers) { if (virCondInit(&pool->prioCond) < 0) goto error; - if (VIR_ALLOC_N(pool->prioWorkers, prioWorkers) < 0) - goto error; - for (i = 0; i < prioWorkers; i++) { - if (VIR_ALLOC(data) < 0) - goto error; - data->pool = pool; - data->cond = &pool->prioCond; - data->priority = true; - - if (virThreadCreateFull(&pool->prioWorkers[i], - false, - virThreadPoolWorker, - pool->jobFuncName, - true, - data) < 0) { - goto error; - } - pool->nPrioWorkers++; - } + if (virThreadPoolExpand(pool, prioWorkers, true) < 0) + goto error; } return pool; error: - VIR_FREE(data); virThreadPoolFree(pool); return NULL; @@ -307,36 +307,15 @@ int virThreadPoolSendJob(virThreadPoolPtr pool, void *jobData) { virThreadPoolJobPtr job; - struct virThreadPoolWorkerData *data = NULL; virMutexLock(&pool->mutex); if (pool->quit) goto error; if (pool->freeWorkers - pool->jobQueueDepth <= 0 && - pool->nWorkers < pool->maxWorkers) { - if (VIR_EXPAND_N(pool->workers, pool->nWorkers, 1) < 0) - goto error; - - if (VIR_ALLOC(data) < 0) { - pool->nWorkers--; - goto error; - } - - data->pool = pool; - data->cond = &pool->cond; - - if (virThreadCreateFull(&pool->workers[pool->nWorkers - 1], - false, - virThreadPoolWorker, - pool->jobFuncName, - true, - data) < 0) { - VIR_FREE(data); - pool->nWorkers--; - goto error; - } - } + pool->nWorkers < pool->maxWorkers && + virThreadPoolExpand(pool, 1, false) < 0) + goto error; if (VIR_ALLOC(job) < 0) goto error; -- 2.4.11

Otherwise 'Unknown' error will be returned to client. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- po/POTFILES.in | 1 + src/util/virthreadpool.c | 1 + 2 files changed, 2 insertions(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 5316d4f..6d720c0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -238,6 +238,7 @@ src/util/virstoragefile.c src/util/virstring.c src/util/virsysinfo.c src/util/virthreadjob.c +src/util/virthreadpool.c src/util/virtime.c src/util/virtpm.c src/util/virtypedparam.c diff --git a/src/util/virthreadpool.c b/src/util/virthreadpool.c index 8af4ec0..e2e9fe4 100644 --- a/src/util/virthreadpool.c +++ b/src/util/virthreadpool.c @@ -183,6 +183,7 @@ virThreadPoolExpand(virThreadPoolPtr pool, size_t gain, bool priority) true, data) < 0) { VIR_FREE(data); + virReportSystemError(errno, "%s", _("Failed to create thread")); goto error; } } -- 2.4.11

So far, the values the affected getters retrieve are static, i.e. there's no way of changing them during runtime. But admin interface will later enable not only getting but changing them as well. So to prevent phenomenons like torn reads or concurrent reads and writes of unaligned values, use mutual exclusion when getting these values (writes do, understandably, use them already). Signed-off-by: Erik Skultety <eskultet@redhat.com> --- src/util/virthreadpool.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/util/virthreadpool.c b/src/util/virthreadpool.c index e2e9fe4..7ceb090 100644 --- a/src/util/virthreadpool.c +++ b/src/util/virthreadpool.c @@ -286,17 +286,35 @@ void virThreadPoolFree(virThreadPoolPtr pool) size_t virThreadPoolGetMinWorkers(virThreadPoolPtr pool) { - return pool->minWorkers; + size_t ret; + + virMutexLock(&pool->mutex); + ret = pool->minWorkers; + virMutexUnlock(&pool->mutex); + + return ret; } size_t virThreadPoolGetMaxWorkers(virThreadPoolPtr pool) { - return pool->maxWorkers; + size_t ret; + + virMutexLock(&pool->mutex); + ret = pool->maxWorkers; + virMutexUnlock(&pool->mutex); + + return ret; } size_t virThreadPoolGetPriorityWorkers(virThreadPoolPtr pool) { - return pool->nPrioWorkers; + size_t ret; + + virMutexLock(&pool->mutex); + ret = pool->nPrioWorkers; + virMutexUnlock(&pool->mutex); + + return ret; } /* -- 2.4.11

In order for the client to see all thread counts and limits, current total and free worker count getters need to be introduced. Client might also be interested in the job queue length, so provide a getter for that too. As with the other getters, preparing for the admin interface, mutual exclusion is used within all getters. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- src/libvirt_private.syms | 3 +++ src/util/virthreadpool.c | 33 +++++++++++++++++++++++++++++++++ src/util/virthreadpool.h | 3 +++ 3 files changed, 39 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 684f06c..e9a2bce 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2347,6 +2347,9 @@ virThreadJobSetWorker; # util/virthreadpool.h virThreadPoolFree; +virThreadPoolGetCurrentWorkers; +virThreadPoolGetFreeWorkers; +virThreadPoolGetJobQueueDepth; virThreadPoolGetMaxWorkers; virThreadPoolGetMinWorkers; virThreadPoolGetPriorityWorkers; diff --git a/src/util/virthreadpool.c b/src/util/virthreadpool.c index 7ceb090..fec8620 100644 --- a/src/util/virthreadpool.c +++ b/src/util/virthreadpool.c @@ -317,6 +317,39 @@ size_t virThreadPoolGetPriorityWorkers(virThreadPoolPtr pool) return ret; } +size_t virThreadPoolGetCurrentWorkers(virThreadPoolPtr pool) +{ + size_t ret; + + virMutexLock(&pool->mutex); + ret = pool->nWorkers; + virMutexUnlock(&pool->mutex); + + return ret; +} + +size_t virThreadPoolGetFreeWorkers(virThreadPoolPtr pool) +{ + size_t ret; + + virMutexLock(&pool->mutex); + ret = pool->freeWorkers; + virMutexUnlock(&pool->mutex); + + return ret; +} + +size_t virThreadPoolGetJobQueueDepth(virThreadPoolPtr pool) +{ + size_t ret; + + virMutexLock(&pool->mutex); + ret = pool->jobQueueDepth; + virMutexUnlock(&pool->mutex); + + return ret; +} + /* * @priority - job priority * Return: 0 on success, -1 otherwise diff --git a/src/util/virthreadpool.h b/src/util/virthreadpool.h index 538b62f..bc0c907 100644 --- a/src/util/virthreadpool.h +++ b/src/util/virthreadpool.h @@ -46,6 +46,9 @@ virThreadPoolPtr virThreadPoolNewFull(size_t minWorkers, size_t virThreadPoolGetMinWorkers(virThreadPoolPtr pool); size_t virThreadPoolGetMaxWorkers(virThreadPoolPtr pool); size_t virThreadPoolGetPriorityWorkers(virThreadPoolPtr pool); +size_t virThreadPoolGetCurrentWorkers(virThreadPoolPtr pool); +size_t virThreadPoolGetFreeWorkers(virThreadPoolPtr pool); +size_t virThreadPoolGetJobQueueDepth(virThreadPoolPtr pool); void virThreadPoolFree(virThreadPoolPtr pool); -- 2.4.11

Before any getter or setter methods can be introduced, first specify a set of public attributes/flags that these methods will be compatible with. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- include/libvirt/libvirt-admin.h | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index 25bcbf4..35849b1 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -110,6 +110,66 @@ virAdmServerPtr virAdmConnectLookupServer(virAdmConnectPtr conn, const char *name, unsigned int flags); +/* Manage threadpool attributes */ + +/** + * VIR_THREADPOOL_WORKERS_MIN: + * Macro for the threadpool minWorkers limit: represents the bottom limit to + * number of active workers in threadpool, as uint. + */ + +# define VIR_THREADPOOL_WORKERS_MIN "minWorkers" + +/** + * VIR_THREADPOOL_WORKERS_MAX: + * Macro for the threadpool maxWorkers limit: represents the upper limit to + * number of active workers in threadpool, as uint. The value of this limit has + * to be greater than VIR_THREADPOOL_WORKERS_MIN at all times. + */ + +# define VIR_THREADPOOL_WORKERS_MAX "maxWorkers" + +/** + * VIR_THREADPOOL_WORKERS_PRIORITY: + * Macro for the threadpool nPrioWorkers attribute: represents the current number + * of active priority workers in threadpool, as uint. + */ + +# define VIR_THREADPOOL_WORKERS_PRIORITY "prioWorkers" + +/** + * VIR_THREADPOOL_WORKERS_FREE: + * Macro for the threadpool freeWorkers attribute: represents the current number + * of free workers available to accomplish a job, as uint. + * + * NOTE: This attribute is read-only and any attempt to set it will be denied + * by daemon + */ + +# define VIR_THREADPOOL_WORKERS_FREE "freeWorkers" + +/** + * VIR_THREADPOOL_WORKERS_CURRENT: + * Macro for the threadpool nWorkers attribute: represents the current number + * of active ordinary workers in threadpool, as uint. + * + * NOTE: This attribute is read-only and any attempt to set it will be denied + * by daemon + */ + +# define VIR_THREADPOOL_WORKERS_CURRENT "nWorkers" + +/** + * VIR_THREADPOOL_JOB_QUEUE_DEPTH: + * Macro for the threadpool jobQueueDepth attribute: represents the current + * number of jobs waiting in a queue to be processed, as uint. + * + * NOTE: This attribute is read-only and any attempt to set it will be denied + * by daemon + */ + +# define VIR_THREADPOOL_JOB_QUEUE_DEPTH "jobQueueDepth" + # ifdef __cplusplus } # endif -- 2.4.11

New API to retrieve current server workerpool specs. Since it uses typed parameters, more specs to retrieve can be further included in the pool of supported ones. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- daemon/admin.c | 45 +++++++++++++++++++++++++++ daemon/admin_server.c | 67 +++++++++++++++++++++++++++++++++++++++++ daemon/admin_server.h | 6 ++++ include/libvirt/libvirt-admin.h | 6 ++++ po/POTFILES.in | 1 + src/admin/admin_protocol.x | 19 +++++++++++- src/admin/admin_remote.c | 43 ++++++++++++++++++++++++++ src/admin_protocol-structs | 11 +++++++ src/libvirt-admin.c | 46 ++++++++++++++++++++++++++++ src/libvirt_admin_private.syms | 2 ++ src/libvirt_admin_public.syms | 1 + src/rpc/virnetserver.c | 22 ++++++++++++++ src/rpc/virnetserver.h | 8 +++++ 13 files changed, 276 insertions(+), 1 deletion(-) diff --git a/daemon/admin.c b/daemon/admin.c index 3169cdd..530f6bf 100644 --- a/daemon/admin.c +++ b/daemon/admin.c @@ -37,6 +37,7 @@ #include "virnetserver.h" #include "virstring.h" #include "virthreadjob.h" +#include "virtypedparam.h" #define VIR_FROM_THIS VIR_FROM_ADMIN @@ -133,4 +134,48 @@ adminConnectGetLibVersion(virNetDaemonPtr dmn ATTRIBUTE_UNUSED, return 0; } +static int +adminDispatchServerGetThreadpoolParameters(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + struct admin_server_get_threadpool_parameters_args *args, + struct admin_server_get_threadpool_parameters_ret *ret) +{ + int rv = -1; + virNetServerPtr srv = NULL; + virTypedParameterPtr params = NULL; + int nparams = 0; + struct daemonAdmClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!(srv = virNetDaemonGetServer(priv->dmn, args->server.name))) + goto cleanup; + + if (adminDaemonGetThreadPoolParameters(srv, ¶ms, &nparams, + args->flags) < 0) + goto cleanup; + + if (nparams > ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of threadpool parameters %d exceeds max " + "allowed limit: %d"), nparams, + ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX); + goto cleanup; + } + + if (virTypedParamsSerialize(params, nparams, + (virTypedParameterRemotePtr *) &ret->params.params_val, + &ret->params.params_len, 0) < 0) + goto cleanup; + + rv = 0; + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + + virTypedParamsFree(params, nparams); + virObjectUnref(srv); + return rv; +} #include "admin_dispatch.h" diff --git a/daemon/admin_server.c b/daemon/admin_server.c index 1d30ea5..e7d48b8 100644 --- a/daemon/admin_server.c +++ b/daemon/admin_server.c @@ -31,6 +31,7 @@ #include "virnetdaemon.h" #include "virnetserver.h" #include "virstring.h" +#include "virthreadpool.h" #define VIR_FROM_THIS VIR_FROM_ADMIN @@ -68,3 +69,69 @@ adminConnectLookupServer(virNetDaemonPtr dmn, return virNetDaemonGetServer(dmn, name); } + +int +adminDaemonGetThreadPoolParameters(virNetServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + int ret = -1; + int maxparams = 0; + size_t minWorkers; + size_t maxWorkers; + size_t nWorkers; + size_t freeWorkers; + size_t nPrioWorkers; + size_t jobQueueDepth; + virTypedParameterPtr tmpparams = NULL; + + virCheckFlags(0, -1); + + if (virNetServerGetThreadPoolParameters(srv, &minWorkers, &maxWorkers, + &nWorkers, &freeWorkers, + &nPrioWorkers, + &jobQueueDepth) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to retrieve threadpool parameters")); + goto cleanup; + } + + if (virTypedParamsAddUInt(&tmpparams, nparams, + &maxparams, VIR_THREADPOOL_WORKERS_MIN, + minWorkers) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, + &maxparams, VIR_THREADPOOL_WORKERS_MAX, + maxWorkers) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, + &maxparams, VIR_THREADPOOL_WORKERS_CURRENT, + nWorkers) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, + &maxparams, VIR_THREADPOOL_WORKERS_FREE, + freeWorkers) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, + &maxparams, VIR_THREADPOOL_WORKERS_PRIORITY, + nPrioWorkers) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&tmpparams, nparams, + &maxparams, VIR_THREADPOOL_JOB_QUEUE_DEPTH, + jobQueueDepth) < 0) + goto cleanup; + + *params = tmpparams; + tmpparams = NULL; + ret = 0; + + cleanup: + virTypedParamsFree(tmpparams, *nparams); + return ret; +} diff --git a/daemon/admin_server.h b/daemon/admin_server.h index 9d0adf0..7aa7727 100644 --- a/daemon/admin_server.h +++ b/daemon/admin_server.h @@ -35,4 +35,10 @@ virNetServerPtr adminConnectLookupServer(virNetDaemonPtr dmn, const char *name, unsigned int flags); +int +adminDaemonGetThreadPoolParameters(virNetServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags); + #endif /* __LIBVIRTD_ADMIN_SERVER_H__ */ diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index 35849b1..39c2c02 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -170,6 +170,12 @@ virAdmServerPtr virAdmConnectLookupServer(virAdmConnectPtr conn, # define VIR_THREADPOOL_JOB_QUEUE_DEPTH "jobQueueDepth" +/* Tunables for a server workerpool */ +int virAdmServerGetThreadPoolParameters(virAdmServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/po/POTFILES.in b/po/POTFILES.in index 6d720c0..902d936 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,5 +1,6 @@ daemon/admin.c daemon/admin_dispatch.h +daemon/admin_server.c daemon/libvirtd-config.c daemon/libvirtd.c daemon/qemu_dispatch.h diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index 57dbb6b..46b1b5c 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -36,6 +36,9 @@ const ADMIN_STRING_MAX = 4194304; /* Upper limit on list of servers */ const ADMIN_SERVER_LIST_MAX = 16384; +/* Upper limit on number of threadpool parameters */ +const ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX = 32; + /* A long string, which may NOT be NULL. */ typedef string admin_nonnull_string<ADMIN_STRING_MAX>; @@ -98,6 +101,15 @@ struct admin_connect_lookup_server_ret { admin_nonnull_server srv; }; +struct admin_server_get_threadpool_parameters_args { + admin_nonnull_server server; + unsigned int flags; +}; + +struct admin_server_get_threadpool_parameters_ret { + admin_typed_param params<ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX>; +}; + /* Define the program number, protocol version and procedure numbers here. */ const ADMIN_PROGRAM = 0x06900690; const ADMIN_PROTOCOL_VERSION = 1; @@ -143,5 +155,10 @@ enum admin_procedure { /** * @generate: both */ - ADMIN_PROC_CONNECT_LOOKUP_SERVER = 5 + ADMIN_PROC_CONNECT_LOOKUP_SERVER = 5, + + /** + * @generate: none + */ + ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6 }; diff --git a/src/admin/admin_remote.c b/src/admin/admin_remote.c index 21e0dd3..64942e7 100644 --- a/src/admin/admin_remote.c +++ b/src/admin/admin_remote.c @@ -22,6 +22,7 @@ #include <config.h> #include <rpc/rpc.h> +#include "virtypedparam.h" #include "admin_protocol.h" typedef struct _remoteAdminPriv remoteAdminPriv; @@ -54,6 +55,11 @@ get_nonnull_server(virAdmConnectPtr conn, admin_nonnull_server server) return virAdmGetServer(conn, server.name); } +static void +make_nonnull_server(admin_nonnull_server *srv_dst, virAdmServerPtr srv_src) +{ + srv_dst->name = srv_src->name; +} static int callFull(virAdmConnectPtr conn ATTRIBUTE_UNUSED, @@ -224,3 +230,40 @@ remoteAdminPrivNew(const char *sock_path) virObjectUnref(priv); return NULL; } + +static int +remoteAdminServerGetThreadPoolParameters(virAdmServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + int rv = -1; + remoteAdminPrivPtr priv = srv->conn->privateData; + admin_server_get_threadpool_parameters_args args; + admin_server_get_threadpool_parameters_ret ret; + + args.flags = flags; + make_nonnull_server(&args.server, srv); + + memset(&ret, 0, sizeof(ret)); + virObjectLock(priv); + + if (call(srv->conn, 0, ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS, + (xdrproc_t)xdr_admin_server_get_threadpool_parameters_args, (char *) &args, + (xdrproc_t)xdr_admin_server_get_threadpool_parameters_ret, (char *) &ret) == -1) + goto cleanup; + + if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val, + ret.params.params_len, + ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX, + params, + nparams) < 0) + goto cleanup; + + rv = 0; + xdr_free((xdrproc_t)xdr_admin_server_get_threadpool_parameters_ret, (char *) &ret); + + cleanup: + virObjectUnlock(priv); + return rv; +} diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index 26c8443..8a7bf88 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -51,10 +51,21 @@ struct admin_connect_lookup_server_args { struct admin_connect_lookup_server_ret { admin_nonnull_server srv; }; +struct admin_server_get_threadpool_parameters_args { + admin_nonnull_server server; + u_int flags; +}; +struct admin_server_get_threadpool_parameters_ret { + struct { + u_int params_len; + admin_typed_param * params_val; + } params; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, ADMIN_PROC_CONNECT_GET_LIB_VERSION = 3, ADMIN_PROC_CONNECT_LIST_SERVERS = 4, ADMIN_PROC_CONNECT_LOOKUP_SERVER = 5, + ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index 54af90c..c528f79 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -674,3 +674,49 @@ virAdmConnectLookupServer(virAdmConnectPtr conn, virDispatchError(NULL); return ret; } + +/** + * virAdmServerGetThreadPoolParameters: + * @srv: a valid server object reference + * @params: a pointer which will be allocated to store all returned parameters + * @nparams: a pointer which will hold the number of params returned in @params + * @flags: extra flags for virAdmServerGetThreadPoolStatsFlags + * + * This methods retrieves threadpool parameters from @srv. Upon successful + * completion, @params will be allocated automatically to hold all returned + * params and setting @nparams accordingly. + * When extracting parameters from @params, following search keys are + * supported: + * VIR_THREADPOOL_WORKERS_MIN + * VIR_THREADPOOL_WORKERS_MAX + * VIR_THREADPOOL_WORKERS_PRIORITY + * VIR_THREADPOOL_WORKERS_FREE + * VIR_THREADPOOL_WORKERS_CURRENT + * + * Returns 0 on success, -1 in case of an error. + */ +int +virAdmServerGetThreadPoolParameters(virAdmServerPtr srv, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + int ret = -1; + + VIR_DEBUG("srv=%p, params=%p, nparams=%p, flags=%x", + srv, params, nparams, flags); + + virResetLastError(); + + virCheckAdmServerReturn(srv, -1); + virCheckNonNullArgGoto(params, error); + + if ((ret = remoteAdminServerGetThreadPoolParameters(srv, params, nparams, + flags)) < 0) + goto error; + + return ret; + error: + virDispatchError(NULL); + return -1; +} diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index 268f1e6..b05067c 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -12,6 +12,8 @@ xdr_admin_connect_list_servers_ret; xdr_admin_connect_lookup_server_args; xdr_admin_connect_lookup_server_ret; xdr_admin_connect_open_args; +xdr_admin_server_get_threadpool_parameters_args; +xdr_admin_server_get_threadpool_parameters_ret; # datatypes.h virAdmConnectClass; diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms index 58d085e..0a12b5f 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -23,6 +23,7 @@ LIBVIRT_ADMIN_1.3.0 { virAdmConnectUnregisterCloseCallback; virAdmConnectListServers; virAdmServerGetName; + virAdmServerGetThreadPoolParameters; virAdmServerFree; virAdmConnectLookupServer; }; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index cf48e50..3878547 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -877,3 +877,25 @@ virNetServerGetName(virNetServerPtr srv) { return srv->name; } + +int +virNetServerGetThreadPoolParameters(virNetServerPtr srv, + size_t *minWorkers, + size_t *maxWorkers, + size_t *nWorkers, + size_t *freeWorkers, + size_t *nPrioWorkers, + size_t *jobQueueDepth) +{ + virObjectLock(srv); + + *minWorkers = virThreadPoolGetMinWorkers(srv->workers); + *maxWorkers = virThreadPoolGetMaxWorkers(srv->workers); + *freeWorkers = virThreadPoolGetFreeWorkers(srv->workers); + *nWorkers = virThreadPoolGetCurrentWorkers(srv->workers); + *nPrioWorkers = virThreadPoolGetPriorityWorkers(srv->workers); + *jobQueueDepth = virThreadPoolGetJobQueueDepth(srv->workers); + + virObjectUnlock(srv); + return 0; +} diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index aa24440..6f17d1c 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -89,4 +89,12 @@ int virNetServerStart(virNetServerPtr srv); const char *virNetServerGetName(virNetServerPtr srv); +int virNetServerGetThreadPoolParameters(virNetServerPtr srv, + size_t *minWorkers, + size_t *maxWorkers, + size_t *nWorkers, + size_t *freeWorkers, + size_t *nPrioWorkers, + size_t *jobQueueDepth); + #endif /* __VIR_NET_SERVER_H__ */ -- 2.4.11

Since threadpool increments the current number of threads according to current load, i.e. how many jobs are waiting in the queue. The count however, is constrained by max and min limits of workers. The logic of this new API works like this: 1) setting the minimum a) When the limit is increased, depending on the current number of threads, new threads are possibly spawned if the current number of threads is less than the new minimum limit b) Decreasing the minimum limit has no possible effect on the current number of threads 2) setting the maximum a) Icreasing the maximum limit has no immediate effect on the current number of threads, it only allows the threadpool to spawn more threads when new jobs, that would otherwise end up queued, arrive. b) Decreasing the maximum limit may affect the current number of threads, if the current number of threads is less than the new maximum limit. Since there may be some ongoing time-consuming jobs that would effectively block this API from killing any threads. Therefore, this API is asynchronous with best-effort execution, i.e. the necessary number of workers will be terminated once they finish their previous job, unless other workers had already terminated, decreasing the limit to the requested value. 3) setting priority workers - both increase and decrease in count of these workers have an immediate impact on the current number of workers, new ones will be spawned or some of them get terminated respectively. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- daemon/admin.c | 43 +++++++++++++++++++++++ daemon/admin_server.c | 43 +++++++++++++++++++++++ daemon/admin_server.h | 5 +++ include/libvirt/libvirt-admin.h | 5 +++ src/admin/admin_protocol.x | 13 ++++++- src/admin/admin_remote.c | 34 ++++++++++++++++++ src/admin_protocol-structs | 9 +++++ src/libvirt-admin.c | 37 ++++++++++++++++++++ src/libvirt_admin_private.syms | 1 + src/libvirt_admin_public.syms | 1 + src/libvirt_private.syms | 1 + src/rpc/virnetserver.c | 15 ++++++++ src/rpc/virnetserver.h | 5 +++ src/util/virthreadpool.c | 77 +++++++++++++++++++++++++++++++++++++++-- src/util/virthreadpool.h | 5 +++ 15 files changed, 290 insertions(+), 4 deletions(-) diff --git a/daemon/admin.c b/daemon/admin.c index 530f6bf..eb961d3 100644 --- a/daemon/admin.c +++ b/daemon/admin.c @@ -178,4 +178,47 @@ adminDispatchServerGetThreadpoolParameters(virNetServerPtr server ATTRIBUTE_UNUS virObjectUnref(srv); return rv; } + +static int +adminDispatchServerSetThreadpoolParameters(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + struct admin_server_set_threadpool_parameters_args *args) +{ + int rv = -1; + virNetServerPtr srv = NULL; + virTypedParameterPtr params = NULL; + int nparams = 0; + struct daemonAdmClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!(srv = virNetDaemonGetServer(priv->dmn, args->server.name))) { + virReportError(VIR_ERR_NO_SERVER, + _("no server with matching name '%s' found"), + args->server.name); + goto cleanup; + } + + if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val, + args->params.params_len, + ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX, + ¶ms, + &nparams) < 0) + goto cleanup; + + + if (adminDaemonSetThreadPoolParameters(srv, params, + nparams, args->flags) < 0) + goto cleanup; + + rv = 0; + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + + virTypedParamsFree(params, nparams); + virObjectUnref(srv); + return rv; +} #include "admin_dispatch.h" diff --git a/daemon/admin_server.c b/daemon/admin_server.c index e7d48b8..573558e 100644 --- a/daemon/admin_server.c +++ b/daemon/admin_server.c @@ -32,6 +32,7 @@ #include "virnetserver.h" #include "virstring.h" #include "virthreadpool.h" +#include "virtypedparam.h" #define VIR_FROM_THIS VIR_FROM_ADMIN @@ -135,3 +136,45 @@ adminDaemonGetThreadPoolParameters(virNetServerPtr srv, virTypedParamsFree(tmpparams, *nparams); return ret; } + +int +adminDaemonSetThreadPoolParameters(virNetServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + long long int minWorkers = -1; + long long int maxWorkers = -1; + long long int prioWorkers = -1; + virTypedParameterPtr param = NULL; + + virCheckFlags(0, -1); + + if (virTypedParamsValidate(params, nparams, + VIR_THREADPOOL_WORKERS_MIN, + VIR_TYPED_PARAM_UINT, + VIR_THREADPOOL_WORKERS_MAX, + VIR_TYPED_PARAM_UINT, + VIR_THREADPOOL_WORKERS_PRIORITY, + VIR_TYPED_PARAM_UINT, + NULL) < 0) + return -1; + + if ((param = virTypedParamsGet(params, nparams, + VIR_THREADPOOL_WORKERS_MIN))) + minWorkers = param->value.ui; + + if ((param = virTypedParamsGet(params, nparams, + VIR_THREADPOOL_WORKERS_MAX))) + maxWorkers = param->value.ui; + + if ((param = virTypedParamsGet(params, nparams, + VIR_THREADPOOL_WORKERS_PRIORITY))) + prioWorkers = param->value.ui; + + if (virNetServerSetThreadPoolParameters(srv, minWorkers, + maxWorkers, prioWorkers) < 0) + return -1; + + return 0; +} diff --git a/daemon/admin_server.h b/daemon/admin_server.h index 7aa7727..076e21a 100644 --- a/daemon/admin_server.h +++ b/daemon/admin_server.h @@ -40,5 +40,10 @@ adminDaemonGetThreadPoolParameters(virNetServerPtr srv, virTypedParameterPtr *params, int *nparams, unsigned int flags); +int +adminDaemonSetThreadPoolParameters(virNetServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags); #endif /* __LIBVIRTD_ADMIN_SERVER_H__ */ diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index 39c2c02..db17663 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -176,6 +176,11 @@ int virAdmServerGetThreadPoolParameters(virAdmServerPtr srv, int *nparams, unsigned int flags); +int virAdmServerSetThreadPoolParameters(virAdmServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index 46b1b5c..e2123b6 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -110,6 +110,12 @@ struct admin_server_get_threadpool_parameters_ret { admin_typed_param params<ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX>; }; +struct admin_server_set_threadpool_parameters_args { + admin_nonnull_server server; + admin_typed_param params<ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX>; + unsigned int flags; +}; + /* Define the program number, protocol version and procedure numbers here. */ const ADMIN_PROGRAM = 0x06900690; const ADMIN_PROTOCOL_VERSION = 1; @@ -160,5 +166,10 @@ enum admin_procedure { /** * @generate: none */ - ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6 + ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6, + + /** + * @generate: none + */ + ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7 }; diff --git a/src/admin/admin_remote.c b/src/admin/admin_remote.c index 64942e7..c2cb6b6 100644 --- a/src/admin/admin_remote.c +++ b/src/admin/admin_remote.c @@ -267,3 +267,37 @@ remoteAdminServerGetThreadPoolParameters(virAdmServerPtr srv, virObjectUnlock(priv); return rv; } + +static int +remoteAdminServerSetThreadPoolParameters(virAdmServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + remoteAdminPrivPtr priv = srv->conn->privateData; + int rv = -1; + admin_server_set_threadpool_parameters_args args; + + args.flags = flags; + make_nonnull_server(&args.server, srv); + + if (virTypedParamsSerialize(params, nparams, + (virTypedParameterRemotePtr *) &args.params.params_val, + &args.params.params_len, + 0) < 0) + goto cleanup; + + + if (call(srv->conn, 0, ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS, + (xdrproc_t)xdr_admin_server_set_threadpool_parameters_args, (char *) &args, + (xdrproc_t)xdr_void, (char *) NULL) == -1) + goto cleanup; + + rv = 0; + + cleanup: + virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val, + args.params.params_len); + virObjectUnlock(priv); + return rv; +} diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index 8a7bf88..d0a0f1a 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -61,6 +61,14 @@ struct admin_server_get_threadpool_parameters_ret { admin_typed_param * params_val; } params; }; +struct admin_server_set_threadpool_parameters_args { + admin_nonnull_server server; + struct { + u_int params_len; + admin_typed_param * params_val; + } params; + u_int flags; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, @@ -68,4 +76,5 @@ enum admin_procedure { ADMIN_PROC_CONNECT_LIST_SERVERS = 4, ADMIN_PROC_CONNECT_LOOKUP_SERVER = 5, ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6, + ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index c528f79..5a6c2a4 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -720,3 +720,40 @@ virAdmServerGetThreadPoolParameters(virAdmServerPtr srv, virDispatchError(NULL); return -1; } + +/** + * virAdmServerSetThreadPoolParameters: + * @srv: a valid server object reference + * @params: pointer to threadpool parameter objects + * @nparams: number of parameters in @params + * @flags: bitwise-OR of extra flags virAdmServerSetThreadPoolParametersFlags + * + * Change server threadpool parameters according to @params. Note that some + * tunables are read-only, thus any attempt to set them will result in a + * failure. + * + * Returns 0 on success, -1 in case of an error. + */ +int +virAdmServerSetThreadPoolParameters(virAdmServerPtr srv, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + VIR_DEBUG("srv=%p, params=%p, nparams=%x, flags=%x", + srv, params, nparams, flags); + + virResetLastError(); + + virCheckAdmServerReturn(srv, -1); + virCheckNonNullArgGoto(params, error); + + if (remoteAdminServerSetThreadPoolParameters(srv, params, + nparams, flags) < 0) + goto error; + + return 0; + error: + virDispatchError(NULL); + return -1; +} diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index b05067c..b150d8a 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -14,6 +14,7 @@ xdr_admin_connect_lookup_server_ret; xdr_admin_connect_open_args; xdr_admin_server_get_threadpool_parameters_args; xdr_admin_server_get_threadpool_parameters_ret; +xdr_admin_server_set_threadpool_parameters_args; # datatypes.h virAdmConnectClass; diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms index 0a12b5f..0a16444 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -26,4 +26,5 @@ LIBVIRT_ADMIN_1.3.0 { virAdmServerGetThreadPoolParameters; virAdmServerFree; virAdmConnectLookupServer; + virAdmServerSetThreadPoolParameters; }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e9a2bce..824b1fa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2355,6 +2355,7 @@ virThreadPoolGetMinWorkers; virThreadPoolGetPriorityWorkers; virThreadPoolNewFull; virThreadPoolSendJob; +virThreadPoolSetParameters; # util/virtime.h diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 3878547..57bd95c 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -899,3 +899,18 @@ virNetServerGetThreadPoolParameters(virNetServerPtr srv, virObjectUnlock(srv); return 0; } + +int +virNetServerSetThreadPoolParameters(virNetServerPtr srv, + long long int minWorkers, + long long int maxWorkers, + long long int prioWorkers) +{ + int ret; + + virObjectLock(srv); + ret = virThreadPoolSetParameters(srv->workers, minWorkers, + maxWorkers, prioWorkers); + virObjectUnlock(srv); + return ret; +} diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index 6f17d1c..8b304f6 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -97,4 +97,9 @@ int virNetServerGetThreadPoolParameters(virNetServerPtr srv, size_t *nPrioWorkers, size_t *jobQueueDepth); +int virNetServerSetThreadPoolParameters(virNetServerPtr srv, + long long int minWorkers, + long long int maxWorkers, + long long int prioWorkers); + #endif /* __VIR_NET_SERVER_H__ */ diff --git a/src/util/virthreadpool.c b/src/util/virthreadpool.c index fec8620..c553477 100644 --- a/src/util/virthreadpool.c +++ b/src/util/virthreadpool.c @@ -73,6 +73,7 @@ struct _virThreadPool { size_t nWorkers; virThreadPtr workers; + size_t maxPrioWorkers; size_t nPrioWorkers; virThreadPtr prioWorkers; virCond prioCond; @@ -84,12 +85,22 @@ struct virThreadPoolWorkerData { bool priority; }; +/* Test whether the worker needs to quit if the current number of workers @count + * is greater than @limit actually allows. + */ +static inline bool virThreadPoolWorkerQuitHelper(size_t count, size_t limit) +{ + return count > limit; +} + static void virThreadPoolWorker(void *opaque) { struct virThreadPoolWorkerData *data = opaque; virThreadPoolPtr pool = data->pool; virCondPtr cond = data->cond; bool priority = data->priority; + size_t *curWorkers = priority ? &pool->nPrioWorkers : &pool->nWorkers; + size_t *maxLimit = priority ? &pool->maxPrioWorkers : &pool->maxWorkers; virThreadPoolJobPtr job = NULL; VIR_FREE(data); @@ -97,6 +108,14 @@ static void virThreadPoolWorker(void *opaque) virMutexLock(&pool->mutex); while (1) { + /* In order to support async worker termination, we need ensure that + * both busy and free workers know if they need to terminated. Thus, + * busy workers need to check for this fact before they start waiting for + * another job (and before taking another one from the queue); and + * free workers need to check for this right after waking up. + */ + if (virThreadPoolWorkerQuitHelper(*curWorkers, *maxLimit)) + goto out; while (!pool->quit && ((!priority && !pool->jobList.head) || (priority && !pool->jobList.firstPrio))) { @@ -109,6 +128,9 @@ static void virThreadPoolWorker(void *opaque) } if (!priority) pool->freeWorkers--; + + if (virThreadPoolWorkerQuitHelper(*curWorkers, *maxLimit)) + goto out; } if (pool->quit) @@ -160,12 +182,12 @@ static void virThreadPoolWorker(void *opaque) static int virThreadPoolExpand(virThreadPoolPtr pool, size_t gain, bool priority) { - virThreadPtr workers = priority ? pool->prioWorkers : pool->workers; + virThreadPtr *workers = priority ? &pool->prioWorkers : &pool->workers; size_t *curWorkers = priority ? &pool->nPrioWorkers : &pool->nWorkers; size_t i = 0; struct virThreadPoolWorkerData *data = NULL; - if (VIR_EXPAND_N(workers, *curWorkers, gain) < 0) + if (VIR_EXPAND_N(*workers, *curWorkers, gain) < 0) return -1; for (i = 0; i < gain; i++) { @@ -176,7 +198,7 @@ virThreadPoolExpand(virThreadPoolPtr pool, size_t gain, bool priority) data->cond = priority ? &pool->prioCond : &pool->cond; data->priority = priority; - if (virThreadCreateFull(&workers[i], + if (virThreadCreateFull(&(*workers)[i], false, virThreadPoolWorker, pool->jobFuncName, @@ -226,6 +248,7 @@ virThreadPoolNewFull(size_t minWorkers, pool->minWorkers = minWorkers; pool->maxWorkers = maxWorkers; + pool->maxPrioWorkers = prioWorkers; if (virThreadPoolExpand(pool, minWorkers, false) < 0) goto error; @@ -399,3 +422,51 @@ int virThreadPoolSendJob(virThreadPoolPtr pool, virMutexUnlock(&pool->mutex); return -1; } + +int +virThreadPoolSetParameters(virThreadPoolPtr pool, + long long int minWorkers, + long long int maxWorkers, + long long int prioWorkers) +{ + virMutexLock(&pool->mutex); + + if ((minWorkers >= 0 && minWorkers > pool->maxWorkers) || + (maxWorkers >= 0 && maxWorkers < pool->minWorkers) || + (minWorkers >= 0 && maxWorkers >= 0 && minWorkers > maxWorkers)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("minWorkers cannot be larger than maxWorkers")); + goto error; + } + + if (minWorkers >= 0) { + if ((size_t) minWorkers > pool->nWorkers && + virThreadPoolExpand(pool, minWorkers - pool->nWorkers, + false) < 0) + goto error; + pool->minWorkers = minWorkers; + } + + if (maxWorkers >= 0) { + pool->maxWorkers = maxWorkers; + virCondBroadcast(&pool->cond); + } + + if (prioWorkers >= 0) { + if (prioWorkers < pool->nPrioWorkers) { + virCondBroadcast(&pool->prioCond); + } else if ((size_t) prioWorkers > pool->nPrioWorkers && + virThreadPoolExpand(pool, prioWorkers - pool->nPrioWorkers, + true) < 0) { + goto error; + } + pool->maxPrioWorkers = prioWorkers; + } + + virMutexUnlock(&pool->mutex); + return 0; + + error: + virMutexUnlock(&pool->mutex); + return -1; +} diff --git a/src/util/virthreadpool.h b/src/util/virthreadpool.h index bc0c907..e1f362f 100644 --- a/src/util/virthreadpool.h +++ b/src/util/virthreadpool.h @@ -57,4 +57,9 @@ int virThreadPoolSendJob(virThreadPoolPtr pool, void *jobdata) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virThreadPoolSetParameters(virThreadPoolPtr pool, + long long int minWorkers, + long long int maxWorkers, + long long int prioWorkers); + #endif -- 2.4.11

Wire up the server threadpool tunable APIs to virt-admin client. Signed-off-by: Erik Skultety <eskultet@redhat.com> --- tools/virt-admin.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/tools/virt-admin.c b/tools/virt-admin.c index edb8690..dec1096 100644 --- a/tools/virt-admin.c +++ b/tools/virt-admin.c @@ -353,6 +353,127 @@ cmdSrvList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) return ret; } + +/* -------------------- + * Command srv-workertune + * -------------------- + */ + +static const vshCmdInfo info_srv_workertune[] = { + {.name = "help", + .data = N_("Get or set server workerpool parameters") + }, + {.name = "desc", + .data = N_("Get or set server workerpool parameters. Some parameters are " + "read-only, thus only \n" + " a subset of all supported parameters can actually be " + "set via OPTIONS.\n" + " To retrieve workerpool parameters, use the command " + "without any options: \n\n" + " virt-admin # srv-workertune <server>") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_srv_workertune[] = { + {.name = "server", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("Server to get threadpool parameters for."), + }, + {.name = "min-workers", + .type = VSH_OT_INT, + .help = N_("Change the value of bottom limit to number of workers."), + }, + {.name = "max-workers", + .type = VSH_OT_INT, + .help = N_("Change the value of top limit to number of workers."), + }, + {.name = "priority-workers", + .type = VSH_OT_INT, + .help = N_("Change the current number of priority workers"), + }, + {.name = NULL} +}; + +static bool +cmdSrvWorkertune(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + virTypedParameterPtr params = NULL; + int nparams = 0; + int maxparams = 0; + unsigned int val; + unsigned int min, max; + int rv = 0; + size_t i; + bool ret = false; + const char *srvname = NULL; + virAdmServerPtr srv = NULL; + vshAdmControlPtr priv = ctl->privData; + + if (vshCommandOptStringReq(ctl, cmd, "server", &srvname) < 0) + return false; + +#define PARSE_WORKERTUNE_PARAM(NAME, FIELD) \ + if ((rv = vshCommandOptUInt(ctl, cmd, NAME, &val)) < 0) { \ + vshError(ctl, _("Unable to parse integer parameter '%s'"), NAME); \ + goto cleanup; \ + } else if (rv > 0) { \ + if (virTypedParamsAddUInt(¶ms, &nparams, &maxparams, \ + FIELD, val) < 0) \ + goto save_error; \ + } + + PARSE_WORKERTUNE_PARAM("max-workers", VIR_THREADPOOL_WORKERS_MAX); + PARSE_WORKERTUNE_PARAM("min-workers", VIR_THREADPOOL_WORKERS_MIN); + PARSE_WORKERTUNE_PARAM("priority-workers", VIR_THREADPOOL_WORKERS_PRIORITY); + +#undef PARSE_WORKERTUNE_PARAM + + if (virTypedParamsGetUInt(params, nparams, + VIR_THREADPOOL_WORKERS_MAX, &max) && + virTypedParamsGetUInt(params, nparams, + VIR_THREADPOOL_WORKERS_MIN, &min) && min > max) { + vshError(ctl, "%s", _("--min-workers must be less than --max-workers")); + goto cleanup; + } + + if (!(srv = virAdmConnectLookupServer(priv->conn, srvname, 0))) + goto cleanup; + + /* set server threadpool parameters */ + if (nparams) { + if (virAdmServerSetThreadPoolParameters(srv, params, + nparams, 0) < 0) + goto error; + } else { + if (virAdmServerGetThreadPoolParameters(srv, ¶ms, + &nparams, 0) < 0) { + vshError(ctl, "%s", + _("Unable to get server workerpool parameters")); + goto cleanup; + } + + for (i = 0; i < nparams; i++) + vshPrint(ctl, "%-15s: %d\n", params[i].field, params[i].value.ui); + } + + ret = true; + + cleanup: + virTypedParamsFree(params, nparams); + if (srv) + virAdmServerFree(srv); + return ret; + + save_error: + vshSaveLibvirtError(); + + error: + vshError(ctl, "%s", _("Unable to change server workerpool parameters")); + goto cleanup; +} + static void * vshAdmConnectionHandler(vshControl *ctl) { @@ -655,9 +776,20 @@ static const vshCmdDef monitoringCmds[] = { {.name = NULL} }; +static const vshCmdDef managementCmds[] = { + {.name = "srv-workertune", + .handler = cmdSrvWorkertune, + .opts = opts_srv_workertune, + .info = info_srv_workertune, + .flags = 0 + }, + {.name = NULL} +}; + static const vshCmdGrp cmdGroups[] = { {"Virt-admin itself", "virt-admin", vshAdmCmds}, {"Monitoring commands", "monitor", monitoringCmds}, + {"Management commands", "management", managementCmds}, {NULL, NULL, NULL} }; -- 2.4.11

On 04/04/16 23:09, Erik Skultety wrote:
since v2: - all getters are now protected by threadpool mutex to prevent torn reads in concurrent execution - some checks in adminDispatchServerGetThreadpoolParameters were redundant, thus were optimizes out - fixed memory leak in adminDispatchServerGetThreadpoolParameters when allocating a newlist although typed params serialization already does that - fixed some cosmetic issues like exporting a function prototype one patch earlier than it should actually be introduced - a mistake that got there by interactive rebase
Erik Skultety (11): po: Fix record ordering in POTFILES.in libvirt-host: Move virTypedParam* to libvirt-common admin: Enable usage of typed parameters util: Refactor thread creation by introducing virThreadPoolExpand util: Report system error when virThreadCreateFull fails util: Use a mutex when retrieving threadpool data util: Add more getters to threadpool parameters admin: Prepare admin protocol for future worker related procedures admin: Introduce virAdmServerGethreadPoolParameters admin: Introduce virAdmServerSetThreadPoolParameters virt-admin: Introduce srv-workertune command
cfg.mk | 2 +- daemon/admin.c | 88 +++++++++++++ daemon/admin_server.c | 110 +++++++++++++++++ daemon/admin_server.h | 11 ++ include/libvirt/libvirt-admin.h | 71 +++++++++++ include/libvirt/libvirt-common.h.in | 185 ++++++++++++++++++++++++++++ include/libvirt/libvirt-host.h | 186 ---------------------------- po/POTFILES.in | 4 +- src/admin/admin_protocol.x | 54 +++++++- src/admin/admin_remote.c | 77 ++++++++++++ src/admin_protocol-structs | 45 +++++++ src/libvirt-admin.c | 83 +++++++++++++ src/libvirt_admin_private.syms | 3 + src/libvirt_admin_public.syms | 2 + src/libvirt_private.syms | 4 + src/rpc/virnetserver.c | 37 ++++++ src/rpc/virnetserver.h | 13 ++ src/util/virthreadpool.c | 238 +++++++++++++++++++++++++----------- src/util/virthreadpool.h | 8 ++ tools/virt-admin.c | 132 ++++++++++++++++++++ 20 files changed, 1096 insertions(+), 257 deletions(-)
I made some code adjustments to this series and sent v4. Erik
participants (1)
-
Erik Skultety