1f1b3ccfaSKevin Wolf /* 2f1b3ccfaSKevin Wolf * QEMU Management Protocol commands 3f1b3ccfaSKevin Wolf * 4f1b3ccfaSKevin Wolf * Copyright IBM, Corp. 2011 5f1b3ccfaSKevin Wolf * 6f1b3ccfaSKevin Wolf * Authors: 7f1b3ccfaSKevin Wolf * Anthony Liguori <aliguori@us.ibm.com> 8f1b3ccfaSKevin Wolf * 9f1b3ccfaSKevin Wolf * This work is licensed under the terms of the GNU GPL, version 2. See 10f1b3ccfaSKevin Wolf * the COPYING file in the top-level directory. 11f1b3ccfaSKevin Wolf * 12f1b3ccfaSKevin Wolf * Contributions after 2012-01-13 are licensed under the terms of the 13f1b3ccfaSKevin Wolf * GNU GPL, version 2 or (at your option) any later version. 14f1b3ccfaSKevin Wolf */ 15f1b3ccfaSKevin Wolf 16f1b3ccfaSKevin Wolf #include "qemu/osdep.h" 17f1b3ccfaSKevin Wolf #include "qemu/cutils.h" 18f1b3ccfaSKevin Wolf #include "qemu/option.h" 19f1b3ccfaSKevin Wolf #include "monitor/monitor.h" 203125af29SMarkus Armbruster #include "monitor/qmp-helpers.h" 21f1b3ccfaSKevin Wolf #include "sysemu/sysemu.h" 22f1b3ccfaSKevin Wolf #include "qemu/config-file.h" 23f1b3ccfaSKevin Wolf #include "qemu/uuid.h" 24f1b3ccfaSKevin Wolf #include "chardev/char.h" 25f1b3ccfaSKevin Wolf #include "sysemu/kvm.h" 2654d31236SMarkus Armbruster #include "sysemu/runstate.h" 27e6dba048SAlejandro Jimenez #include "sysemu/runstate-action.h" 28f1b3ccfaSKevin Wolf #include "sysemu/blockdev.h" 29f1b3ccfaSKevin Wolf #include "sysemu/block-backend.h" 30f1b3ccfaSKevin Wolf #include "qapi/error.h" 3127c9188fSPhilippe Mathieu-Daudé #include "qapi/qapi-commands-acpi.h" 325a16818bSKevin Wolf #include "qapi/qapi-commands-block.h" 33fa4dcf57SKevin Wolf #include "qapi/qapi-commands-control.h" 348ac25c84SMarkus Armbruster #include "qapi/qapi-commands-machine.h" 35f1b3ccfaSKevin Wolf #include "qapi/qapi-commands-misc.h" 36b9f88dc0SMark Kanda #include "qapi/qapi-commands-stats.h" 3737087fdeSDaniel P. Berrangé #include "qapi/type-helpers.h" 38ca411b7cSDaniel P. Berrangé #include "exec/ramlist.h" 39f1b3ccfaSKevin Wolf #include "hw/mem/memory-device.h" 40f1b3ccfaSKevin Wolf #include "hw/acpi/acpi_dev_interface.h" 4191f2fa70SDaniel P. Berrangé #include "hw/intc/intc.h" 428dbbca5cSDaniel P. Berrangé #include "hw/rdma/rdma.h" 43b9f88dc0SMark Kanda #include "monitor/stats.h" 44f1b3ccfaSKevin Wolf 45f1b3ccfaSKevin Wolf NameInfo *qmp_query_name(Error **errp) 46f1b3ccfaSKevin Wolf { 47f1b3ccfaSKevin Wolf NameInfo *info = g_malloc0(sizeof(*info)); 48f1b3ccfaSKevin Wolf 49f1b3ccfaSKevin Wolf info->name = g_strdup(qemu_name); 50f1b3ccfaSKevin Wolf return info; 51f1b3ccfaSKevin Wolf } 52f1b3ccfaSKevin Wolf 53f1b3ccfaSKevin Wolf KvmInfo *qmp_query_kvm(Error **errp) 54f1b3ccfaSKevin Wolf { 55f1b3ccfaSKevin Wolf KvmInfo *info = g_malloc0(sizeof(*info)); 56f1b3ccfaSKevin Wolf 57f1b3ccfaSKevin Wolf info->enabled = kvm_enabled(); 584f9205beSPeter Maydell info->present = accel_find("kvm"); 59f1b3ccfaSKevin Wolf 60f1b3ccfaSKevin Wolf return info; 61f1b3ccfaSKevin Wolf } 62f1b3ccfaSKevin Wolf 63f1b3ccfaSKevin Wolf UuidInfo *qmp_query_uuid(Error **errp) 64f1b3ccfaSKevin Wolf { 65f1b3ccfaSKevin Wolf UuidInfo *info = g_malloc0(sizeof(*info)); 66f1b3ccfaSKevin Wolf 67f1b3ccfaSKevin Wolf info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid); 68f1b3ccfaSKevin Wolf return info; 69f1b3ccfaSKevin Wolf } 70f1b3ccfaSKevin Wolf 71f1b3ccfaSKevin Wolf void qmp_quit(Error **errp) 72f1b3ccfaSKevin Wolf { 73e6dba048SAlejandro Jimenez shutdown_action = SHUTDOWN_ACTION_POWEROFF; 74f1b3ccfaSKevin Wolf qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); 75f1b3ccfaSKevin Wolf } 76f1b3ccfaSKevin Wolf 77f1b3ccfaSKevin Wolf void qmp_stop(Error **errp) 78f1b3ccfaSKevin Wolf { 79f1b3ccfaSKevin Wolf /* if there is a dump in background, we should wait until the dump 80f1b3ccfaSKevin Wolf * finished */ 81544803c7SMarc-André Lureau if (qemu_system_dump_in_progress()) { 82f1b3ccfaSKevin Wolf error_setg(errp, "There is a dump in process, please wait."); 83f1b3ccfaSKevin Wolf return; 84f1b3ccfaSKevin Wolf } 85f1b3ccfaSKevin Wolf 86f1b3ccfaSKevin Wolf if (runstate_check(RUN_STATE_INMIGRATE)) { 87f1b3ccfaSKevin Wolf autostart = 0; 88f1b3ccfaSKevin Wolf } else { 89f1b3ccfaSKevin Wolf vm_stop(RUN_STATE_PAUSED); 90f1b3ccfaSKevin Wolf } 91f1b3ccfaSKevin Wolf } 92f1b3ccfaSKevin Wolf 93f1b3ccfaSKevin Wolf void qmp_system_reset(Error **errp) 94f1b3ccfaSKevin Wolf { 95f1b3ccfaSKevin Wolf qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); 96f1b3ccfaSKevin Wolf } 97f1b3ccfaSKevin Wolf 98ec48595eSVladimir Sementsov-Ogievskiy void qmp_system_powerdown(Error **errp) 99f1b3ccfaSKevin Wolf { 100f1b3ccfaSKevin Wolf qemu_system_powerdown_request(); 101f1b3ccfaSKevin Wolf } 102f1b3ccfaSKevin Wolf 103f1b3ccfaSKevin Wolf void qmp_cont(Error **errp) 104f1b3ccfaSKevin Wolf { 105f1b3ccfaSKevin Wolf BlockBackend *blk; 10668d00e42SVladimir Sementsov-Ogievskiy BlockJob *job; 107f1b3ccfaSKevin Wolf Error *local_err = NULL; 108f1b3ccfaSKevin Wolf 109f1b3ccfaSKevin Wolf /* if there is a dump in background, we should wait until the dump 110f1b3ccfaSKevin Wolf * finished */ 111544803c7SMarc-André Lureau if (qemu_system_dump_in_progress()) { 112f1b3ccfaSKevin Wolf error_setg(errp, "There is a dump in process, please wait."); 113f1b3ccfaSKevin Wolf return; 114f1b3ccfaSKevin Wolf } 115f1b3ccfaSKevin Wolf 116f1b3ccfaSKevin Wolf if (runstate_needs_reset()) { 117f1b3ccfaSKevin Wolf error_setg(errp, "Resetting the Virtual Machine is required"); 118f1b3ccfaSKevin Wolf return; 119f1b3ccfaSKevin Wolf } else if (runstate_check(RUN_STATE_SUSPENDED)) { 120f1b3ccfaSKevin Wolf return; 121f1b3ccfaSKevin Wolf } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { 122f1b3ccfaSKevin Wolf error_setg(errp, "Migration is not finalized yet"); 123f1b3ccfaSKevin Wolf return; 124f1b3ccfaSKevin Wolf } 125f1b3ccfaSKevin Wolf 126f1b3ccfaSKevin Wolf for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { 127f1b3ccfaSKevin Wolf blk_iostatus_reset(blk); 128f1b3ccfaSKevin Wolf } 129f1b3ccfaSKevin Wolf 130880eeec6SEmanuele Giuseppe Esposito WITH_JOB_LOCK_GUARD() { 131880eeec6SEmanuele Giuseppe Esposito for (job = block_job_next_locked(NULL); job; 132880eeec6SEmanuele Giuseppe Esposito job = block_job_next_locked(job)) { 133880eeec6SEmanuele Giuseppe Esposito block_job_iostatus_reset_locked(job); 134880eeec6SEmanuele Giuseppe Esposito } 13568d00e42SVladimir Sementsov-Ogievskiy } 13668d00e42SVladimir Sementsov-Ogievskiy 137f1b3ccfaSKevin Wolf /* Continuing after completed migration. Images have been inactivated to 138f1b3ccfaSKevin Wolf * allow the destination to take control. Need to get control back now. 139f1b3ccfaSKevin Wolf * 140f1b3ccfaSKevin Wolf * If there are no inactive block nodes (e.g. because the VM was just 141f1b3ccfaSKevin Wolf * paused rather than completing a migration), bdrv_inactivate_all() simply 142f1b3ccfaSKevin Wolf * doesn't do anything. */ 1433b717194SEmanuele Giuseppe Esposito bdrv_activate_all(&local_err); 144f1b3ccfaSKevin Wolf if (local_err) { 145f1b3ccfaSKevin Wolf error_propagate(errp, local_err); 146f1b3ccfaSKevin Wolf return; 147f1b3ccfaSKevin Wolf } 148f1b3ccfaSKevin Wolf 149f1b3ccfaSKevin Wolf if (runstate_check(RUN_STATE_INMIGRATE)) { 150f1b3ccfaSKevin Wolf autostart = 1; 151f1b3ccfaSKevin Wolf } else { 152f1b3ccfaSKevin Wolf vm_start(); 153f1b3ccfaSKevin Wolf } 154f1b3ccfaSKevin Wolf } 155f1b3ccfaSKevin Wolf 156f1b3ccfaSKevin Wolf void qmp_system_wakeup(Error **errp) 157f1b3ccfaSKevin Wolf { 158f1b3ccfaSKevin Wolf if (!qemu_wakeup_suspend_enabled()) { 159f1b3ccfaSKevin Wolf error_setg(errp, 160f1b3ccfaSKevin Wolf "wake-up from suspend is not supported by this guest"); 161f1b3ccfaSKevin Wolf return; 162f1b3ccfaSKevin Wolf } 163f1b3ccfaSKevin Wolf 164f1b3ccfaSKevin Wolf qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); 165f1b3ccfaSKevin Wolf } 166f1b3ccfaSKevin Wolf 167f1b3ccfaSKevin Wolf void qmp_add_client(const char *protocol, const char *fdname, 168f1b3ccfaSKevin Wolf bool has_skipauth, bool skipauth, bool has_tls, bool tls, 169f1b3ccfaSKevin Wolf Error **errp) 170f1b3ccfaSKevin Wolf { 171*f916a175SMarkus Armbruster static const struct { 1723125af29SMarkus Armbruster const char *name; 1733125af29SMarkus Armbruster bool (*add_client)(int fd, bool has_skipauth, bool skipauth, 1743125af29SMarkus Armbruster bool has_tls, bool tls, Error **errp); 1753125af29SMarkus Armbruster } protocol_table[] = { 1763125af29SMarkus Armbruster { "spice", qmp_add_client_spice }, 1773125af29SMarkus Armbruster #ifdef CONFIG_VNC 1783125af29SMarkus Armbruster { "vnc", qmp_add_client_vnc }, 1793125af29SMarkus Armbruster #endif 1803125af29SMarkus Armbruster #ifdef CONFIG_DBUS_DISPLAY 1813125af29SMarkus Armbruster { "@dbus-display", qmp_add_client_dbus_display }, 1823125af29SMarkus Armbruster #endif 1833125af29SMarkus Armbruster }; 184f1b3ccfaSKevin Wolf Chardev *s; 1853125af29SMarkus Armbruster int fd, i; 186f1b3ccfaSKevin Wolf 187947e4744SKevin Wolf fd = monitor_get_fd(monitor_cur(), fdname, errp); 188f1b3ccfaSKevin Wolf if (fd < 0) { 189f1b3ccfaSKevin Wolf return; 190f1b3ccfaSKevin Wolf } 191f1b3ccfaSKevin Wolf 1923125af29SMarkus Armbruster for (i = 0; i < ARRAY_SIZE(protocol_table); i++) { 1933125af29SMarkus Armbruster if (!strcmp(protocol, protocol_table[i].name)) { 1943125af29SMarkus Armbruster if (!protocol_table[i].add_client(fd, has_skipauth, skipauth, 1953125af29SMarkus Armbruster has_tls, tls, errp)) { 196f1b3ccfaSKevin Wolf close(fd); 1973125af29SMarkus Armbruster } 198f1b3ccfaSKevin Wolf return; 199f1b3ccfaSKevin Wolf } 200f1b3ccfaSKevin Wolf } 2013125af29SMarkus Armbruster 20261d7f2a9SMarkus Armbruster s = qemu_chr_find(protocol); 20361d7f2a9SMarkus Armbruster if (!s) { 20461d7f2a9SMarkus Armbruster error_setg(errp, "protocol '%s' is invalid", protocol); 20561d7f2a9SMarkus Armbruster close(fd); 20661d7f2a9SMarkus Armbruster return; 20761d7f2a9SMarkus Armbruster } 208f1b3ccfaSKevin Wolf if (qemu_chr_add_client(s, fd) < 0) { 209f1b3ccfaSKevin Wolf error_setg(errp, "failed to add client"); 210f1b3ccfaSKevin Wolf close(fd); 211f1b3ccfaSKevin Wolf return; 212f1b3ccfaSKevin Wolf } 213f1b3ccfaSKevin Wolf } 214f1b3ccfaSKevin Wolf 215f1b3ccfaSKevin Wolf MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) 216f1b3ccfaSKevin Wolf { 217f1b3ccfaSKevin Wolf return qmp_memory_device_list(); 218f1b3ccfaSKevin Wolf } 219f1b3ccfaSKevin Wolf 220f1b3ccfaSKevin Wolf ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) 221f1b3ccfaSKevin Wolf { 222f1b3ccfaSKevin Wolf bool ambig; 223f1b3ccfaSKevin Wolf ACPIOSTInfoList *head = NULL; 224f1b3ccfaSKevin Wolf ACPIOSTInfoList **prev = &head; 225f1b3ccfaSKevin Wolf Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig); 226f1b3ccfaSKevin Wolf 227f1b3ccfaSKevin Wolf if (obj) { 228f1b3ccfaSKevin Wolf AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); 229f1b3ccfaSKevin Wolf AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj); 230f1b3ccfaSKevin Wolf 231f1b3ccfaSKevin Wolf adevc->ospm_status(adev, &prev); 232f1b3ccfaSKevin Wolf } else { 233f1b3ccfaSKevin Wolf error_setg(errp, "command is not supported, missing ACPI device"); 234f1b3ccfaSKevin Wolf } 235f1b3ccfaSKevin Wolf 236f1b3ccfaSKevin Wolf return head; 237f1b3ccfaSKevin Wolf } 238f1b3ccfaSKevin Wolf 239f1b3ccfaSKevin Wolf MemoryInfo *qmp_query_memory_size_summary(Error **errp) 240f1b3ccfaSKevin Wolf { 241b21e2380SMarkus Armbruster MemoryInfo *mem_info = g_new0(MemoryInfo, 1); 242b326b6eaSPaolo Bonzini MachineState *ms = MACHINE(qdev_get_machine()); 243f1b3ccfaSKevin Wolf 244b326b6eaSPaolo Bonzini mem_info->base_memory = ms->ram_size; 245f1b3ccfaSKevin Wolf 246f1b3ccfaSKevin Wolf mem_info->plugged_memory = get_plugged_memory_size(); 247f1b3ccfaSKevin Wolf mem_info->has_plugged_memory = 248f1b3ccfaSKevin Wolf mem_info->plugged_memory != (uint64_t)-1; 249f1b3ccfaSKevin Wolf 250f1b3ccfaSKevin Wolf return mem_info; 251f1b3ccfaSKevin Wolf } 2529cc07651SZihao Chang 2538dbbca5cSDaniel P. Berrangé static int qmp_x_query_rdma_foreach(Object *obj, void *opaque) 2548dbbca5cSDaniel P. Berrangé { 2558dbbca5cSDaniel P. Berrangé RdmaProvider *rdma; 2568dbbca5cSDaniel P. Berrangé RdmaProviderClass *k; 2578dbbca5cSDaniel P. Berrangé GString *buf = opaque; 2588dbbca5cSDaniel P. Berrangé 2598dbbca5cSDaniel P. Berrangé if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) { 2608dbbca5cSDaniel P. Berrangé rdma = RDMA_PROVIDER(obj); 2618dbbca5cSDaniel P. Berrangé k = RDMA_PROVIDER_GET_CLASS(obj); 2628dbbca5cSDaniel P. Berrangé if (k->format_statistics) { 2638dbbca5cSDaniel P. Berrangé k->format_statistics(rdma, buf); 2648dbbca5cSDaniel P. Berrangé } else { 2658dbbca5cSDaniel P. Berrangé g_string_append_printf(buf, 2668dbbca5cSDaniel P. Berrangé "RDMA statistics not available for %s.\n", 2678dbbca5cSDaniel P. Berrangé object_get_typename(obj)); 2688dbbca5cSDaniel P. Berrangé } 2698dbbca5cSDaniel P. Berrangé } 2708dbbca5cSDaniel P. Berrangé 2718dbbca5cSDaniel P. Berrangé return 0; 2728dbbca5cSDaniel P. Berrangé } 2738dbbca5cSDaniel P. Berrangé 2748dbbca5cSDaniel P. Berrangé HumanReadableText *qmp_x_query_rdma(Error **errp) 2758dbbca5cSDaniel P. Berrangé { 2768dbbca5cSDaniel P. Berrangé g_autoptr(GString) buf = g_string_new(""); 2778dbbca5cSDaniel P. Berrangé 2788dbbca5cSDaniel P. Berrangé object_child_foreach_recursive(object_get_root(), 2798dbbca5cSDaniel P. Berrangé qmp_x_query_rdma_foreach, buf); 2808dbbca5cSDaniel P. Berrangé 2818dbbca5cSDaniel P. Berrangé return human_readable_text_from_str(buf); 2828dbbca5cSDaniel P. Berrangé } 283ca411b7cSDaniel P. Berrangé 284ca411b7cSDaniel P. Berrangé HumanReadableText *qmp_x_query_ramblock(Error **errp) 285ca411b7cSDaniel P. Berrangé { 286ca411b7cSDaniel P. Berrangé g_autoptr(GString) buf = ram_block_format(); 287ca411b7cSDaniel P. Berrangé 288ca411b7cSDaniel P. Berrangé return human_readable_text_from_str(buf); 289ca411b7cSDaniel P. Berrangé } 29091f2fa70SDaniel P. Berrangé 29191f2fa70SDaniel P. Berrangé static int qmp_x_query_irq_foreach(Object *obj, void *opaque) 29291f2fa70SDaniel P. Berrangé { 29391f2fa70SDaniel P. Berrangé InterruptStatsProvider *intc; 29491f2fa70SDaniel P. Berrangé InterruptStatsProviderClass *k; 29591f2fa70SDaniel P. Berrangé GString *buf = opaque; 29691f2fa70SDaniel P. Berrangé 29791f2fa70SDaniel P. Berrangé if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { 29891f2fa70SDaniel P. Berrangé intc = INTERRUPT_STATS_PROVIDER(obj); 29991f2fa70SDaniel P. Berrangé k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); 30091f2fa70SDaniel P. Berrangé uint64_t *irq_counts; 30191f2fa70SDaniel P. Berrangé unsigned int nb_irqs, i; 30291f2fa70SDaniel P. Berrangé if (k->get_statistics && 30391f2fa70SDaniel P. Berrangé k->get_statistics(intc, &irq_counts, &nb_irqs)) { 30491f2fa70SDaniel P. Berrangé if (nb_irqs > 0) { 30591f2fa70SDaniel P. Berrangé g_string_append_printf(buf, "IRQ statistics for %s:\n", 30691f2fa70SDaniel P. Berrangé object_get_typename(obj)); 30791f2fa70SDaniel P. Berrangé for (i = 0; i < nb_irqs; i++) { 30891f2fa70SDaniel P. Berrangé if (irq_counts[i] > 0) { 30991f2fa70SDaniel P. Berrangé g_string_append_printf(buf, "%2d: %" PRId64 "\n", i, 31091f2fa70SDaniel P. Berrangé irq_counts[i]); 31191f2fa70SDaniel P. Berrangé } 31291f2fa70SDaniel P. Berrangé } 31391f2fa70SDaniel P. Berrangé } 31491f2fa70SDaniel P. Berrangé } else { 31591f2fa70SDaniel P. Berrangé g_string_append_printf(buf, 31691f2fa70SDaniel P. Berrangé "IRQ statistics not available for %s.\n", 31791f2fa70SDaniel P. Berrangé object_get_typename(obj)); 31891f2fa70SDaniel P. Berrangé } 31991f2fa70SDaniel P. Berrangé } 32091f2fa70SDaniel P. Berrangé 32191f2fa70SDaniel P. Berrangé return 0; 32291f2fa70SDaniel P. Berrangé } 32391f2fa70SDaniel P. Berrangé 32491f2fa70SDaniel P. Berrangé HumanReadableText *qmp_x_query_irq(Error **errp) 32591f2fa70SDaniel P. Berrangé { 32691f2fa70SDaniel P. Berrangé g_autoptr(GString) buf = g_string_new(""); 32791f2fa70SDaniel P. Berrangé 32891f2fa70SDaniel P. Berrangé object_child_foreach_recursive(object_get_root(), 32991f2fa70SDaniel P. Berrangé qmp_x_query_irq_foreach, buf); 33091f2fa70SDaniel P. Berrangé 33191f2fa70SDaniel P. Berrangé return human_readable_text_from_str(buf); 33291f2fa70SDaniel P. Berrangé } 333b9f88dc0SMark Kanda 334b9f88dc0SMark Kanda typedef struct StatsCallbacks { 335068cc51dSPaolo Bonzini StatsProvider provider; 336b9f88dc0SMark Kanda StatRetrieveFunc *stats_cb; 337b9f88dc0SMark Kanda SchemaRetrieveFunc *schemas_cb; 338b9f88dc0SMark Kanda QTAILQ_ENTRY(StatsCallbacks) next; 339b9f88dc0SMark Kanda } StatsCallbacks; 340b9f88dc0SMark Kanda 341b9f88dc0SMark Kanda static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks = 342b9f88dc0SMark Kanda QTAILQ_HEAD_INITIALIZER(stats_callbacks); 343b9f88dc0SMark Kanda 344068cc51dSPaolo Bonzini void add_stats_callbacks(StatsProvider provider, 345068cc51dSPaolo Bonzini StatRetrieveFunc *stats_fn, 346b9f88dc0SMark Kanda SchemaRetrieveFunc *schemas_fn) 347b9f88dc0SMark Kanda { 348b9f88dc0SMark Kanda StatsCallbacks *entry = g_new(StatsCallbacks, 1); 349068cc51dSPaolo Bonzini entry->provider = provider; 350b9f88dc0SMark Kanda entry->stats_cb = stats_fn; 351b9f88dc0SMark Kanda entry->schemas_cb = schemas_fn; 352b9f88dc0SMark Kanda 353b9f88dc0SMark Kanda QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next); 354b9f88dc0SMark Kanda } 355b9f88dc0SMark Kanda 356b9f88dc0SMark Kanda static bool invoke_stats_cb(StatsCallbacks *entry, 357b9f88dc0SMark Kanda StatsResultList **stats_results, 358068cc51dSPaolo Bonzini StatsFilter *filter, StatsRequest *request, 359b9f88dc0SMark Kanda Error **errp) 360b9f88dc0SMark Kanda { 36105e385d2SMarkus Armbruster ERRP_GUARD(); 362467ef823SPaolo Bonzini strList *targets = NULL; 363cf7405bcSPaolo Bonzini strList *names = NULL; 364b9f88dc0SMark Kanda 365068cc51dSPaolo Bonzini if (request) { 366068cc51dSPaolo Bonzini if (request->provider != entry->provider) { 367068cc51dSPaolo Bonzini return true; 368068cc51dSPaolo Bonzini } 369cf7405bcSPaolo Bonzini if (request->has_names && !request->names) { 370cf7405bcSPaolo Bonzini return true; 371cf7405bcSPaolo Bonzini } 372cf7405bcSPaolo Bonzini names = request->has_names ? request->names : NULL; 373068cc51dSPaolo Bonzini } 374068cc51dSPaolo Bonzini 375467ef823SPaolo Bonzini switch (filter->target) { 376467ef823SPaolo Bonzini case STATS_TARGET_VM: 377467ef823SPaolo Bonzini break; 378467ef823SPaolo Bonzini case STATS_TARGET_VCPU: 379467ef823SPaolo Bonzini if (filter->u.vcpu.has_vcpus) { 380467ef823SPaolo Bonzini if (!filter->u.vcpu.vcpus) { 381467ef823SPaolo Bonzini /* No targets allowed? Return no statistics. */ 382467ef823SPaolo Bonzini return true; 383467ef823SPaolo Bonzini } 384467ef823SPaolo Bonzini targets = filter->u.vcpu.vcpus; 385467ef823SPaolo Bonzini } 386467ef823SPaolo Bonzini break; 387467ef823SPaolo Bonzini default: 388467ef823SPaolo Bonzini abort(); 389467ef823SPaolo Bonzini } 390467ef823SPaolo Bonzini 391cf7405bcSPaolo Bonzini entry->stats_cb(stats_results, filter->target, names, targets, errp); 392b9f88dc0SMark Kanda if (*errp) { 393b9f88dc0SMark Kanda qapi_free_StatsResultList(*stats_results); 394b9f88dc0SMark Kanda *stats_results = NULL; 395b9f88dc0SMark Kanda return false; 396b9f88dc0SMark Kanda } 397b9f88dc0SMark Kanda return true; 398b9f88dc0SMark Kanda } 399b9f88dc0SMark Kanda 400b9f88dc0SMark Kanda StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp) 401b9f88dc0SMark Kanda { 402b9f88dc0SMark Kanda StatsResultList *stats_results = NULL; 403b9f88dc0SMark Kanda StatsCallbacks *entry; 404068cc51dSPaolo Bonzini StatsRequestList *request; 405b9f88dc0SMark Kanda 406b9f88dc0SMark Kanda QTAILQ_FOREACH(entry, &stats_callbacks, next) { 407068cc51dSPaolo Bonzini if (filter->has_providers) { 408068cc51dSPaolo Bonzini for (request = filter->providers; request; request = request->next) { 409068cc51dSPaolo Bonzini if (!invoke_stats_cb(entry, &stats_results, filter, 410068cc51dSPaolo Bonzini request->value, errp)) { 411b9f88dc0SMark Kanda break; 412b9f88dc0SMark Kanda } 413b9f88dc0SMark Kanda } 414068cc51dSPaolo Bonzini } else { 415068cc51dSPaolo Bonzini if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) { 416068cc51dSPaolo Bonzini break; 417068cc51dSPaolo Bonzini } 418068cc51dSPaolo Bonzini } 419068cc51dSPaolo Bonzini } 420b9f88dc0SMark Kanda 421b9f88dc0SMark Kanda return stats_results; 422b9f88dc0SMark Kanda } 423b9f88dc0SMark Kanda 424068cc51dSPaolo Bonzini StatsSchemaList *qmp_query_stats_schemas(bool has_provider, 425068cc51dSPaolo Bonzini StatsProvider provider, 426068cc51dSPaolo Bonzini Error **errp) 427b9f88dc0SMark Kanda { 42805e385d2SMarkus Armbruster ERRP_GUARD(); 429b9f88dc0SMark Kanda StatsSchemaList *stats_results = NULL; 430b9f88dc0SMark Kanda StatsCallbacks *entry; 431b9f88dc0SMark Kanda 432b9f88dc0SMark Kanda QTAILQ_FOREACH(entry, &stats_callbacks, next) { 433068cc51dSPaolo Bonzini if (!has_provider || provider == entry->provider) { 434b9f88dc0SMark Kanda entry->schemas_cb(&stats_results, errp); 435b9f88dc0SMark Kanda if (*errp) { 436b9f88dc0SMark Kanda qapi_free_StatsSchemaList(stats_results); 437b9f88dc0SMark Kanda return NULL; 438b9f88dc0SMark Kanda } 439b9f88dc0SMark Kanda } 440068cc51dSPaolo Bonzini } 441b9f88dc0SMark Kanda 442b9f88dc0SMark Kanda return stats_results; 443b9f88dc0SMark Kanda } 444b9f88dc0SMark Kanda 445b9f88dc0SMark Kanda void add_stats_entry(StatsResultList **stats_results, StatsProvider provider, 446b9f88dc0SMark Kanda const char *qom_path, StatsList *stats_list) 447b9f88dc0SMark Kanda { 448b9f88dc0SMark Kanda StatsResult *entry = g_new0(StatsResult, 1); 449b9f88dc0SMark Kanda 450b9f88dc0SMark Kanda entry->provider = provider; 451b9f88dc0SMark Kanda entry->qom_path = g_strdup(qom_path); 452b9f88dc0SMark Kanda entry->stats = stats_list; 453b9f88dc0SMark Kanda 454b9f88dc0SMark Kanda QAPI_LIST_PREPEND(*stats_results, entry); 455b9f88dc0SMark Kanda } 456b9f88dc0SMark Kanda 457b9f88dc0SMark Kanda void add_stats_schema(StatsSchemaList **schema_results, 458b9f88dc0SMark Kanda StatsProvider provider, StatsTarget target, 459b9f88dc0SMark Kanda StatsSchemaValueList *stats_list) 460b9f88dc0SMark Kanda { 461b9f88dc0SMark Kanda StatsSchema *entry = g_new0(StatsSchema, 1); 462b9f88dc0SMark Kanda 463b9f88dc0SMark Kanda entry->provider = provider; 464b9f88dc0SMark Kanda entry->target = target; 465b9f88dc0SMark Kanda entry->stats = stats_list; 466b9f88dc0SMark Kanda QAPI_LIST_PREPEND(*schema_results, entry); 467b9f88dc0SMark Kanda } 468467ef823SPaolo Bonzini 469467ef823SPaolo Bonzini bool apply_str_list_filter(const char *string, strList *list) 470467ef823SPaolo Bonzini { 471467ef823SPaolo Bonzini strList *str_list = NULL; 472467ef823SPaolo Bonzini 473467ef823SPaolo Bonzini if (!list) { 474467ef823SPaolo Bonzini return true; 475467ef823SPaolo Bonzini } 476467ef823SPaolo Bonzini for (str_list = list; str_list; str_list = str_list->next) { 477467ef823SPaolo Bonzini if (g_str_equal(string, str_list->value)) { 478467ef823SPaolo Bonzini return true; 479467ef823SPaolo Bonzini } 480467ef823SPaolo Bonzini } 481467ef823SPaolo Bonzini return false; 482467ef823SPaolo Bonzini } 483