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_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 */ - 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_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_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 */ - REMOTE_PROC_NUM_OF_NETWORKS = 52, /* autogen autogen */ + 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_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 */ - 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_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_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 */ - REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /* autogen autogen */ + 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_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 */ - REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /* autogen autogen */ + 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_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 */ - 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_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_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 */ - 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_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_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 */ + 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); + VIR_DEBUG("server=%p client=%p message=%p prog=%p", + srv, job->client, job->msg, job->prog); - for (i = 0 ; i < srv->nprograms ; i++) { - if (virNetServerProgramMatches(srv->programs[i], job->msg)) { - prog = srv->programs[i]; - break; - } - } - - 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;