From 597fe3cee68f561a181967b59a87b4e5c5880c4c Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 12 Aug 2011 14:04:31 +0200 Subject: [PATCH] daemon: Create priority workers pool This patch annotates APIs with low or high priority. In low set MUST be all APIs which might eventually access monitor (and thus block indefinitely). Other APIs may be marked as high priority. However, some must be (e.g. domainDestroy). For high priority calls (HPC), there are some high priority workers (HPW) created in the pool. HPW can execute only HPC, although normal worker can process any call regardless priority. Therefore, only those APIs which are guaranteed to end in reasonable small amount of time can be marked as HPC. The size of this HPC pool is static, because HPC are expected to end quickly, therefore jobs assigned to this pool will be served quickly. It can be configured in libvirtd.conf via prio_workers variable. Default is set to 5. To mark API with low or high priority, append priority:{low|high} to it's comment in src/remote/remote_protocol.x. This is similar to autogen|skipgen. If not marked, the generator assumes low as default. --- daemon/libvirtd.aug | 1 + daemon/libvirtd.c | 7 + daemon/libvirtd.conf | 6 + src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 2 +- src/remote/qemu_protocol.x | 13 +- src/remote/remote_protocol.x | 294 ++++++++++++++++++---------------- src/rpc/gendispatch.pl | 20 ++- src/rpc/virnetserver.c | 68 ++++---- src/rpc/virnetserver.h | 1 + src/rpc/virnetserverprogram.c | 11 ++ src/rpc/virnetserverprogram.h | 4 + src/util/threadpool.c | 158 +++++++++++++++--- src/util/threadpool.h | 4 +- 14 files changed, 384 insertions(+), 207 deletions(-) diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug index 3f47ebb66b..ce00db5394 100644 --- a/daemon/libvirtd.aug +++ b/daemon/libvirtd.aug @@ -57,6 +57,7 @@ module Libvirtd = | int_entry "max_clients" | int_entry "max_requests" | int_entry "max_client_requests" + | int_entry "prio_workers" let logging_entry = int_entry "log_level" | str_entry "log_filters" diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 7734ffff07..1a9fd82d96 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -134,6 +134,8 @@ struct daemonConfig { int max_workers; int max_clients; + int prio_workers; + int max_requests; int max_client_requests; @@ -886,6 +888,8 @@ daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) data->max_workers = 20; data->max_clients = 20; + data->prio_workers = 5; + data->max_requests = 20; data->max_client_requests = 5; @@ -1042,6 +1046,8 @@ daemonConfigLoad(struct daemonConfig *data, GET_CONF_INT (conf, filename, max_workers); GET_CONF_INT (conf, filename, max_clients); + GET_CONF_INT (conf, filename, prio_workers); + GET_CONF_INT (conf, filename, max_requests); GET_CONF_INT (conf, filename, max_client_requests); @@ -1441,6 +1447,7 @@ int main(int argc, char **argv) { config->auth_unix_ro == REMOTE_AUTH_POLKIT; if (!(srv = virNetServerNew(config->min_workers, config->max_workers, + config->prio_workers, config->max_clients, config->mdns_adv ? config->mdns_name : NULL, use_polkit_dbus, diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf index 95e43dd23d..da3983ecef 100644 --- a/daemon/libvirtd.conf +++ b/daemon/libvirtd.conf @@ -257,6 +257,12 @@ #min_workers = 5 #max_workers = 20 + +# The number of priority workers. If all workers from above +# pool will stuck, some calls marked as high priority +# (notably domainDestroy) can be executed in this pool. +#prio_workers = 5 + # Total global limit on concurrent RPC calls. Should be # at least as large as max_workers. Beyond this, RPC requests # will be read into memory and queued. This directly impact diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0dc886a01f..b1992a62db 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -663,7 +663,7 @@ qemudStartup(int privileged) { virHashForEach(qemu_driver->domains.objs, qemuDomainSnapshotLoad, qemu_driver->snapshotDir); - qemu_driver->workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); + qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver); if (!qemu_driver->workerPool) goto error; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index f36efeaf95..e5f25f56ce 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -571,7 +571,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, * deleted before handling watchdog event is finished. */ virDomainObjRef(vm); - if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { + if (virThreadPoolSendJob(driver->workerPool, 0, wdEvent) < 0) { if (virDomainObjUnref(vm) == 0) vm = NULL; VIR_FREE(wdEvent); diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x index 3279405b76..39f9adfe1b 100644 --- a/src/remote/qemu_protocol.x +++ b/src/remote/qemu_protocol.x @@ -52,9 +52,14 @@ const QEMU_PROGRAM = 0x20008087; const QEMU_PROTOCOL_VERSION = 1; enum qemu_procedure { - /* Each function must have a two-word comment. The first word is + /* Each function must have a three-word comment. The first word is * whether gendispatch.pl handles daemon, the second whether - * it handles src/remote. */ - QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen */ - QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen */ + * it handles src/remote. + * The last argument describes priority of API. There are two accepted + * values: low, high; Each API that might eventually access hypervisor's + * monitor (and thus block) MUST fall into low priority. However, there + * are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY + * be marked as high priority. If in doubt, it's safe to choose low. */ + QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen priority:low */ + QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen priority:low */ }; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 676570ea43..4bb6453201 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2211,189 +2211,195 @@ const REMOTE_PROGRAM = 0x20008086; const REMOTE_PROTOCOL_VERSION = 1; enum remote_procedure { - /* Each function must have a two-word comment. The first word is + /* Each function must have a three-word comment. The first word is * whether gendispatch.pl handles daemon, the second whether * it handles src/remote. Additional flags can be specified after a * pipe. + * The last argument describes priority of API. There are two accepted + * values: low, high; Each API that might eventually access hypervisor's + * monitor (and thus block) MUST fall into low priority. However, there + * are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY + * be marked as high priority. If in doubt, it's safe to choose low. + * Low is taken as default, and thus can be left out. * * The (readstream|writestream)@ flag lets daemon and src/remote * create a stream. The direction is defined from the src/remote point * of view. A readstream transfers data from daemon to src/remote. The * specifies at which offset the stream parameter is inserted * in the function parameter list. */ - REMOTE_PROC_OPEN = 1, /* skipgen skipgen */ - REMOTE_PROC_CLOSE = 2, /* skipgen skipgen */ - REMOTE_PROC_GET_TYPE = 3, /* autogen skipgen */ - REMOTE_PROC_GET_VERSION = 4, /* autogen autogen */ - REMOTE_PROC_GET_MAX_VCPUS = 5, /* autogen autogen */ - REMOTE_PROC_NODE_GET_INFO = 6, /* autogen autogen */ + REMOTE_PROC_OPEN = 1, /* skipgen skipgen priority:high */ + REMOTE_PROC_CLOSE = 2, /* skipgen skipgen priority:high */ + REMOTE_PROC_GET_TYPE = 3, /* autogen skipgen priority:high */ + REMOTE_PROC_GET_VERSION = 4, /* autogen autogen priority:high */ + REMOTE_PROC_GET_MAX_VCPUS = 5, /* autogen autogen priority:high */ + REMOTE_PROC_NODE_GET_INFO = 6, /* autogen autogen priority:high */ REMOTE_PROC_GET_CAPABILITIES = 7, /* autogen autogen */ REMOTE_PROC_DOMAIN_ATTACH_DEVICE = 8, /* autogen autogen */ REMOTE_PROC_DOMAIN_CREATE = 9, /* autogen skipgen */ REMOTE_PROC_DOMAIN_CREATE_XML = 10, /* autogen autogen */ - REMOTE_PROC_DOMAIN_DEFINE_XML = 11, /* autogen autogen */ - REMOTE_PROC_DOMAIN_DESTROY = 12, /* autogen autogen */ + REMOTE_PROC_DOMAIN_DEFINE_XML = 11, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_DESTROY = 12, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_DETACH_DEVICE = 13, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_XML_DESC = 14, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_AUTOSTART = 15, /* autogen autogen */ + REMOTE_PROC_DOMAIN_GET_AUTOSTART = 15, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_GET_INFO = 16, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_MAX_MEMORY = 17, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_MAX_VCPUS = 18, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_OS_TYPE = 19, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_VCPUS = 20, /* skipgen skipgen */ - - REMOTE_PROC_LIST_DEFINED_DOMAINS = 21, /* autogen autogen */ - REMOTE_PROC_DOMAIN_LOOKUP_BY_ID = 22, /* autogen autogen */ - REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME = 23, /* autogen autogen */ - REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID = 24, /* autogen autogen */ - REMOTE_PROC_NUM_OF_DEFINED_DOMAINS = 25, /* autogen autogen */ + REMOTE_PROC_DOMAIN_GET_MAX_MEMORY = 17, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_GET_MAX_VCPUS = 18, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_GET_OS_TYPE = 19, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_GET_VCPUS = 20, /* skipgen skipgen priority:high */ + + REMOTE_PROC_LIST_DEFINED_DOMAINS = 21, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_LOOKUP_BY_ID = 22, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME = 23, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID = 24, /* autogen autogen priority:high */ + REMOTE_PROC_NUM_OF_DEFINED_DOMAINS = 25, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_PIN_VCPU = 26, /* autogen autogen */ REMOTE_PROC_DOMAIN_REBOOT = 27, /* autogen autogen */ REMOTE_PROC_DOMAIN_RESUME = 28, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SET_AUTOSTART = 29, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SET_MAX_MEMORY = 30, /* autogen autogen */ + REMOTE_PROC_DOMAIN_SET_AUTOSTART = 29, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_SET_MAX_MEMORY = 30, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_SET_MEMORY = 31, /* autogen autogen */ REMOTE_PROC_DOMAIN_SET_VCPUS = 32, /* autogen autogen */ REMOTE_PROC_DOMAIN_SHUTDOWN = 33, /* autogen autogen */ REMOTE_PROC_DOMAIN_SUSPEND = 34, /* autogen autogen */ - REMOTE_PROC_DOMAIN_UNDEFINE = 35, /* autogen autogen */ - REMOTE_PROC_LIST_DEFINED_NETWORKS = 36, /* autogen autogen */ - REMOTE_PROC_LIST_DOMAINS = 37, /* autogen skipgen */ - REMOTE_PROC_LIST_NETWORKS = 38, /* autogen autogen */ + REMOTE_PROC_DOMAIN_UNDEFINE = 35, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_DEFINED_NETWORKS = 36, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_DOMAINS = 37, /* autogen skipgen priority:high */ + REMOTE_PROC_LIST_NETWORKS = 38, /* autogen autogen priority:high */ REMOTE_PROC_NETWORK_CREATE = 39, /* autogen autogen */ REMOTE_PROC_NETWORK_CREATE_XML = 40, /* autogen autogen */ - REMOTE_PROC_NETWORK_DEFINE_XML = 41, /* autogen autogen */ - REMOTE_PROC_NETWORK_DESTROY = 42, /* autogen autogen */ - REMOTE_PROC_NETWORK_GET_XML_DESC = 43, /* autogen autogen */ - REMOTE_PROC_NETWORK_GET_AUTOSTART = 44, /* autogen autogen */ - REMOTE_PROC_NETWORK_GET_BRIDGE_NAME = 45, /* autogen autogen */ - REMOTE_PROC_NETWORK_LOOKUP_BY_NAME = 46, /* autogen autogen */ - REMOTE_PROC_NETWORK_LOOKUP_BY_UUID = 47, /* autogen autogen */ - REMOTE_PROC_NETWORK_SET_AUTOSTART = 48, /* autogen autogen */ - REMOTE_PROC_NETWORK_UNDEFINE = 49, /* autogen autogen */ - REMOTE_PROC_NUM_OF_DEFINED_NETWORKS = 50, /* autogen autogen */ - - REMOTE_PROC_NUM_OF_DOMAINS = 51, /* autogen autogen */ - REMOTE_PROC_NUM_OF_NETWORKS = 52, /* autogen autogen */ + REMOTE_PROC_NETWORK_DEFINE_XML = 41, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_DESTROY = 42, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_GET_XML_DESC = 43, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_GET_AUTOSTART = 44, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_GET_BRIDGE_NAME = 45, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_LOOKUP_BY_NAME = 46, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_LOOKUP_BY_UUID = 47, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_SET_AUTOSTART = 48, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_UNDEFINE = 49, /* autogen autogen priority:high */ + REMOTE_PROC_NUM_OF_DEFINED_NETWORKS = 50, /* autogen autogen priority:high */ + + REMOTE_PROC_NUM_OF_DOMAINS = 51, /* autogen autogen priority:high */ + REMOTE_PROC_NUM_OF_NETWORKS = 52, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_CORE_DUMP = 53, /* autogen autogen */ REMOTE_PROC_DOMAIN_RESTORE = 54, /* autogen autogen */ REMOTE_PROC_DOMAIN_SAVE = 55, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE = 56, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, /* skipgen autogen */ REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, /* autogen autogen */ - REMOTE_PROC_GET_HOSTNAME = 59, /* autogen autogen */ - REMOTE_PROC_SUPPORTS_FEATURE = 60, /* autogen autogen */ + REMOTE_PROC_GET_HOSTNAME = 59, /* autogen autogen priority:high */ + REMOTE_PROC_SUPPORTS_FEATURE = 60, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE = 61, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62, /* autogen autogen */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63, /* autogen autogen */ REMOTE_PROC_DOMAIN_BLOCK_STATS = 64, /* autogen autogen */ - REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65, /* autogen autogen */ - REMOTE_PROC_AUTH_LIST = 66, /* skipgen skipgen */ - REMOTE_PROC_AUTH_SASL_INIT = 67, /* skipgen skipgen */ - REMOTE_PROC_AUTH_SASL_START = 68, /* skipgen skipgen */ - REMOTE_PROC_AUTH_SASL_STEP = 69, /* skipgen skipgen */ - REMOTE_PROC_AUTH_POLKIT = 70, /* skipgen skipgen */ - - REMOTE_PROC_NUM_OF_STORAGE_POOLS = 71, /* autogen autogen */ - REMOTE_PROC_LIST_STORAGE_POOLS = 72, /* autogen autogen */ - REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS = 73, /* autogen autogen */ - REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS = 74, /* autogen autogen */ + REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65, /* autogen autogen priority:high */ + REMOTE_PROC_AUTH_LIST = 66, /* skipgen skipgen priority:high */ + REMOTE_PROC_AUTH_SASL_INIT = 67, /* skipgen skipgen priority:high */ + REMOTE_PROC_AUTH_SASL_START = 68, /* skipgen skipgen priority:high */ + REMOTE_PROC_AUTH_SASL_STEP = 69, /* skipgen skipgen priority:high */ + REMOTE_PROC_AUTH_POLKIT = 70, /* skipgen skipgen priority:high */ + + REMOTE_PROC_NUM_OF_STORAGE_POOLS = 71, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_STORAGE_POOLS = 72, /* autogen autogen priority:high */ + REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS = 73, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS = 74, /* autogen autogen priority:high */ REMOTE_PROC_FIND_STORAGE_POOL_SOURCES = 75, /* autogen skipgen */ REMOTE_PROC_STORAGE_POOL_CREATE_XML = 76, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_DEFINE_XML = 77, /* autogen autogen */ + REMOTE_PROC_STORAGE_POOL_DEFINE_XML = 77, /* autogen autogen priority:high */ REMOTE_PROC_STORAGE_POOL_CREATE = 78, /* autogen autogen */ REMOTE_PROC_STORAGE_POOL_BUILD = 79, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_DESTROY = 80, /* autogen autogen */ + REMOTE_PROC_STORAGE_POOL_DESTROY = 80, /* autogen autogen priority:high */ REMOTE_PROC_STORAGE_POOL_DELETE = 81, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_UNDEFINE = 82, /* autogen autogen */ + REMOTE_PROC_STORAGE_POOL_UNDEFINE = 82, /* autogen autogen priority:high */ REMOTE_PROC_STORAGE_POOL_REFRESH = 83, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME = 84, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID = 85, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME = 86, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_GET_INFO = 87, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_GET_XML_DESC = 88, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART = 89, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART = 90, /* autogen autogen */ - - REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES = 91, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /* autogen autogen */ + REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME = 84, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID = 85, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME = 86, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_GET_INFO = 87, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_GET_XML_DESC = 88, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART = 89, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART = 90, /* autogen autogen priority:high */ + + REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES = 91, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /* autogen autogen priority:high */ REMOTE_PROC_STORAGE_VOL_CREATE_XML = 93, /* autogen autogen */ REMOTE_PROC_STORAGE_VOL_DELETE = 94, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME = 95, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY = 96, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH = 97, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_GET_INFO = 98, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_GET_XML_DESC = 99, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_GET_PATH = 100, /* autogen autogen */ - - REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101, /* autogen skipgen */ - REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /* autogen autogen */ + REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME = 95, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY = 96, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH = 97, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_VOL_GET_INFO = 98, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_VOL_GET_XML_DESC = 99, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_VOL_GET_PATH = 100, /* autogen autogen priority:high */ + + REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101, /* autogen skipgen priority:high */ + REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104, /* skipgen skipgen */ - REMOTE_PROC_DOMAIN_EVENTS_REGISTER = 105, /* skipgen skipgen */ - REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER = 106, /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_EVENTS_REGISTER = 105, /* skipgen skipgen priority:high */ + REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER = 106, /* skipgen skipgen priority:high */ REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE = 107, /* autogen autogen */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2 = 108, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH2 = 109, /* autogen autogen */ - REMOTE_PROC_GET_URI = 110, /* autogen skipgen */ + REMOTE_PROC_GET_URI = 110, /* autogen skipgen priority:high */ - REMOTE_PROC_NODE_NUM_OF_DEVICES = 111, /* autogen autogen */ - REMOTE_PROC_NODE_LIST_DEVICES = 112, /* autogen autogen */ - REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME = 113, /* autogen autogen */ + REMOTE_PROC_NODE_NUM_OF_DEVICES = 111, /* autogen autogen priority:high */ + REMOTE_PROC_NODE_LIST_DEVICES = 112, /* autogen autogen priority:high */ + REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME = 113, /* autogen autogen priority:high */ REMOTE_PROC_NODE_DEVICE_GET_XML_DESC = 114, /* autogen autogen */ - REMOTE_PROC_NODE_DEVICE_GET_PARENT = 115, /* skipgen autogen */ - REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS = 116, /* autogen autogen */ - REMOTE_PROC_NODE_DEVICE_LIST_CAPS = 117, /* autogen autogen */ + REMOTE_PROC_NODE_DEVICE_GET_PARENT = 115, /* skipgen autogen priority:high */ + REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS = 116, /* autogen autogen priority:high */ + REMOTE_PROC_NODE_DEVICE_LIST_CAPS = 117, /* autogen autogen priority:high */ REMOTE_PROC_NODE_DEVICE_DETTACH = 118, /* autogen skipgen */ REMOTE_PROC_NODE_DEVICE_RE_ATTACH = 119, /* autogen skipgen */ REMOTE_PROC_NODE_DEVICE_RESET = 120, /* autogen skipgen */ - REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121, /* skipgen skipgen */ - REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121, /* skipgen skipgen priority:high */ + REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, /* skipgen skipgen priority:high */ REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, /* autogen autogen */ - REMOTE_PROC_NODE_DEVICE_DESTROY = 124, /* autogen autogen */ + REMOTE_PROC_NODE_DEVICE_DESTROY = 124, /* autogen autogen priority:high */ REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125, /* autogen autogen */ - REMOTE_PROC_NUM_OF_INTERFACES = 126, /* autogen autogen */ - REMOTE_PROC_LIST_INTERFACES = 127, /* autogen autogen */ - REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, /* autogen autogen */ - REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, /* autogen autogen */ + REMOTE_PROC_NUM_OF_INTERFACES = 126, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_INTERFACES = 127, /* autogen autogen priority:high */ + REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, /* autogen autogen priority:high */ + REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, /* autogen autogen priority:high */ REMOTE_PROC_INTERFACE_GET_XML_DESC = 130, /* autogen autogen */ - REMOTE_PROC_INTERFACE_DEFINE_XML = 131, /* autogen autogen */ - REMOTE_PROC_INTERFACE_UNDEFINE = 132, /* autogen autogen */ + REMOTE_PROC_INTERFACE_DEFINE_XML = 131, /* autogen autogen priority:high */ + REMOTE_PROC_INTERFACE_UNDEFINE = 132, /* autogen autogen priority:high */ REMOTE_PROC_INTERFACE_CREATE = 133, /* autogen autogen */ - REMOTE_PROC_INTERFACE_DESTROY = 134, /* autogen autogen */ + REMOTE_PROC_INTERFACE_DESTROY = 134, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_XML_FROM_NATIVE = 135, /* autogen autogen */ REMOTE_PROC_DOMAIN_XML_TO_NATIVE = 136, /* autogen autogen */ - REMOTE_PROC_NUM_OF_DEFINED_INTERFACES = 137, /* autogen autogen */ - REMOTE_PROC_LIST_DEFINED_INTERFACES = 138, /* autogen autogen */ - REMOTE_PROC_NUM_OF_SECRETS = 139, /* autogen autogen */ - REMOTE_PROC_LIST_SECRETS = 140, /* autogen autogen */ - - REMOTE_PROC_SECRET_LOOKUP_BY_UUID = 141, /* autogen autogen */ - REMOTE_PROC_SECRET_DEFINE_XML = 142, /* autogen autogen */ - REMOTE_PROC_SECRET_GET_XML_DESC = 143, /* autogen autogen */ - REMOTE_PROC_SECRET_SET_VALUE = 144, /* autogen autogen */ - REMOTE_PROC_SECRET_GET_VALUE = 145, /* skipgen skipgen */ - REMOTE_PROC_SECRET_UNDEFINE = 146, /* autogen autogen */ - REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147, /* autogen autogen */ + REMOTE_PROC_NUM_OF_DEFINED_INTERFACES = 137, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_DEFINED_INTERFACES = 138, /* autogen autogen priority:high */ + REMOTE_PROC_NUM_OF_SECRETS = 139, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_SECRETS = 140, /* autogen autogen priority:high */ + + REMOTE_PROC_SECRET_LOOKUP_BY_UUID = 141, /* autogen autogen priority:high */ + REMOTE_PROC_SECRET_DEFINE_XML = 142, /* autogen autogen priority:high */ + REMOTE_PROC_SECRET_GET_XML_DESC = 143, /* autogen autogen priority:high */ + REMOTE_PROC_SECRET_SET_VALUE = 144, /* autogen autogen priority:high */ + REMOTE_PROC_SECRET_GET_VALUE = 145, /* skipgen skipgen priority:high */ + REMOTE_PROC_SECRET_UNDEFINE = 146, /* autogen autogen priority:high */ + REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL = 148, /* autogen autogen | writestream@1 */ - REMOTE_PROC_IS_SECURE = 149, /* autogen skipgen */ - REMOTE_PROC_DOMAIN_IS_ACTIVE = 150, /* autogen autogen */ - - REMOTE_PROC_DOMAIN_IS_PERSISTENT = 151, /* autogen autogen */ - REMOTE_PROC_NETWORK_IS_ACTIVE = 152, /* autogen autogen */ - REMOTE_PROC_NETWORK_IS_PERSISTENT = 153, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, /* autogen autogen */ - REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, /* autogen autogen */ - REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, /* autogen autogen */ - REMOTE_PROC_GET_LIB_VERSION = 157, /* autogen autogen */ - REMOTE_PROC_CPU_COMPARE = 158, /* autogen autogen */ + REMOTE_PROC_IS_SECURE = 149, /* autogen skipgen priority:high */ + REMOTE_PROC_DOMAIN_IS_ACTIVE = 150, /* autogen autogen priority:high */ + + REMOTE_PROC_DOMAIN_IS_PERSISTENT = 151, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_IS_ACTIVE = 152, /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_IS_PERSISTENT = 153, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, /* autogen autogen priority:high */ + REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, /* autogen autogen priority:high */ + REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, /* autogen autogen priority:high */ + REMOTE_PROC_GET_LIB_VERSION = 157, /* autogen autogen priority:high */ + REMOTE_PROC_CPU_COMPARE = 158, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_MEMORY_STATS = 159, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS = 160, /* autogen autogen */ @@ -2403,8 +2409,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_ABORT_JOB = 164, /* autogen autogen */ REMOTE_PROC_STORAGE_VOL_WIPE = 165, /* autogen autogen */ REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166, /* autogen autogen */ - REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167, /* skipgen skipgen */ - REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168, /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167, /* skipgen skipgen priority:high */ + REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168, /* skipgen skipgen priority:high */ REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169, /* autogen autogen */ REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170, /* autogen autogen */ @@ -2412,22 +2418,22 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172, /* autogen autogen */ REMOTE_PROC_DOMAIN_EVENT_GRAPHICS = 173, /* autogen autogen */ REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS = 174, /* autogen autogen */ - REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME = 175, /* autogen autogen */ - REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID = 176, /* autogen autogen */ - REMOTE_PROC_NWFILTER_GET_XML_DESC = 177, /* autogen autogen */ - REMOTE_PROC_NUM_OF_NWFILTERS = 178, /* autogen autogen */ - REMOTE_PROC_LIST_NWFILTERS = 179, /* autogen autogen */ - REMOTE_PROC_NWFILTER_DEFINE_XML = 180, /* autogen autogen */ - - REMOTE_PROC_NWFILTER_UNDEFINE = 181, /* autogen autogen */ + REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME = 175, /* autogen autogen priority:high */ + REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID = 176, /* autogen autogen priority:high */ + REMOTE_PROC_NWFILTER_GET_XML_DESC = 177, /* autogen autogen priority:high */ + REMOTE_PROC_NUM_OF_NWFILTERS = 178, /* autogen autogen priority:high */ + REMOTE_PROC_LIST_NWFILTERS = 179, /* autogen autogen priority:high */ + REMOTE_PROC_NWFILTER_DEFINE_XML = 180, /* autogen autogen priority:high */ + + REMOTE_PROC_NWFILTER_UNDEFINE = 181, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_MANAGED_SAVE = 182, /* autogen autogen */ REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE = 183, /* autogen autogen */ REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE = 184, /* autogen autogen */ REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML = 185, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SNAPSHOT_GET_XML_DESC = 186, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 187, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 188, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 189, /* autogen autogen */ + REMOTE_PROC_DOMAIN_SNAPSHOT_GET_XML_DESC = 186, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 187, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 188, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 189, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT = 190, /* autogen autogen */ REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191, /* autogen autogen */ @@ -2442,8 +2448,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, /* autogen autogen */ REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201, /* autogen autogen | readstream@2 */ - REMOTE_PROC_DOMAIN_IS_UPDATED = 202, /* autogen autogen */ - REMOTE_PROC_GET_SYSINFO = 203, /* autogen autogen */ + REMOTE_PROC_DOMAIN_IS_UPDATED = 202, /* autogen autogen priority:high */ + REMOTE_PROC_GET_SYSINFO = 203, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS = 204, /* autogen autogen */ REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS = 205, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, /* skipgen skipgen */ @@ -2453,7 +2459,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_INJECT_NMI = 210, /* autogen autogen */ REMOTE_PROC_DOMAIN_SCREENSHOT = 211, /* autogen autogen | readstream@1 */ - REMOTE_PROC_DOMAIN_GET_STATE = 212, /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_GET_STATE = 212, /* skipgen skipgen priority:high */ REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3 = 213, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3 = 214, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 215, /* autogen skipgen | writestream@1 */ @@ -2469,17 +2475,17 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR = 224, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 225, /* autogen autogen */ REMOTE_PROC_DOMAIN_SEND_KEY = 226, /* autogen autogen */ - REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen */ - REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen */ - REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen */ + REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen priority:high */ + REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen priority:high */ + REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230, /* skipgen skipgen */ - REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS = 231, /* autogen autogen */ + REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS = 231, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_SAVE_FLAGS = 232, /* autogen autogen */ REMOTE_PROC_DOMAIN_RESTORE_FLAGS = 233, /* autogen autogen */ - REMOTE_PROC_DOMAIN_DESTROY_FLAGS = 234, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC = 235, /* autogen autogen */ - REMOTE_PROC_DOMAIN_SAVE_IMAGE_DEFINE_XML = 236, /* autogen autogen */ + REMOTE_PROC_DOMAIN_DESTROY_FLAGS = 234, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC = 235, /* autogen autogen priority:high */ + REMOTE_PROC_DOMAIN_SAVE_IMAGE_DEFINE_XML = 236, /* autogen autogen priority:high */ REMOTE_PROC_DOMAIN_BLOCK_JOB_ABORT = 237, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_BLOCK_JOB_INFO = 238, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_BLOCK_JOB_SET_SPEED = 239, /* autogen autogen */ @@ -2492,10 +2498,16 @@ enum remote_procedure { * Notice how the entries are grouped in sets of 10 ? * Nice isn't it. Please keep it this way when adding more. * - * Each function must have a two-word comment. The first word is + * Each function must have a three-word comment. The first word is * whether gendispatch.pl handles daemon, the second whether * it handles src/remote. Additional flags can be specified after a * pipe. + * The last argument describes priority of API. There are two accepted + * values: low, high; Each API that might eventually access hypervisor's + * monitor (and thus block) MUST fall into low priority. However, there + * are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY + * be marked as high priority. If in doubt, it's safe to choose low. + * Low is taken as default, and thus can be left out. * * The (readstream|writestream)@ flag lets daemon and src/remote * create a stream. The direction is defined from the src/remote point diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 2be903352c..fcd1a263fc 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -146,12 +146,13 @@ while () { } if ($opt_b or $opt_k) { - if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(.*)\*\/\s*$/)) { + if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(\|.*)?\s+(priority:(\S+))?\s*\*\/\s*$/)) { die "invalid generator flags for ${procprefix}_PROC_${name}" } my $genmode = $opt_b ? $1 : $2; my $genflags = $3; + my $priority = defined $5 ? $5 : "low"; if ($genmode eq "autogen") { push(@autogen, $ProcName); @@ -171,6 +172,16 @@ while () { } else { $calls{$name}->{streamflag} = "none"; } + + # for now, we distinguish only two levels of prioroty: + # low (0) and high (1) + if ($priority eq "high") { + $calls{$name}->{priority} = 1; + } elsif ($priority eq "low") { + $calls{$name}->{priority} = 0; + } else { + die "invalid priority ${priority} for ${procprefix}_PROC_${name}" + } } $calls[$id] = $calls{$name}; @@ -260,6 +271,7 @@ if ($opt_d) { print "$_:\n"; print " name $calls{$_}->{name} ($calls{$_}->{ProcName})\n"; print " $calls{$_}->{args} -> $calls{$_}->{ret}\n"; + print " priority -> $calls{$_}->{priority}\n"; } } @@ -935,7 +947,7 @@ elsif ($opt_b) { print "virNetServerProgramProc ${structprefix}Procs[] = {\n"; for ($id = 0 ; $id <= $#calls ; $id++) { - my ($comment, $name, $argtype, $arglen, $argfilter, $retlen, $retfilter); + my ($comment, $name, $argtype, $arglen, $argfilter, $retlen, $retfilter, $priority); if (defined $calls[$id] && !$calls[$id]->{msg}) { $comment = "/* Method $calls[$id]->{ProcName} => $id */"; @@ -958,7 +970,9 @@ elsif ($opt_b) { $retfilter = "xdr_void"; } - print "{ $comment\n ${name},\n $arglen,\n (xdrproc_t)$argfilter,\n $retlen,\n (xdrproc_t)$retfilter,\n true \n},\n"; + $priority = defined $calls[$id]->{priority} ? $calls[$id]->{priority} : 0; + + print "{ $comment\n ${name},\n $arglen,\n (xdrproc_t)$argfilter,\n $retlen,\n (xdrproc_t)$retfilter,\n true,\n $priority\n},\n"; } print "};\n"; print "size_t ${structprefix}NProcs = ARRAY_CARDINALITY(${structprefix}Procs);\n"; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index fd8781d675..d71ed18d72 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -64,6 +64,7 @@ typedef virNetServerJob *virNetServerJobPtr; struct _virNetServerJob { virNetServerClientPtr client; virNetMessagePtr msg; + virNetServerProgramPtr prog; }; struct _virNetServer { @@ -128,61 +129,41 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque) { virNetServerPtr srv = opaque; virNetServerJobPtr job = jobOpaque; - virNetServerProgramPtr prog = NULL; - size_t i; - - virNetServerLock(srv); - VIR_DEBUG("server=%p client=%p message=%p", - srv, job->client, job->msg); - for (i = 0 ; i < srv->nprograms ; i++) { - if (virNetServerProgramMatches(srv->programs[i], job->msg)) { - prog = srv->programs[i]; - break; - } - } + VIR_DEBUG("server=%p client=%p message=%p prog=%p", + srv, job->client, job->msg, job->prog); - if (!prog) { - if (virNetServerProgramUnknownError(job->client, - job->msg, - &job->msg->header) < 0) - goto error; - else - goto cleanup; - } - - virNetServerProgramRef(prog); - virNetServerUnlock(srv); - - if (virNetServerProgramDispatch(prog, + if (virNetServerProgramDispatch(job->prog, srv, job->client, job->msg) < 0) goto error; virNetServerLock(srv); - -cleanup: - virNetServerProgramFree(prog); + virNetServerProgramFree(job->prog); virNetServerUnlock(srv); virNetServerClientFree(job->client); VIR_FREE(job); return; error: + virNetServerProgramFree(job->prog); virNetMessageFree(job->msg); virNetServerClientClose(job->client); - goto cleanup; + virNetServerClientFree(job->client); + VIR_FREE(job); } - static int virNetServerDispatchNewMessage(virNetServerClientPtr client, virNetMessagePtr msg, void *opaque) { virNetServerPtr srv = opaque; virNetServerJobPtr job; - int ret; + virNetServerProgramPtr prog = NULL; + unsigned int priority = 0; + size_t i; + int ret = -1; VIR_DEBUG("server=%p client=%p message=%p", srv, client, msg); @@ -196,8 +177,29 @@ static int virNetServerDispatchNewMessage(virNetServerClientPtr client, job->msg = msg; virNetServerLock(srv); - if ((ret = virThreadPoolSendJob(srv->workers, job)) < 0) + for (i = 0 ; i < srv->nprograms ; i++) { + if (virNetServerProgramMatches(srv->programs[i], job->msg)) { + prog = srv->programs[i]; + break; + } + } + + if (!prog) { + virNetServerProgramUnknownError(client, msg, &msg->header); + goto cleanup; + } + + virNetServerProgramRef(prog); + job->prog = prog; + priority = virNetServerProgramGetPriority(prog, msg->header.proc); + + ret = virThreadPoolSendJob(srv->workers, priority, job); + +cleanup: + if (ret < 0) { VIR_FREE(job); + virNetServerProgramFree(prog); + } virNetServerUnlock(srv); return ret; @@ -274,6 +276,7 @@ static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED virNetServerPtr virNetServerNew(size_t min_workers, size_t max_workers, + size_t priority_workers, size_t max_clients, const char *mdnsGroupName, bool connectDBus ATTRIBUTE_UNUSED, @@ -290,6 +293,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, srv->refs = 1; if (!(srv->workers = virThreadPoolNew(min_workers, max_workers, + priority_workers, virNetServerHandleJob, srv))) goto error; diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index 324cfb7186..cc9d039adc 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -39,6 +39,7 @@ typedef int (*virNetServerClientInitHook)(virNetServerPtr srv, virNetServerPtr virNetServerNew(size_t min_workers, size_t max_workers, + size_t priority_workers, size_t max_clients, const char *mdnsGroupName, bool connectDBus, diff --git a/src/rpc/virnetserverprogram.c b/src/rpc/virnetserverprogram.c index 643a97dba0..334a0bf7a5 100644 --- a/src/rpc/virnetserverprogram.c +++ b/src/rpc/virnetserverprogram.c @@ -108,6 +108,17 @@ static virNetServerProgramProcPtr virNetServerProgramGetProc(virNetServerProgram return &prog->procs[procedure]; } +unsigned int +virNetServerProgramGetPriority(virNetServerProgramPtr prog, + int procedure) +{ + virNetServerProgramProcPtr proc = virNetServerProgramGetProc(prog, procedure); + + if (!proc) + return 0; + + return proc->priority; +} static int virNetServerProgramSendError(unsigned program, diff --git a/src/rpc/virnetserverprogram.h b/src/rpc/virnetserverprogram.h index 06b16d72bb..9dabf92167 100644 --- a/src/rpc/virnetserverprogram.h +++ b/src/rpc/virnetserverprogram.h @@ -53,6 +53,7 @@ struct _virNetServerProgramProc { size_t ret_len; xdrproc_t ret_filter; bool needAuth; + unsigned int priority; }; virNetServerProgramPtr virNetServerProgramNew(unsigned program, @@ -63,6 +64,9 @@ virNetServerProgramPtr virNetServerProgramNew(unsigned program, int virNetServerProgramGetID(virNetServerProgramPtr prog); int virNetServerProgramGetVersion(virNetServerProgramPtr prog); +unsigned int virNetServerProgramGetPriority(virNetServerProgramPtr prog, + int procedure); + void virNetServerProgramRef(virNetServerProgramPtr prog); int virNetServerProgramMatches(virNetServerProgramPtr prog, diff --git a/src/util/threadpool.c b/src/util/threadpool.c index 821759133d..70a75c0512 100644 --- a/src/util/threadpool.c +++ b/src/util/threadpool.c @@ -37,7 +37,9 @@ typedef struct _virThreadPoolJob virThreadPoolJob; typedef virThreadPoolJob *virThreadPoolJobPtr; struct _virThreadPoolJob { + virThreadPoolJobPtr prev; virThreadPoolJobPtr next; + unsigned int priority; void *data; }; @@ -47,7 +49,8 @@ typedef virThreadPoolJobList *virThreadPoolJobListPtr; struct _virThreadPoolJobList { virThreadPoolJobPtr head; - virThreadPoolJobPtr *tail; + virThreadPoolJobPtr tail; + virThreadPoolJobPtr firstPrio; }; @@ -57,6 +60,7 @@ struct _virThreadPool { virThreadPoolJobFunc jobFunc; void *jobOpaque; virThreadPoolJobList jobList; + size_t jobQueueDepth; virMutex mutex; virCond cond; @@ -66,33 +70,75 @@ struct _virThreadPool { size_t freeWorkers; size_t nWorkers; virThreadPtr workers; + + size_t nPrioWorkers; + virThreadPtr prioWorkers; + virCond prioCond; +}; + +struct virThreadPoolWorkerData { + virThreadPoolPtr pool; + virCondPtr cond; + bool priority; }; static void virThreadPoolWorker(void *opaque) { - virThreadPoolPtr pool = opaque; + struct virThreadPoolWorkerData *data = opaque; + virThreadPoolPtr pool = data->pool; + virCondPtr cond = data->cond; + bool priority = data->priority; + virThreadPoolJobPtr job = NULL; + + VIR_FREE(data); virMutexLock(&pool->mutex); while (1) { while (!pool->quit && - !pool->jobList.head) { - pool->freeWorkers++; - if (virCondWait(&pool->cond, &pool->mutex) < 0) { - pool->freeWorkers--; + ((!priority && !pool->jobList.head) || + (priority && !pool->jobList.firstPrio))) { + if (!priority) + pool->freeWorkers++; + if (virCondWait(cond, &pool->mutex) < 0) { + if (!priority) + pool->freeWorkers--; goto out; } - pool->freeWorkers--; + if (!priority) + pool->freeWorkers--; } if (pool->quit) break; - virThreadPoolJobPtr job = pool->jobList.head; - pool->jobList.head = pool->jobList.head->next; - job->next = NULL; - if (pool->jobList.tail == &job->next) - pool->jobList.tail = &pool->jobList.head; + if (priority) { + job = pool->jobList.firstPrio; + } else { + job = pool->jobList.head; + } + + if (job == pool->jobList.firstPrio) { + virThreadPoolJobPtr tmp = job->next; + while (tmp) { + if (tmp->priority) { + break; + } + tmp = tmp->next; + } + pool->jobList.firstPrio = tmp; + } + + if (job->prev) + job->prev->next = job->next; + else + pool->jobList.head = job->next; + if (job->next) + job->next->prev = job->prev; + else + pool->jobList.tail = job->prev; + + pool->jobQueueDepth--; virMutexUnlock(&pool->mutex); (pool->jobFunc)(job->data, pool->jobOpaque); @@ -101,19 +147,24 @@ static void virThreadPoolWorker(void *opaque) } out: - pool->nWorkers--; - if (pool->nWorkers == 0) + if (priority) + pool->nPrioWorkers--; + else + pool->nWorkers--; + if (pool->nWorkers == 0 && pool->nPrioWorkers==0) virCondSignal(&pool->quit_cond); virMutexUnlock(&pool->mutex); } virThreadPoolPtr virThreadPoolNew(size_t minWorkers, size_t maxWorkers, + size_t prioWorkers, virThreadPoolJobFunc func, void *opaque) { virThreadPoolPtr pool; size_t i; + struct virThreadPoolWorkerData *data = NULL; if (minWorkers > maxWorkers) minWorkers = maxWorkers; @@ -123,8 +174,7 @@ virThreadPoolPtr virThreadPoolNew(size_t minWorkers, return NULL; } - pool->jobList.head = NULL; - pool->jobList.tail = &pool->jobList.head; + pool->jobList.tail = pool->jobList.head = NULL; pool->jobFunc = func; pool->jobOpaque = opaque; @@ -141,18 +191,51 @@ virThreadPoolPtr virThreadPoolNew(size_t minWorkers, pool->maxWorkers = maxWorkers; for (i = 0; i < minWorkers; i++) { + if (VIR_ALLOC(data) < 0) { + virReportOOMError(); + goto error; + } + data->pool = pool; + data->cond = &pool->cond; + if (virThreadCreate(&pool->workers[i], true, virThreadPoolWorker, - pool) < 0) { + data) < 0) { goto error; } pool->nWorkers++; } + 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) { + virReportOOMError(); + goto error; + } + data->pool = pool; + data->cond = &pool->prioCond; + data->priority = true; + + if (virThreadCreate(&pool->prioWorkers[i], + true, + virThreadPoolWorker, + data) < 0) { + goto error; + } + pool->nPrioWorkers++; + } + } + return pool; error: + VIR_FREE(data); virThreadPoolFree(pool); return NULL; @@ -161,17 +244,22 @@ error: void virThreadPoolFree(virThreadPoolPtr pool) { virThreadPoolJobPtr job; + bool priority = false; if (!pool) return; virMutexLock(&pool->mutex); pool->quit = true; - if (pool->nWorkers > 0) { + if (pool->nWorkers > 0) virCondBroadcast(&pool->cond); - ignore_value(virCondWait(&pool->quit_cond, &pool->mutex)); + if (pool->nPrioWorkers > 0) { + priority = true; + virCondBroadcast(&pool->prioCond); } + ignore_value(virCondWait(&pool->quit_cond, &pool->mutex)); + while ((job = pool->jobList.head)) { pool->jobList.head = pool->jobList.head->next; VIR_FREE(job); @@ -182,10 +270,19 @@ void virThreadPoolFree(virThreadPoolPtr pool) virMutexDestroy(&pool->mutex); ignore_value(virCondDestroy(&pool->quit_cond)); ignore_value(virCondDestroy(&pool->cond)); + if (priority) { + VIR_FREE(pool->prioWorkers); + ignore_value(virCondDestroy(&pool->prioCond)); + } VIR_FREE(pool); } +/* + * @priority - job priority + * Return: 0 on success, -1 otherwise + */ int virThreadPoolSendJob(virThreadPoolPtr pool, + unsigned int priority, void *jobData) { virThreadPoolJobPtr job; @@ -194,7 +291,7 @@ int virThreadPoolSendJob(virThreadPoolPtr pool, if (pool->quit) goto error; - if (pool->freeWorkers == 0 && + if (pool->freeWorkers - pool->jobQueueDepth <= 0 && pool->nWorkers < pool->maxWorkers) { if (VIR_EXPAND_N(pool->workers, pool->nWorkers, 1) < 0) { virReportOOMError(); @@ -216,13 +313,26 @@ int virThreadPoolSendJob(virThreadPoolPtr pool, } job->data = jobData; - job->next = NULL; - *pool->jobList.tail = job; - pool->jobList.tail = &(*pool->jobList.tail)->next; + job->priority = priority; + + job->prev = pool->jobList.tail; + if (pool->jobList.tail) + pool->jobList.tail->next = job; + pool->jobList.tail = job; + + if (!pool->jobList.head) + pool->jobList.head = job; + + if (priority && !pool->jobList.firstPrio) + pool->jobList.firstPrio = job; + + pool->jobQueueDepth++; virCondSignal(&pool->cond); - virMutexUnlock(&pool->mutex); + if (priority) + virCondSignal(&pool->prioCond); + virMutexUnlock(&pool->mutex); return 0; error: diff --git a/src/util/threadpool.h b/src/util/threadpool.h index 8b8c6768a8..c4612ad1a9 100644 --- a/src/util/threadpool.h +++ b/src/util/threadpool.h @@ -35,12 +35,14 @@ typedef void (*virThreadPoolJobFunc)(void *jobdata, void *opaque); virThreadPoolPtr virThreadPoolNew(size_t minWorkers, size_t maxWorkers, + size_t prioWorkers, virThreadPoolJobFunc func, - void *opaque) ATTRIBUTE_NONNULL(3); + void *opaque) ATTRIBUTE_NONNULL(4); void virThreadPoolFree(virThreadPoolPtr pool); int virThreadPoolSendJob(virThreadPoolPtr pool, + unsigned int priority, void *jobdata) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -- GitLab