1 /*
2  * qemu_driver.c: core driver methods for managing qemu guests
3  *
4  * Copyright (C) 2006-2019 Red Hat, Inc.
5  * Copyright (C) 2006 Daniel P. Berrange
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include <sys/types.h>
25 #include <sys/poll.h>
26 #include <sys/time.h>
27 #include <dirent.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <signal.h>
33 #include <sys/ioctl.h>
34 
35 #include "qemu_driver.h"
36 #include "qemu_agent.h"
37 #include "qemu_alias.h"
38 #include "qemu_block.h"
39 #include "qemu_conf.h"
40 #include "qemu_capabilities.h"
41 #include "qemu_command.h"
42 #include "qemu_cgroup.h"
43 #include "qemu_hostdev.h"
44 #include "qemu_hotplug.h"
45 #include "qemu_monitor.h"
46 #include "qemu_process.h"
47 #include "qemu_migration.h"
48 #include "qemu_migration_params.h"
49 #include "qemu_blockjob.h"
50 #include "qemu_security.h"
51 #include "qemu_checkpoint.h"
52 #include "qemu_backup.h"
53 #include "qemu_namespace.h"
54 #include "qemu_saveimage.h"
55 #include "qemu_snapshot.h"
56 #include "qemu_validate.h"
57 
58 #include "virerror.h"
59 #include "virlog.h"
60 #include "datatypes.h"
61 #include "virbuffer.h"
62 #include "virhostcpu.h"
63 #include "virhostmem.h"
64 #include "virnetdevtap.h"
65 #include "virnetdevopenvswitch.h"
66 #include "capabilities.h"
67 #include "viralloc.h"
68 #include "virarptable.h"
69 #include "viruuid.h"
70 #include "domain_conf.h"
71 #include "domain_audit.h"
72 #include "domain_cgroup.h"
73 #include "domain_driver.h"
74 #include "domain_validate.h"
75 #include "node_device_conf.h"
76 #include "virpci.h"
77 #include "virusb.h"
78 #include "virpidfile.h"
79 #include "virprocess.h"
80 #include "libvirt_internal.h"
81 #include "virxml.h"
82 #include "cpu/cpu.h"
83 #include "virsysinfo.h"
84 #include "domain_nwfilter.h"
85 #include "virhook.h"
86 #include "virstoragefile.h"
87 #include "storage_source_conf.h"
88 #include "storage_file_probe.h"
89 #include "storage_source.h"
90 #include "virfile.h"
91 #include "virfdstream.h"
92 #include "configmake.h"
93 #include "virthreadpool.h"
94 #include "locking/lock_manager.h"
95 #include "locking/domain_lock.h"
96 #include "virkeycode.h"
97 #include "virnodesuspend.h"
98 #include "virtime.h"
99 #include "virtypedparam.h"
100 #include "virbitmap.h"
101 #include "virstring.h"
102 #include "viraccessapicheck.h"
103 #include "viraccessapicheckqemu.h"
104 #include "virhostdev.h"
105 #include "domain_capabilities.h"
106 #include "vircgroup.h"
107 #include "virperf.h"
108 #include "virnuma.h"
109 #include "netdev_bandwidth_conf.h"
110 #include "virqemu.h"
111 #include "virdomainsnapshotobjlist.h"
112 #include "virenum.h"
113 #include "virdomaincheckpointobjlist.h"
114 #include "virsocket.h"
115 #include "virutil.h"
116 #include "backup_conf.h"
117 
118 #define VIR_FROM_THIS VIR_FROM_QEMU
119 
120 VIR_LOG_INIT("qemu.qemu_driver");
121 
122 #define QEMU_NB_MEM_PARAM  3
123 
124 #define QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS 6
125 #define QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS 7
126 #define QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS 6
127 #define QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS 1
128 #define QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS (QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS + \
129                                           QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS + \
130                                           QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS + \
131                                           QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS)
132 
133 #define QEMU_NB_NUMA_PARAM 2
134 
135 #define QEMU_GUEST_VCPU_MAX_ID 4096
136 
137 #define QEMU_NB_BLKIO_PARAM  6
138 
139 #define QEMU_NB_BANDWIDTH_PARAM 7
140 
141 VIR_ENUM_DECL(qemuDumpFormat);
142 VIR_ENUM_IMPL(qemuDumpFormat,
143               VIR_DOMAIN_CORE_DUMP_FORMAT_LAST,
144               "elf",
145               "kdump-zlib",
146               "kdump-lzo",
147               "kdump-snappy",
148               "win-dmp",
149 );
150 
151 
152 static void qemuProcessEventHandler(void *data, void *opaque);
153 
154 static int qemuStateCleanup(void);
155 
156 static int qemuDomainObjStart(virConnectPtr conn,
157                               virQEMUDriver *driver,
158                               virDomainObj *vm,
159                               unsigned int flags,
160                               qemuDomainAsyncJob asyncJob);
161 
162 static int qemuDomainManagedSaveLoad(virDomainObj *vm,
163                                      void *opaque);
164 
165 static virQEMUDriver *qemu_driver;
166 
167 /* Looks up the domain object from snapshot and unlocks the
168  * driver. The returned domain object is locked and ref'd and the
169  * caller must call virDomainObjEndAPI() on it. */
170 static virDomainObj *
qemuDomObjFromSnapshot(virDomainSnapshotPtr snapshot)171 qemuDomObjFromSnapshot(virDomainSnapshotPtr snapshot)
172 {
173     return qemuDomainObjFromDomain(snapshot->domain);
174 }
175 
176 
177 
178 
179 static int
qemuAutostartDomain(virDomainObj * vm,void * opaque)180 qemuAutostartDomain(virDomainObj *vm,
181                     void *opaque)
182 {
183     virQEMUDriver *driver = opaque;
184     int flags = 0;
185     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
186     int ret = -1;
187 
188     if (cfg->autoStartBypassCache)
189         flags |= VIR_DOMAIN_START_BYPASS_CACHE;
190 
191     virObjectLock(vm);
192     virObjectRef(vm);
193     virResetLastError();
194     if (vm->autostart &&
195         !virDomainObjIsActive(vm)) {
196         if (qemuProcessBeginJob(driver, vm,
197                                 VIR_DOMAIN_JOB_OPERATION_START, flags) < 0) {
198             virReportError(VIR_ERR_INTERNAL_ERROR,
199                            _("Failed to start job on VM '%s': %s"),
200                            vm->def->name, virGetLastErrorMessage());
201             goto cleanup;
202         }
203 
204         if (qemuDomainObjStart(NULL, driver, vm, flags,
205                                QEMU_ASYNC_JOB_START) < 0) {
206             virReportError(VIR_ERR_INTERNAL_ERROR,
207                            _("Failed to autostart VM '%s': %s"),
208                            vm->def->name, virGetLastErrorMessage());
209         }
210 
211         qemuProcessEndJob(driver, vm);
212     }
213 
214     ret = 0;
215  cleanup:
216     virDomainObjEndAPI(&vm);
217     return ret;
218 }
219 
220 
221 static void
qemuAutostartDomains(virQEMUDriver * driver)222 qemuAutostartDomains(virQEMUDriver *driver)
223 {
224     virDomainObjListForEach(driver->domains, false, qemuAutostartDomain, driver);
225 }
226 
227 
228 static int
qemuSecurityChownCallback(const virStorageSource * src,uid_t uid,gid_t gid)229 qemuSecurityChownCallback(const virStorageSource *src,
230                           uid_t uid,
231                           gid_t gid)
232 {
233     int save_errno = 0;
234     int ret = -1;
235     int rv;
236     g_autoptr(virStorageSource) cpy = NULL;
237 
238     if (virStorageSourceIsLocalStorage(src))
239         return -3;
240 
241     if ((rv = virStorageSourceSupportsSecurityDriver(src)) <= 0)
242         return rv;
243 
244     if (!(cpy = virStorageSourceCopy(src, false)))
245         return -1;
246 
247     /* src file init reports errors, return -2 on failure */
248     if (virStorageSourceInit(cpy) < 0)
249         return -2;
250 
251     ret = virStorageSourceChown(cpy, uid, gid);
252 
253     save_errno = errno;
254     virStorageSourceDeinit(cpy);
255     errno = save_errno;
256 
257     return ret;
258 }
259 
260 
261 static int
qemuSecurityInit(virQEMUDriver * driver)262 qemuSecurityInit(virQEMUDriver *driver)
263 {
264     char **names;
265     virSecurityManager *mgr = NULL;
266     virSecurityManager *stack = NULL;
267     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
268     unsigned int flags = 0;
269 
270     if (cfg->securityDefaultConfined)
271         flags |= VIR_SECURITY_MANAGER_DEFAULT_CONFINED;
272     if (cfg->securityRequireConfined)
273         flags |= VIR_SECURITY_MANAGER_REQUIRE_CONFINED;
274     if (driver->privileged)
275         flags |= VIR_SECURITY_MANAGER_PRIVILEGED;
276 
277     if (cfg->securityDriverNames &&
278         cfg->securityDriverNames[0]) {
279         names = cfg->securityDriverNames;
280         while (names && *names) {
281             if (!(mgr = qemuSecurityNew(*names,
282                                         QEMU_DRIVER_NAME,
283                                         flags)))
284                 goto error;
285             if (!stack) {
286                 if (!(stack = qemuSecurityNewStack(mgr)))
287                     goto error;
288             } else {
289                 if (qemuSecurityStackAddNested(stack, mgr) < 0)
290                     goto error;
291             }
292             mgr = NULL;
293             names++;
294         }
295     } else {
296         if (!(mgr = qemuSecurityNew(NULL,
297                                     QEMU_DRIVER_NAME,
298                                     flags)))
299             goto error;
300         if (!(stack = qemuSecurityNewStack(mgr)))
301             goto error;
302         mgr = NULL;
303     }
304 
305     if (driver->privileged) {
306         if (cfg->dynamicOwnership)
307             flags |= VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP;
308         if (virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT))
309             flags |= VIR_SECURITY_MANAGER_MOUNT_NAMESPACE;
310         if (!(mgr = qemuSecurityNewDAC(QEMU_DRIVER_NAME,
311                                        cfg->user,
312                                        cfg->group,
313                                        flags,
314                                        qemuSecurityChownCallback)))
315             goto error;
316         if (!stack) {
317             if (!(stack = qemuSecurityNewStack(mgr)))
318                 goto error;
319         } else {
320             if (qemuSecurityStackAddNested(stack, mgr) < 0)
321                 goto error;
322         }
323         mgr = NULL;
324     }
325 
326     driver->securityManager = stack;
327     return 0;
328 
329  error:
330     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
331                    _("Failed to initialize security drivers"));
332     virObjectUnref(stack);
333     virObjectUnref(mgr);
334     return -1;
335 }
336 
337 
338 static int
qemuDomainSnapshotLoad(virDomainObj * vm,void * data)339 qemuDomainSnapshotLoad(virDomainObj *vm,
340                        void *data)
341 {
342     char *baseDir = (char *)data;
343     g_autofree char *snapDir = NULL;
344     g_autoptr(DIR) dir = NULL;
345     struct dirent *entry;
346     virDomainSnapshotDef *def = NULL;
347     virDomainMomentObj *snap = NULL;
348     virDomainMomentObj *current = NULL;
349     bool cur;
350     unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE |
351                           VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
352                           VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL);
353     int ret = -1;
354     int direrr;
355     qemuDomainObjPrivate *priv;
356 
357     virObjectLock(vm);
358 
359     priv = vm->privateData;
360 
361     snapDir = g_strdup_printf("%s/%s", baseDir, vm->def->name);
362 
363     VIR_INFO("Scanning for snapshots for domain %s in %s", vm->def->name,
364              snapDir);
365 
366     if (virDirOpenIfExists(&dir, snapDir) <= 0)
367         goto cleanup;
368 
369     while ((direrr = virDirRead(dir, &entry, NULL)) > 0) {
370         g_autofree char *xmlStr = NULL;
371         g_autofree char *fullpath = NULL;
372 
373         /* NB: ignoring errors, so one malformed config doesn't
374            kill the whole process */
375         VIR_INFO("Loading snapshot file '%s'", entry->d_name);
376 
377         fullpath = g_strdup_printf("%s/%s", snapDir, entry->d_name);
378 
379         if (virFileReadAll(fullpath, 1024*1024*1, &xmlStr) < 0) {
380             /* Nothing we can do here, skip this one */
381             virReportSystemError(errno,
382                                  _("Failed to read snapshot file %s"),
383                                  fullpath);
384             continue;
385         }
386 
387         def = virDomainSnapshotDefParseString(xmlStr,
388                                               qemu_driver->xmlopt,
389                                               priv->qemuCaps, &cur,
390                                               flags);
391         if (def == NULL) {
392             /* Nothing we can do here, skip this one */
393             virReportError(VIR_ERR_INTERNAL_ERROR,
394                            _("Failed to parse snapshot XML from file '%s'"),
395                            fullpath);
396             continue;
397         }
398 
399         snap = virDomainSnapshotAssignDef(vm->snapshots, def);
400         if (snap == NULL) {
401             virObjectUnref(def);
402         } else if (cur) {
403             if (current)
404                 virReportError(VIR_ERR_INTERNAL_ERROR,
405                                _("Too many snapshots claiming to be current for domain %s"),
406                                vm->def->name);
407             current = snap;
408         }
409     }
410     if (direrr < 0)
411         virReportError(VIR_ERR_INTERNAL_ERROR,
412                        _("Failed to fully read directory %s"),
413                        snapDir);
414 
415     virDomainSnapshotSetCurrent(vm->snapshots, current);
416     if (virDomainSnapshotUpdateRelations(vm->snapshots) < 0)
417         virReportError(VIR_ERR_INTERNAL_ERROR,
418                        _("Snapshots have inconsistent relations for domain %s"),
419                        vm->def->name);
420 
421     /* FIXME: qemu keeps internal track of snapshots.  We can get access
422      * to this info via the "info snapshots" monitor command for running
423      * domains, or via "qemu-img snapshot -l" for shutoff domains.  It would
424      * be nice to update our internal state based on that, but there is a
425      * a problem.  qemu doesn't track all of the same metadata that we do.
426      * In particular we wouldn't be able to fill in the <parent>, which is
427      * pretty important in our metadata.
428      */
429 
430     virResetLastError();
431 
432     ret = 0;
433  cleanup:
434     virObjectUnlock(vm);
435     return ret;
436 }
437 
438 
439 static int
qemuDomainCheckpointLoad(virDomainObj * vm,void * data)440 qemuDomainCheckpointLoad(virDomainObj *vm,
441                          void *data)
442 {
443     char *baseDir = (char *)data;
444     g_autofree char *chkDir = NULL;
445     g_autoptr(DIR) dir = NULL;
446     struct dirent *entry;
447     virDomainCheckpointDef *def = NULL;
448     virDomainMomentObj *chk = NULL;
449     virDomainMomentObj *current = NULL;
450     unsigned int flags = VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE;
451     int ret = -1;
452     int direrr;
453     qemuDomainObjPrivate *priv;
454 
455     virObjectLock(vm);
456     priv = vm->privateData;
457 
458     chkDir = g_strdup_printf("%s/%s", baseDir, vm->def->name);
459 
460     VIR_INFO("Scanning for checkpoints for domain %s in %s", vm->def->name,
461              chkDir);
462 
463     if (virDirOpenIfExists(&dir, chkDir) <= 0)
464         goto cleanup;
465 
466     while ((direrr = virDirRead(dir, &entry, NULL)) > 0) {
467         g_autofree char *xmlStr = NULL;
468         g_autofree char *fullpath = NULL;
469 
470         /* NB: ignoring errors, so one malformed config doesn't
471            kill the whole process */
472         VIR_INFO("Loading checkpoint file '%s'", entry->d_name);
473 
474         fullpath = g_strdup_printf("%s/%s", chkDir, entry->d_name);
475 
476         if (virFileReadAll(fullpath, 1024*1024*1, &xmlStr) < 0) {
477             /* Nothing we can do here, skip this one */
478             virReportSystemError(errno,
479                                  _("Failed to read checkpoint file %s"),
480                                  fullpath);
481             continue;
482         }
483 
484         if (!(def = virDomainCheckpointDefParseString(xmlStr,
485                                                       qemu_driver->xmlopt,
486                                                       priv->qemuCaps,
487                                                       flags)))
488             continue;
489 
490         chk = virDomainCheckpointAssignDef(vm->checkpoints, def);
491         if (chk == NULL)
492             virObjectUnref(def);
493     }
494     if (direrr < 0)
495         virReportError(VIR_ERR_INTERNAL_ERROR,
496                        _("Failed to fully read directory %s"),
497                        chkDir);
498 
499     if (virDomainCheckpointUpdateRelations(vm->checkpoints, &current) < 0)
500         virReportError(VIR_ERR_INTERNAL_ERROR,
501                        _("Checkpoints have inconsistent relations for domain %s"),
502                        vm->def->name);
503     virDomainCheckpointSetCurrent(vm->checkpoints, current);
504 
505     virResetLastError();
506 
507     ret = 0;
508  cleanup:
509     virObjectUnlock(vm);
510     return ret;
511 }
512 
513 
514 static int
qemuDomainNetsRestart(virDomainObj * vm,void * data G_GNUC_UNUSED)515 qemuDomainNetsRestart(virDomainObj *vm,
516                       void *data G_GNUC_UNUSED)
517 {
518     size_t i;
519     virDomainDef *def = vm->def;
520 
521     virObjectLock(vm);
522 
523     for (i = 0; i < def->nnets; i++) {
524         virDomainNetDef *net = def->nets[i];
525         if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT &&
526             virDomainNetGetActualDirectMode(net) == VIR_NETDEV_MACVLAN_MODE_VEPA) {
527             VIR_DEBUG("VEPA mode device %s active in domain %s. Reassociating.",
528                       net->ifname, def->name);
529             ignore_value(virNetDevMacVLanRestartWithVPortProfile(net->ifname,
530                                                                  &net->mac,
531                                                                  virDomainNetGetActualDirectDev(net),
532                                                                  def->uuid,
533                                                                  virDomainNetGetActualVirtPortProfile(net),
534                                                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE));
535         }
536     }
537 
538     virObjectUnlock(vm);
539     return 0;
540 }
541 
542 
543 static int
qemuDomainFindMaxID(virDomainObj * vm,void * data)544 qemuDomainFindMaxID(virDomainObj *vm,
545                     void *data)
546 {
547     int *driver_maxid = data;
548 
549     if (vm->def->id > *driver_maxid)
550         *driver_maxid = vm->def->id;
551 
552     return 0;
553 }
554 
555 
556 /**
557  * qemuStateInitialize:
558  *
559  * Initialization function for the QEMU daemon
560  */
561 static int
qemuStateInitialize(bool privileged,const char * root,virStateInhibitCallback callback,void * opaque)562 qemuStateInitialize(bool privileged,
563                     const char *root,
564                     virStateInhibitCallback callback,
565                     void *opaque)
566 {
567     g_autofree char *driverConf = NULL;
568     virQEMUDriverConfig *cfg;
569     uid_t run_uid = -1;
570     gid_t run_gid = -1;
571     bool autostart = true;
572     size_t i;
573     const char *defsecmodel = NULL;
574     g_autofree virSecurityManager **sec_managers = NULL;
575     g_autoptr(virIdentity) identity = virIdentityGetCurrent();
576 
577     qemu_driver = g_new0(virQEMUDriver, 1);
578 
579     qemu_driver->lockFD = -1;
580 
581     if (virMutexInit(&qemu_driver->lock) < 0) {
582         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
583                        _("cannot initialize mutex"));
584         VIR_FREE(qemu_driver);
585         return VIR_DRV_STATE_INIT_ERROR;
586     }
587 
588     qemu_driver->inhibitCallback = callback;
589     qemu_driver->inhibitOpaque = opaque;
590 
591     qemu_driver->privileged = privileged;
592     qemu_driver->hostarch = virArchFromHost();
593     if (root != NULL)
594         qemu_driver->embeddedRoot = g_strdup(root);
595 
596     if (!(qemu_driver->domains = virDomainObjListNew()))
597         goto error;
598 
599     /* Init domain events */
600     qemu_driver->domainEventState = virObjectEventStateNew();
601     if (!qemu_driver->domainEventState)
602         goto error;
603 
604     /* read the host sysinfo */
605     if (privileged)
606         qemu_driver->hostsysinfo = virSysinfoRead();
607 
608     if (!(qemu_driver->config = cfg = virQEMUDriverConfigNew(privileged, root)))
609         goto error;
610 
611     driverConf = g_strdup_printf("%s/qemu.conf", cfg->configBaseDir);
612 
613     if (virQEMUDriverConfigLoadFile(cfg, driverConf, privileged) < 0)
614         goto error;
615 
616     if (virQEMUDriverConfigValidate(cfg) < 0)
617         goto error;
618 
619     if (virQEMUDriverConfigSetDefaults(cfg) < 0)
620         goto error;
621 
622     if (g_mkdir_with_parents(cfg->stateDir, 0777) < 0) {
623         virReportSystemError(errno, _("Failed to create state dir %s"),
624                              cfg->stateDir);
625         goto error;
626     }
627     if (g_mkdir_with_parents(cfg->libDir, 0777) < 0) {
628         virReportSystemError(errno, _("Failed to create lib dir %s"),
629                              cfg->libDir);
630         goto error;
631     }
632     if (g_mkdir_with_parents(cfg->cacheDir, 0777) < 0) {
633         virReportSystemError(errno, _("Failed to create cache dir %s"),
634                              cfg->cacheDir);
635         goto error;
636     }
637     if (g_mkdir_with_parents(cfg->saveDir, 0777) < 0) {
638         virReportSystemError(errno, _("Failed to create save dir %s"),
639                              cfg->saveDir);
640         goto error;
641     }
642     if (g_mkdir_with_parents(cfg->snapshotDir, 0777) < 0) {
643         virReportSystemError(errno, _("Failed to create snapshot dir %s"),
644                              cfg->snapshotDir);
645         goto error;
646     }
647     if (g_mkdir_with_parents(cfg->checkpointDir, 0777) < 0) {
648         virReportSystemError(errno, _("Failed to create checkpoint dir %s"),
649                              cfg->checkpointDir);
650         goto error;
651     }
652     if (g_mkdir_with_parents(cfg->autoDumpPath, 0777) < 0) {
653         virReportSystemError(errno, _("Failed to create dump dir %s"),
654                              cfg->autoDumpPath);
655         goto error;
656     }
657     if (g_mkdir_with_parents(cfg->channelTargetDir, 0777) < 0) {
658         virReportSystemError(errno, _("Failed to create channel target dir %s"),
659                              cfg->channelTargetDir);
660         goto error;
661     }
662     if (g_mkdir_with_parents(cfg->nvramDir, 0777) < 0) {
663         virReportSystemError(errno, _("Failed to create nvram dir %s"),
664                              cfg->nvramDir);
665         goto error;
666     }
667     if (g_mkdir_with_parents(cfg->memoryBackingDir, 0777) < 0) {
668         virReportSystemError(errno, _("Failed to create memory backing dir %s"),
669                              cfg->memoryBackingDir);
670         goto error;
671     }
672     if (g_mkdir_with_parents(cfg->slirpStateDir, 0777) < 0) {
673         virReportSystemError(errno, _("Failed to create slirp state dir %s"),
674                              cfg->slirpStateDir);
675         goto error;
676     }
677 
678     if (virDirCreate(cfg->dbusStateDir, 0770, cfg->user, cfg->group,
679                      VIR_DIR_CREATE_ALLOW_EXIST) < 0) {
680         virReportSystemError(errno, _("Failed to create dbus state dir %s"),
681                              cfg->dbusStateDir);
682         goto error;
683     }
684 
685     if ((qemu_driver->lockFD =
686          virPidFileAcquire(cfg->stateDir, "driver", false, getpid())) < 0)
687         goto error;
688 
689     qemu_driver->qemuImgBinary = virFindFileInPath("qemu-img");
690 
691     if (!(qemu_driver->lockManager =
692           virLockManagerPluginNew(cfg->lockManagerName ?
693                                   cfg->lockManagerName : "nop",
694                                   "qemu",
695                                   cfg->configBaseDir,
696                                   0)))
697         goto error;
698 
699    if (cfg->macFilter) {
700         if (!(qemu_driver->ebtables = ebtablesContextNew("qemu"))) {
701             virReportSystemError(errno,
702                                  _("failed to enable mac filter in '%s'"),
703                                  __FILE__);
704             goto error;
705         }
706 
707         if (ebtablesAddForwardPolicyReject(qemu_driver->ebtables) < 0)
708             goto error;
709    }
710 
711     /* Allocate bitmap for remote display port reservations. We cannot
712      * do this before the config is loaded properly, since the port
713      * numbers are configurable now */
714     if ((qemu_driver->remotePorts =
715          virPortAllocatorRangeNew(_("display"),
716                                   cfg->remotePortMin,
717                                   cfg->remotePortMax)) == NULL)
718         goto error;
719 
720     if ((qemu_driver->webSocketPorts =
721          virPortAllocatorRangeNew(_("webSocket"),
722                                   cfg->webSocketPortMin,
723                                   cfg->webSocketPortMax)) == NULL)
724         goto error;
725 
726     if ((qemu_driver->migrationPorts =
727          virPortAllocatorRangeNew(_("migration"),
728                                   cfg->migrationPortMin,
729                                   cfg->migrationPortMax)) == NULL)
730         goto error;
731 
732     if (qemuSecurityInit(qemu_driver) < 0)
733         goto error;
734 
735     if (!(qemu_driver->hostdevMgr = virHostdevManagerGetDefault()))
736         goto error;
737 
738     qemu_driver->sharedDevices = virHashNew(qemuSharedDeviceEntryFree);
739 
740     if (qemuMigrationDstErrorInit(qemu_driver) < 0)
741         goto error;
742 
743     if (privileged) {
744         g_autofree char *channeldir = NULL;
745 
746         if (chown(cfg->libDir, cfg->user, cfg->group) < 0) {
747             virReportSystemError(errno,
748                                  _("unable to set ownership of '%s' to user %d:%d"),
749                                  cfg->libDir, (int)cfg->user,
750                                  (int)cfg->group);
751             goto error;
752         }
753         if (chown(cfg->saveDir, cfg->user, cfg->group) < 0) {
754             virReportSystemError(errno,
755                                  _("unable to set ownership of '%s' to %d:%d"),
756                                  cfg->saveDir, (int)cfg->user,
757                                  (int)cfg->group);
758             goto error;
759         }
760         if (chown(cfg->snapshotDir, cfg->user, cfg->group) < 0) {
761             virReportSystemError(errno,
762                                  _("unable to set ownership of '%s' to %d:%d"),
763                                  cfg->snapshotDir, (int)cfg->user,
764                                  (int)cfg->group);
765             goto error;
766         }
767         if (chown(cfg->checkpointDir, cfg->user, cfg->group) < 0) {
768             virReportSystemError(errno,
769                                  _("unable to set ownership of '%s' to %d:%d"),
770                                  cfg->checkpointDir, (int)cfg->user,
771                                  (int)cfg->group);
772             goto error;
773         }
774         if (chown(cfg->autoDumpPath, cfg->user, cfg->group) < 0) {
775             virReportSystemError(errno,
776                                  _("unable to set ownership of '%s' to %d:%d"),
777                                  cfg->autoDumpPath, (int)cfg->user,
778                                  (int)cfg->group);
779             goto error;
780         }
781         channeldir = g_path_get_dirname(cfg->channelTargetDir);
782 
783         if (chown(channeldir, cfg->user, cfg->group) < 0) {
784             virReportSystemError(errno,
785                                  _("unable to set ownership of '%s' to %d:%d"),
786                                  channeldir, (int)cfg->user,
787                                  (int)cfg->group);
788             goto error;
789         }
790         if (chown(cfg->channelTargetDir, cfg->user, cfg->group) < 0) {
791             virReportSystemError(errno,
792                                  _("unable to set ownership of '%s' to %d:%d"),
793                                  cfg->channelTargetDir, (int)cfg->user,
794                                  (int)cfg->group);
795             goto error;
796         }
797         if (chown(cfg->nvramDir, cfg->user, cfg->group) < 0) {
798             virReportSystemError(errno,
799                                  _("unable to set ownership of '%s' to %d:%d"),
800                                  cfg->nvramDir, (int)cfg->user,
801                                  (int)cfg->group);
802             goto error;
803         }
804         if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) {
805             virReportSystemError(errno,
806                                  _("unable to set ownership of '%s' to %d:%d"),
807                                  cfg->memoryBackingDir, (int)cfg->user,
808                                  (int)cfg->group);
809             goto error;
810         }
811         if (chown(cfg->slirpStateDir, cfg->user, cfg->group) < 0) {
812             virReportSystemError(errno,
813                                  _("unable to set ownership of '%s' to %d:%d"),
814                                  cfg->slirpStateDir, (int)cfg->user,
815                                  (int)cfg->group);
816             goto error;
817         }
818 
819         run_uid = cfg->user;
820         run_gid = cfg->group;
821     }
822 
823     qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
824                                                      cfg->cacheDir,
825                                                      run_uid,
826                                                      run_gid);
827     if (!qemu_driver->qemuCapsCache)
828         goto error;
829 
830     if (!(sec_managers = qemuSecurityGetNested(qemu_driver->securityManager)))
831         goto error;
832 
833     if (sec_managers[0] != NULL)
834         defsecmodel = qemuSecurityGetModel(sec_managers[0]);
835 
836     if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver,
837                                                            defsecmodel)))
838         goto error;
839 
840     /* If hugetlbfs is present, then we need to create a sub-directory within
841      * it, since we can't assume the root mount point has permissions that
842      * will let our spawned QEMU instances use it. */
843     for (i = 0; i < cfg->nhugetlbfs; i++) {
844         g_autofree char *hugepagePath = NULL;
845 
846         hugepagePath = qemuGetBaseHugepagePath(qemu_driver, &cfg->hugetlbfs[i]);
847 
848         if (!hugepagePath)
849             goto error;
850 
851         if (g_mkdir_with_parents(hugepagePath, 0777) < 0) {
852             virReportSystemError(errno,
853                                  _("unable to create hugepage path %s"),
854                                  hugepagePath);
855             goto error;
856         }
857         if (privileged &&
858             virFileUpdatePerm(cfg->hugetlbfs[i].mnt_dir,
859                               0, S_IXGRP | S_IXOTH) < 0)
860             goto error;
861     }
862 
863     if (privileged &&
864         virFileUpdatePerm(cfg->memoryBackingDir,
865                           0, S_IXGRP | S_IXOTH) < 0)
866         goto error;
867 
868     if (!(qemu_driver->closeCallbacks = virCloseCallbacksNew()))
869         goto error;
870 
871     /* Get all the running persistent or transient configs first */
872     if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
873                                        cfg->stateDir,
874                                        NULL, true,
875                                        qemu_driver->xmlopt,
876                                        NULL, NULL) < 0)
877         goto error;
878 
879     /* find the maximum ID from active and transient configs to initialize
880      * the driver with. This is to avoid race between autostart and reconnect
881      * threads */
882     virDomainObjListForEach(qemu_driver->domains,
883                             false,
884                             qemuDomainFindMaxID,
885                             &qemu_driver->lastvmid);
886 
887     virDomainObjListForEach(qemu_driver->domains,
888                             false,
889                             qemuDomainNetsRestart,
890                             NULL);
891 
892     /* Then inactive persistent configs */
893     if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
894                                        cfg->configDir,
895                                        cfg->autostartDir, false,
896                                        qemu_driver->xmlopt,
897                                        NULL, NULL) < 0)
898         goto error;
899 
900     virDomainObjListForEach(qemu_driver->domains,
901                             false,
902                             qemuDomainSnapshotLoad,
903                             cfg->snapshotDir);
904 
905     virDomainObjListForEach(qemu_driver->domains,
906                             false,
907                             qemuDomainCheckpointLoad,
908                             cfg->checkpointDir);
909 
910     virDomainObjListForEach(qemu_driver->domains,
911                             false,
912                             qemuDomainManagedSaveLoad,
913                             qemu_driver);
914 
915     /* must be initialized before trying to reconnect to all the
916      * running domains since there might occur some QEMU monitor
917      * events that will be dispatched to the worker pool */
918     qemu_driver->workerPool = virThreadPoolNewFull(0, 1, 0, qemuProcessEventHandler,
919                                                    "qemu-event",
920                                                    identity,
921                                                    qemu_driver);
922     if (!qemu_driver->workerPool)
923         goto error;
924 
925     qemuProcessReconnectAll(qemu_driver);
926 
927     if (virDriverShouldAutostart(cfg->stateDir, &autostart) < 0)
928         goto error;
929 
930     if (autostart)
931         qemuAutostartDomains(qemu_driver);
932 
933     return VIR_DRV_STATE_INIT_COMPLETE;
934 
935  error:
936     qemuStateCleanup();
937     return VIR_DRV_STATE_INIT_ERROR;
938 }
939 
qemuNotifyLoadDomain(virDomainObj * vm,int newVM,void * opaque)940 static void qemuNotifyLoadDomain(virDomainObj *vm, int newVM, void *opaque)
941 {
942     virQEMUDriver *driver = opaque;
943 
944     if (newVM) {
945         virObjectEvent *event =
946             virDomainEventLifecycleNewFromObj(vm,
947                                      VIR_DOMAIN_EVENT_DEFINED,
948                                      VIR_DOMAIN_EVENT_DEFINED_ADDED);
949         virObjectEventStateQueue(driver->domainEventState, event);
950     }
951 }
952 
953 /**
954  * qemuStateReload:
955  *
956  * Function to restart the QEMU daemon, it will recheck the configuration
957  * files and update its state and the networking
958  */
959 static int
qemuStateReload(void)960 qemuStateReload(void)
961 {
962     g_autoptr(virQEMUDriverConfig) cfg = NULL;
963 
964     if (!qemu_driver)
965         return 0;
966 
967     cfg = virQEMUDriverGetConfig(qemu_driver);
968     virDomainObjListLoadAllConfigs(qemu_driver->domains,
969                                    cfg->configDir,
970                                    cfg->autostartDir, false,
971                                    qemu_driver->xmlopt,
972                                    qemuNotifyLoadDomain, qemu_driver);
973     return 0;
974 }
975 
976 
977 /*
978  * qemuStateStop:
979  *
980  * Save any VMs in preparation for shutdown
981  *
982  */
983 static int
qemuStateStop(void)984 qemuStateStop(void)
985 {
986     int ret = -1;
987     g_autoptr(virConnect) conn = NULL;
988     int numDomains = 0;
989     size_t i;
990     int state;
991     virDomainPtr *domains = NULL;
992     g_autofree unsigned int *flags = NULL;
993     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(qemu_driver);
994 
995     if (!(conn = virConnectOpen(cfg->uri)))
996         goto cleanup;
997 
998     if ((numDomains = virConnectListAllDomains(conn,
999                                                &domains,
1000                                                VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
1001         goto cleanup;
1002 
1003     flags = g_new0(unsigned int, numDomains);
1004 
1005     /* First we pause all VMs to make them stop dirtying
1006        pages, etc. We remember if any VMs were paused so
1007        we can restore that on resume. */
1008     for (i = 0; i < numDomains; i++) {
1009         flags[i] = VIR_DOMAIN_SAVE_RUNNING;
1010         if (virDomainGetState(domains[i], &state, NULL, 0) == 0) {
1011             if (state == VIR_DOMAIN_PAUSED)
1012                 flags[i] = VIR_DOMAIN_SAVE_PAUSED;
1013         }
1014         virDomainSuspend(domains[i]);
1015     }
1016 
1017     ret = 0;
1018     /* Then we save the VMs to disk */
1019     for (i = 0; i < numDomains; i++)
1020         if (virDomainManagedSave(domains[i], flags[i]) < 0)
1021             ret = -1;
1022 
1023  cleanup:
1024     if (domains) {
1025         for (i = 0; i < numDomains; i++)
1026             virObjectUnref(domains[i]);
1027         VIR_FREE(domains);
1028     }
1029 
1030     return ret;
1031 }
1032 
1033 
1034 static int
qemuStateShutdownPrepare(void)1035 qemuStateShutdownPrepare(void)
1036 {
1037     if (!qemu_driver)
1038         return 0;
1039 
1040     virThreadPoolStop(qemu_driver->workerPool);
1041     return 0;
1042 }
1043 
1044 
1045 static int
qemuDomainObjStopWorkerIter(virDomainObj * vm,void * opaque G_GNUC_UNUSED)1046 qemuDomainObjStopWorkerIter(virDomainObj *vm,
1047                             void *opaque G_GNUC_UNUSED)
1048 {
1049     virObjectLock(vm);
1050     qemuDomainObjStopWorker(vm);
1051     virObjectUnlock(vm);
1052     return 0;
1053 }
1054 
1055 
1056 static int
qemuStateShutdownWait(void)1057 qemuStateShutdownWait(void)
1058 {
1059     if (!qemu_driver)
1060         return 0;
1061 
1062     virDomainObjListForEach(qemu_driver->domains, false,
1063                             qemuDomainObjStopWorkerIter, NULL);
1064     virThreadPoolDrain(qemu_driver->workerPool);
1065     return 0;
1066 }
1067 
1068 
1069 /**
1070  * qemuStateCleanup:
1071  *
1072  * Release resources allocated by QEMU driver (no domain is shut off though)
1073  */
1074 static int
qemuStateCleanup(void)1075 qemuStateCleanup(void)
1076 {
1077     if (!qemu_driver)
1078         return -1;
1079 
1080     virObjectUnref(qemu_driver->migrationErrors);
1081     virObjectUnref(qemu_driver->closeCallbacks);
1082     virLockManagerPluginUnref(qemu_driver->lockManager);
1083     virSysinfoDefFree(qemu_driver->hostsysinfo);
1084     virPortAllocatorRangeFree(qemu_driver->migrationPorts);
1085     virPortAllocatorRangeFree(qemu_driver->webSocketPorts);
1086     virPortAllocatorRangeFree(qemu_driver->remotePorts);
1087     virHashFree(qemu_driver->sharedDevices);
1088     virObjectUnref(qemu_driver->hostdevMgr);
1089     virObjectUnref(qemu_driver->securityManager);
1090     virObjectUnref(qemu_driver->domainEventState);
1091     virObjectUnref(qemu_driver->qemuCapsCache);
1092     virObjectUnref(qemu_driver->xmlopt);
1093     virCPUDefFree(qemu_driver->hostcpu);
1094     virObjectUnref(qemu_driver->caps);
1095     ebtablesContextFree(qemu_driver->ebtables);
1096     VIR_FREE(qemu_driver->qemuImgBinary);
1097     virObjectUnref(qemu_driver->domains);
1098     virThreadPoolFree(qemu_driver->workerPool);
1099 
1100     if (qemu_driver->lockFD != -1)
1101         virPidFileRelease(qemu_driver->config->stateDir, "driver", qemu_driver->lockFD);
1102 
1103     virObjectUnref(qemu_driver->config);
1104     virMutexDestroy(&qemu_driver->lock);
1105     VIR_FREE(qemu_driver);
1106 
1107     return 0;
1108 }
1109 
1110 
1111 static int
qemuConnectURIProbe(char ** uri)1112 qemuConnectURIProbe(char **uri)
1113 {
1114     g_autoptr(virQEMUDriverConfig) cfg = NULL;
1115 
1116     if (qemu_driver == NULL)
1117         return 0;
1118 
1119     cfg = virQEMUDriverGetConfig(qemu_driver);
1120     *uri = g_strdup(cfg->uri);
1121 
1122     return 0;
1123 }
1124 
qemuConnectOpen(virConnectPtr conn,virConnectAuthPtr auth G_GNUC_UNUSED,virConf * conf G_GNUC_UNUSED,unsigned int flags)1125 static virDrvOpenStatus qemuConnectOpen(virConnectPtr conn,
1126                                         virConnectAuthPtr auth G_GNUC_UNUSED,
1127                                         virConf *conf G_GNUC_UNUSED,
1128                                         unsigned int flags)
1129 {
1130     virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
1131 
1132     if (qemu_driver == NULL) {
1133         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1134                        _("qemu state driver is not active"));
1135         return VIR_DRV_OPEN_ERROR;
1136     }
1137 
1138     if (qemu_driver->embeddedRoot) {
1139         const char *root = virURIGetParam(conn->uri, "root");
1140         if (!root)
1141             return VIR_DRV_OPEN_ERROR;
1142 
1143         if (STRNEQ(conn->uri->path, "/embed")) {
1144             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1145                            _("URI must be qemu:///embed"));
1146             return VIR_DRV_OPEN_ERROR;
1147         }
1148 
1149         if (STRNEQ(root, qemu_driver->embeddedRoot)) {
1150             virReportError(VIR_ERR_INTERNAL_ERROR,
1151                            _("Cannot open embedded driver at path '%s', "
1152                              "already open with path '%s'"),
1153                            root, qemu_driver->embeddedRoot);
1154             return VIR_DRV_OPEN_ERROR;
1155         }
1156     } else {
1157         if (!virConnectValidateURIPath(conn->uri->path,
1158                                        "qemu",
1159                                        qemu_driver->privileged))
1160             return VIR_DRV_OPEN_ERROR;
1161     }
1162 
1163     if (virConnectOpenEnsureACL(conn) < 0)
1164         return VIR_DRV_OPEN_ERROR;
1165 
1166     conn->privateData = qemu_driver;
1167 
1168     return VIR_DRV_OPEN_SUCCESS;
1169 }
1170 
qemuConnectClose(virConnectPtr conn)1171 static int qemuConnectClose(virConnectPtr conn)
1172 {
1173     virQEMUDriver *driver = conn->privateData;
1174 
1175     /* Get rid of callbacks registered for this conn */
1176     virCloseCallbacksRun(driver->closeCallbacks, conn, driver->domains, driver);
1177 
1178     conn->privateData = NULL;
1179 
1180     return 0;
1181 }
1182 
1183 /* Which features are supported by this driver? */
1184 static int
qemuConnectSupportsFeature(virConnectPtr conn,int feature)1185 qemuConnectSupportsFeature(virConnectPtr conn, int feature)
1186 {
1187     if (virConnectSupportsFeatureEnsureACL(conn) < 0)
1188         return -1;
1189 
1190     switch ((virDrvFeature) feature) {
1191     case VIR_DRV_FEATURE_MIGRATION_V2:
1192     case VIR_DRV_FEATURE_MIGRATION_V3:
1193     case VIR_DRV_FEATURE_MIGRATION_P2P:
1194     case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
1195     case VIR_DRV_FEATURE_FD_PASSING:
1196     case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
1197     case VIR_DRV_FEATURE_XML_MIGRATABLE:
1198     case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
1199     case VIR_DRV_FEATURE_MIGRATION_PARAMS:
1200     case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
1201         return 1;
1202     case VIR_DRV_FEATURE_MIGRATION_DIRECT:
1203     case VIR_DRV_FEATURE_MIGRATION_V1:
1204     case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
1205     case VIR_DRV_FEATURE_REMOTE:
1206     case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
1207     case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
1208     default:
1209         return 0;
1210     }
1211 }
1212 
qemuConnectGetType(virConnectPtr conn)1213 static const char *qemuConnectGetType(virConnectPtr conn) {
1214     if (virConnectGetTypeEnsureACL(conn) < 0)
1215         return NULL;
1216 
1217     return "QEMU";
1218 }
1219 
1220 
qemuConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)1221 static int qemuConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)
1222 {
1223     /* Trivially secure, since always inside the daemon */
1224     return 1;
1225 }
1226 
qemuConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)1227 static int qemuConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)
1228 {
1229     /* Not encrypted, but remote driver takes care of that */
1230     return 0;
1231 }
1232 
qemuConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)1233 static int qemuConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
1234 {
1235     return 1;
1236 }
1237 
1238 
1239 static char *
qemuConnectGetSysinfo(virConnectPtr conn,unsigned int flags)1240 qemuConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
1241 {
1242     virQEMUDriver *driver = conn->privateData;
1243     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1244 
1245     virCheckFlags(0, NULL);
1246 
1247     if (virConnectGetSysinfoEnsureACL(conn) < 0)
1248         return NULL;
1249 
1250     if (!driver->hostsysinfo) {
1251         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1252                        _("Host SMBIOS information is not available"));
1253         return NULL;
1254     }
1255 
1256     if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
1257         return NULL;
1258     return virBufferContentAndReset(&buf);
1259 }
1260 
1261 static int
qemuConnectGetMaxVcpus(virConnectPtr conn G_GNUC_UNUSED,const char * type)1262 qemuConnectGetMaxVcpus(virConnectPtr conn G_GNUC_UNUSED, const char *type)
1263 {
1264     if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
1265         return -1;
1266 
1267     if (!type)
1268         return 16;
1269 
1270     if (STRCASEEQ(type, "qemu"))
1271         return 16;
1272 
1273     if (STRCASEEQ(type, "kvm"))
1274         return virHostCPUGetKVMMaxVCPUs();
1275 
1276     virReportError(VIR_ERR_INVALID_ARG,
1277                    _("unknown type '%s'"), type);
1278     return -1;
1279 }
1280 
1281 
qemuConnectGetCapabilities(virConnectPtr conn)1282 static char *qemuConnectGetCapabilities(virConnectPtr conn) {
1283     virQEMUDriver *driver = conn->privateData;
1284     g_autoptr(virCaps) caps = NULL;
1285 
1286     if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
1287         return NULL;
1288 
1289     if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
1290         return NULL;
1291 
1292     return virCapabilitiesFormatXML(caps);
1293 }
1294 
1295 
1296 static int
qemuGetSchedstatDelay(unsigned long long * cpudelay,pid_t pid,pid_t tid)1297 qemuGetSchedstatDelay(unsigned long long *cpudelay,
1298                       pid_t pid,
1299                       pid_t tid)
1300 {
1301     g_autofree char *path = NULL;
1302     g_autofree char *buf = NULL;
1303 
1304     if (tid)
1305         path = g_strdup_printf("/proc/%d/task/%d/schedstat", (int)pid, (int)tid);
1306     else
1307         path = g_strdup_printf("/proc/%d/schedstat", (int)pid);
1308 
1309     /* This file might not exist (needs CONFIG_SCHED_INFO) */
1310     if (!virFileExists(path))
1311         return 0;
1312 
1313     if (virFileReadAll(path, 1024, &buf) < 0)
1314         return -1;
1315 
1316     if (sscanf(buf, "%*u %llu", cpudelay) != 1) {
1317         virReportError(VIR_ERR_INTERNAL_ERROR,
1318                        _("Unable to parse schedstat info at '%s'"),
1319                        path);
1320         return -1;
1321     }
1322 
1323     return 0;
1324 }
1325 
1326 
1327 static int
qemuGetSchedInfo(unsigned long long * cpuWait,pid_t pid,pid_t tid)1328 qemuGetSchedInfo(unsigned long long *cpuWait,
1329                  pid_t pid, pid_t tid)
1330 {
1331     g_autofree char *proc = NULL;
1332     g_autofree char *data = NULL;
1333     g_auto(GStrv) lines = NULL;
1334     size_t i;
1335     double val;
1336 
1337     *cpuWait = 0;
1338 
1339     /* In general, we cannot assume pid_t fits in int; but /proc parsing
1340      * is specific to Linux where int works fine.  */
1341     if (tid)
1342         proc = g_strdup_printf("/proc/%d/task/%d/sched", (int)pid, (int)tid);
1343     else
1344         proc = g_strdup_printf("/proc/%d/sched", (int)pid);
1345     if (!proc)
1346         return -1;
1347 
1348     /* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */
1349     if (access(proc, R_OK) < 0) {
1350         return 0;
1351     }
1352 
1353     if (virFileReadAll(proc, (1<<16), &data) < 0)
1354         return -1;
1355 
1356     lines = g_strsplit(data, "\n", 0);
1357     if (!lines)
1358         return -1;
1359 
1360     for (i = 0; lines[i] != NULL; i++) {
1361         const char *line = lines[i];
1362 
1363         /* Needs CONFIG_SCHEDSTATS. The second check
1364          * is the old name the kernel used in past */
1365         if (STRPREFIX(line, "se.statistics.wait_sum") ||
1366             STRPREFIX(line, "se.wait_sum")) {
1367             line = strchr(line, ':');
1368             if (!line) {
1369                 virReportError(VIR_ERR_INTERNAL_ERROR,
1370                                _("Missing separator in sched info '%s'"),
1371                                lines[i]);
1372                 return -1;
1373             }
1374             line++;
1375             while (*line == ' ')
1376                 line++;
1377 
1378             if (virStrToDouble(line, NULL, &val) < 0) {
1379                 virReportError(VIR_ERR_INTERNAL_ERROR,
1380                                _("Unable to parse sched info value '%s'"),
1381                                line);
1382                 return -1;
1383             }
1384 
1385             *cpuWait = (unsigned long long)(val * 1000000);
1386             break;
1387         }
1388     }
1389 
1390     return 0;
1391 }
1392 
1393 
1394 static int
qemuGetProcessInfo(unsigned long long * cpuTime,int * lastCpu,long * vm_rss,pid_t pid,pid_t tid)1395 qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
1396                    pid_t pid, pid_t tid)
1397 {
1398     g_auto(GStrv) proc_stat = virProcessGetStat(pid, tid);
1399     unsigned long long usertime = 0, systime = 0;
1400     long rss = 0;
1401     int cpu = 0;
1402 
1403     if (!proc_stat ||
1404         virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_UTIME], NULL, 10, &usertime) < 0 ||
1405         virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_STIME], NULL, 10, &systime) < 0 ||
1406         virStrToLong_l(proc_stat[VIR_PROCESS_STAT_RSS], NULL, 10, &rss) < 0 ||
1407         virStrToLong_i(proc_stat[VIR_PROCESS_STAT_PROCESSOR], NULL, 10, &cpu) < 0) {
1408         VIR_WARN("cannot parse process status data");
1409     }
1410 
1411     /* We got jiffies
1412      * We want nanoseconds
1413      * _SC_CLK_TCK is jiffies per second
1414      * So calculate thus....
1415      */
1416     if (cpuTime)
1417         *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime)
1418             / (unsigned long long)sysconf(_SC_CLK_TCK);
1419     if (lastCpu)
1420         *lastCpu = cpu;
1421 
1422     if (vm_rss)
1423         *vm_rss = rss * virGetSystemPageSizeKB();
1424 
1425 
1426     VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
1427               (int)pid, tid, usertime, systime, cpu, rss);
1428 
1429     return 0;
1430 }
1431 
1432 
1433 static int
qemuDomainHelperGetVcpus(virDomainObj * vm,virVcpuInfoPtr info,unsigned long long * cpuwait,unsigned long long * cpudelay,int maxinfo,unsigned char * cpumaps,int maplen)1434 qemuDomainHelperGetVcpus(virDomainObj *vm,
1435                          virVcpuInfoPtr info,
1436                          unsigned long long *cpuwait,
1437                          unsigned long long *cpudelay,
1438                          int maxinfo,
1439                          unsigned char *cpumaps,
1440                          int maplen)
1441 {
1442     size_t ncpuinfo = 0;
1443     size_t i;
1444 
1445     if (maxinfo == 0)
1446         return 0;
1447 
1448     if (!qemuDomainHasVcpuPids(vm)) {
1449         virReportError(VIR_ERR_OPERATION_INVALID,
1450                        "%s", _("cpu affinity is not supported"));
1451         return -1;
1452     }
1453 
1454     if (info)
1455         memset(info, 0, sizeof(*info) * maxinfo);
1456 
1457     if (cpumaps)
1458         memset(cpumaps, 0, sizeof(*cpumaps) * maxinfo);
1459 
1460     for (i = 0; i < virDomainDefGetVcpusMax(vm->def) && ncpuinfo < maxinfo; i++) {
1461         virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
1462         pid_t vcpupid = qemuDomainGetVcpuPid(vm, i);
1463         virVcpuInfoPtr vcpuinfo = info + ncpuinfo;
1464 
1465         if (!vcpu->online)
1466             continue;
1467 
1468         if (info) {
1469             vcpuinfo->number = i;
1470             vcpuinfo->state = VIR_VCPU_RUNNING;
1471 
1472             if (qemuGetProcessInfo(&vcpuinfo->cpuTime,
1473                                    &vcpuinfo->cpu, NULL,
1474                                    vm->pid, vcpupid) < 0) {
1475                 virReportSystemError(errno, "%s",
1476                                      _("cannot get vCPU placement & pCPU time"));
1477                 return -1;
1478             }
1479         }
1480 
1481         if (cpumaps) {
1482             unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
1483             virBitmap *map = NULL;
1484 
1485             if (!(map = virProcessGetAffinity(vcpupid)))
1486                 return -1;
1487 
1488             virBitmapToDataBuf(map, cpumap, maplen);
1489             virBitmapFree(map);
1490         }
1491 
1492         if (cpuwait) {
1493             if (qemuGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) < 0)
1494                 return -1;
1495         }
1496 
1497         if (cpudelay) {
1498             if (qemuGetSchedstatDelay(&(cpudelay[ncpuinfo]), vm->pid, vcpupid) < 0)
1499                 return -1;
1500         }
1501 
1502         ncpuinfo++;
1503     }
1504 
1505     return ncpuinfo;
1506 }
1507 
1508 
qemuDomainLookupByID(virConnectPtr conn,int id)1509 static virDomainPtr qemuDomainLookupByID(virConnectPtr conn,
1510                                          int id)
1511 {
1512     virQEMUDriver *driver = conn->privateData;
1513     virDomainObj *vm;
1514     virDomainPtr dom = NULL;
1515 
1516     vm = virDomainObjListFindByID(driver->domains, id);
1517 
1518     if (!vm) {
1519         virReportError(VIR_ERR_NO_DOMAIN,
1520                        _("no domain with matching id %d"), id);
1521         goto cleanup;
1522     }
1523 
1524     if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
1525         goto cleanup;
1526 
1527     dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1528 
1529  cleanup:
1530     virDomainObjEndAPI(&vm);
1531     return dom;
1532 }
1533 
qemuDomainLookupByUUID(virConnectPtr conn,const unsigned char * uuid)1534 static virDomainPtr qemuDomainLookupByUUID(virConnectPtr conn,
1535                                            const unsigned char *uuid)
1536 {
1537     virQEMUDriver *driver = conn->privateData;
1538     virDomainObj *vm;
1539     virDomainPtr dom = NULL;
1540 
1541     vm = virDomainObjListFindByUUID(driver->domains, uuid);
1542 
1543     if (!vm) {
1544         char uuidstr[VIR_UUID_STRING_BUFLEN];
1545         virUUIDFormat(uuid, uuidstr);
1546         virReportError(VIR_ERR_NO_DOMAIN,
1547                        _("no domain with matching uuid '%s'"), uuidstr);
1548         goto cleanup;
1549     }
1550 
1551     if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
1552         goto cleanup;
1553 
1554     dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1555 
1556  cleanup:
1557     virDomainObjEndAPI(&vm);
1558     return dom;
1559 }
1560 
qemuDomainLookupByName(virConnectPtr conn,const char * name)1561 static virDomainPtr qemuDomainLookupByName(virConnectPtr conn,
1562                                            const char *name)
1563 {
1564     virQEMUDriver *driver = conn->privateData;
1565     virDomainObj *vm;
1566     virDomainPtr dom = NULL;
1567 
1568     vm = virDomainObjListFindByName(driver->domains, name);
1569 
1570     if (!vm) {
1571         virReportError(VIR_ERR_NO_DOMAIN,
1572                        _("no domain with matching name '%s'"), name);
1573         goto cleanup;
1574     }
1575 
1576     if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
1577         goto cleanup;
1578 
1579     dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1580 
1581  cleanup:
1582     virDomainObjEndAPI(&vm);
1583     return dom;
1584 }
1585 
1586 
qemuDomainIsActive(virDomainPtr dom)1587 static int qemuDomainIsActive(virDomainPtr dom)
1588 {
1589     virDomainObj *obj;
1590     int ret = -1;
1591 
1592     if (!(obj = qemuDomainObjFromDomain(dom)))
1593         goto cleanup;
1594 
1595     if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
1596         goto cleanup;
1597 
1598     ret = virDomainObjIsActive(obj);
1599 
1600  cleanup:
1601     virDomainObjEndAPI(&obj);
1602     return ret;
1603 }
1604 
qemuDomainIsPersistent(virDomainPtr dom)1605 static int qemuDomainIsPersistent(virDomainPtr dom)
1606 {
1607     virDomainObj *obj;
1608     int ret = -1;
1609 
1610     if (!(obj = qemuDomainObjFromDomain(dom)))
1611         goto cleanup;
1612 
1613     if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
1614         goto cleanup;
1615 
1616     ret = obj->persistent;
1617 
1618  cleanup:
1619     virDomainObjEndAPI(&obj);
1620     return ret;
1621 }
1622 
qemuDomainIsUpdated(virDomainPtr dom)1623 static int qemuDomainIsUpdated(virDomainPtr dom)
1624 {
1625     virDomainObj *obj;
1626     int ret = -1;
1627 
1628     if (!(obj = qemuDomainObjFromDomain(dom)))
1629         goto cleanup;
1630 
1631     if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0)
1632         goto cleanup;
1633 
1634     ret = obj->updated;
1635 
1636  cleanup:
1637     virDomainObjEndAPI(&obj);
1638     return ret;
1639 }
1640 
qemuConnectGetVersion(virConnectPtr conn,unsigned long * version)1641 static int qemuConnectGetVersion(virConnectPtr conn, unsigned long *version)
1642 {
1643     virQEMUDriver *driver = conn->privateData;
1644     unsigned int qemuVersion = 0;
1645     g_autoptr(virCaps) caps = NULL;
1646 
1647     if (virConnectGetVersionEnsureACL(conn) < 0)
1648         return -1;
1649 
1650     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
1651         return -1;
1652 
1653     if (virQEMUCapsGetDefaultVersion(caps,
1654                                      driver->qemuCapsCache,
1655                                      &qemuVersion) < 0)
1656         return -1;
1657 
1658     *version = qemuVersion;
1659     return 0;
1660 }
1661 
1662 
qemuConnectGetHostname(virConnectPtr conn)1663 static char *qemuConnectGetHostname(virConnectPtr conn)
1664 {
1665     if (virConnectGetHostnameEnsureACL(conn) < 0)
1666         return NULL;
1667 
1668     return virGetHostname();
1669 }
1670 
1671 
qemuConnectListDomains(virConnectPtr conn,int * ids,int nids)1672 static int qemuConnectListDomains(virConnectPtr conn, int *ids, int nids)
1673 {
1674     virQEMUDriver *driver = conn->privateData;
1675 
1676     if (virConnectListDomainsEnsureACL(conn) < 0)
1677         return -1;
1678 
1679     return virDomainObjListGetActiveIDs(driver->domains, ids, nids,
1680                                         virConnectListDomainsCheckACL, conn);
1681 }
1682 
qemuConnectNumOfDomains(virConnectPtr conn)1683 static int qemuConnectNumOfDomains(virConnectPtr conn)
1684 {
1685     virQEMUDriver *driver = conn->privateData;
1686 
1687     if (virConnectNumOfDomainsEnsureACL(conn) < 0)
1688         return -1;
1689 
1690     return virDomainObjListNumOfDomains(driver->domains, true,
1691                                         virConnectNumOfDomainsCheckACL, conn);
1692 }
1693 
1694 
qemuDomainCreateXML(virConnectPtr conn,const char * xml,unsigned int flags)1695 static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
1696                                         const char *xml,
1697                                         unsigned int flags)
1698 {
1699     virQEMUDriver *driver = conn->privateData;
1700     g_autoptr(virDomainDef) def = NULL;
1701     virDomainObj *vm = NULL;
1702     virDomainPtr dom = NULL;
1703     virObjectEvent *event = NULL;
1704     virObjectEvent *event2 = NULL;
1705     unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
1706     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
1707                                VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
1708 
1709     virCheckFlags(VIR_DOMAIN_START_PAUSED |
1710                   VIR_DOMAIN_START_AUTODESTROY |
1711                   VIR_DOMAIN_START_VALIDATE, NULL);
1712 
1713     if (flags & VIR_DOMAIN_START_VALIDATE)
1714         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1715     if (flags & VIR_DOMAIN_START_PAUSED)
1716         start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
1717     if (flags & VIR_DOMAIN_START_AUTODESTROY)
1718         start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
1719 
1720     virNWFilterReadLockFilterUpdates();
1721 
1722     if (!(def = virDomainDefParseString(xml, driver->xmlopt,
1723                                         NULL, parse_flags)))
1724         goto cleanup;
1725 
1726     if (virDomainCreateXMLEnsureACL(conn, def) < 0)
1727         goto cleanup;
1728 
1729     if (!(vm = virDomainObjListAdd(driver->domains, &def,
1730                                    driver->xmlopt,
1731                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1732                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
1733                                    NULL)))
1734         goto cleanup;
1735 
1736     if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_START,
1737                             flags) < 0) {
1738         qemuDomainRemoveInactiveJob(driver, vm);
1739         goto cleanup;
1740     }
1741 
1742     if (qemuProcessStart(conn, driver, vm, NULL, QEMU_ASYNC_JOB_START,
1743                          NULL, -1, NULL, NULL,
1744                          VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
1745                          start_flags) < 0) {
1746         virDomainAuditStart(vm, "booted", false);
1747         qemuDomainRemoveInactive(driver, vm);
1748         qemuProcessEndJob(driver, vm);
1749         goto cleanup;
1750     }
1751 
1752     event = virDomainEventLifecycleNewFromObj(vm,
1753                                      VIR_DOMAIN_EVENT_STARTED,
1754                                      VIR_DOMAIN_EVENT_STARTED_BOOTED);
1755     if (event && (flags & VIR_DOMAIN_START_PAUSED)) {
1756         /* There are two classes of event-watching clients - those
1757          * that only care about on/off (and must see a started event
1758          * no matter what, but don't care about suspend events), and
1759          * those that also care about running/paused.  To satisfy both
1760          * client types, we have to send two events.  */
1761         event2 = virDomainEventLifecycleNewFromObj(vm,
1762                                           VIR_DOMAIN_EVENT_SUSPENDED,
1763                                           VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1764     }
1765     virDomainAuditStart(vm, "booted", true);
1766 
1767     dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1768 
1769     qemuProcessEndJob(driver, vm);
1770 
1771  cleanup:
1772     virDomainObjEndAPI(&vm);
1773     virObjectEventStateQueue(driver->domainEventState, event);
1774     virObjectEventStateQueue(driver->domainEventState, event2);
1775     virNWFilterUnlockFilterUpdates();
1776     return dom;
1777 }
1778 
1779 
qemuDomainSuspend(virDomainPtr dom)1780 static int qemuDomainSuspend(virDomainPtr dom)
1781 {
1782     virQEMUDriver *driver = dom->conn->privateData;
1783     virDomainObj *vm;
1784     int ret = -1;
1785     qemuDomainObjPrivate *priv;
1786     virDomainPausedReason reason;
1787     int state;
1788 
1789     if (!(vm = qemuDomainObjFromDomain(dom)))
1790         return -1;
1791 
1792     if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
1793         goto cleanup;
1794 
1795     priv = vm->privateData;
1796 
1797     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_SUSPEND) < 0)
1798         goto cleanup;
1799 
1800     if (virDomainObjCheckActive(vm) < 0)
1801         goto endjob;
1802 
1803     if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT)
1804         reason = VIR_DOMAIN_PAUSED_MIGRATION;
1805     else if (priv->job.asyncJob == QEMU_ASYNC_JOB_SNAPSHOT)
1806         reason = VIR_DOMAIN_PAUSED_SNAPSHOT;
1807     else
1808         reason = VIR_DOMAIN_PAUSED_USER;
1809 
1810     state = virDomainObjGetState(vm, NULL);
1811     if (state == VIR_DOMAIN_PMSUSPENDED) {
1812         virReportError(VIR_ERR_OPERATION_INVALID,
1813                        "%s", _("domain is pmsuspended"));
1814         goto endjob;
1815     }
1816     if (state != VIR_DOMAIN_PAUSED) {
1817         if (qemuProcessStopCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0)
1818             goto endjob;
1819     }
1820     qemuDomainSaveStatus(vm);
1821     ret = 0;
1822 
1823  endjob:
1824     qemuDomainObjEndJob(driver, vm);
1825 
1826  cleanup:
1827     virDomainObjEndAPI(&vm);
1828 
1829     return ret;
1830 }
1831 
1832 
qemuDomainResume(virDomainPtr dom)1833 static int qemuDomainResume(virDomainPtr dom)
1834 {
1835     virQEMUDriver *driver = dom->conn->privateData;
1836     virDomainObj *vm;
1837     int ret = -1;
1838     int state;
1839     int reason;
1840 
1841     if (!(vm = qemuDomainObjFromDomain(dom)))
1842         return -1;
1843 
1844     if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
1845         goto cleanup;
1846 
1847     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1848         goto cleanup;
1849 
1850     if (virDomainObjCheckActive(vm) < 0)
1851         goto endjob;
1852 
1853     state = virDomainObjGetState(vm, &reason);
1854     if (state == VIR_DOMAIN_PMSUSPENDED) {
1855         virReportError(VIR_ERR_OPERATION_INVALID,
1856                        "%s", _("domain is pmsuspended"));
1857         goto endjob;
1858     }
1859     if (state == VIR_DOMAIN_RUNNING) {
1860         virReportError(VIR_ERR_OPERATION_INVALID,
1861                        "%s", _("domain is already running"));
1862         goto endjob;
1863     }
1864     if ((state == VIR_DOMAIN_CRASHED &&
1865          reason == VIR_DOMAIN_CRASHED_PANICKED) ||
1866         state == VIR_DOMAIN_PAUSED) {
1867         if (qemuProcessStartCPUs(driver, vm,
1868                                  VIR_DOMAIN_RUNNING_UNPAUSED,
1869                                  QEMU_ASYNC_JOB_NONE) < 0) {
1870             if (virGetLastErrorCode() == VIR_ERR_OK)
1871                 virReportError(VIR_ERR_OPERATION_FAILED,
1872                                "%s", _("resume operation failed"));
1873             goto endjob;
1874         }
1875     }
1876     qemuDomainSaveStatus(vm);
1877     ret = 0;
1878 
1879  endjob:
1880     qemuDomainObjEndJob(driver, vm);
1881 
1882  cleanup:
1883     virDomainObjEndAPI(&vm);
1884     return ret;
1885 }
1886 
1887 
1888 static int
qemuDomainShutdownFlagsAgent(virQEMUDriver * driver,virDomainObj * vm,bool isReboot,bool reportError)1889 qemuDomainShutdownFlagsAgent(virQEMUDriver *driver,
1890                              virDomainObj *vm,
1891                              bool isReboot,
1892                              bool reportError)
1893 {
1894     int ret = -1;
1895     qemuAgent *agent;
1896     int agentFlag = isReboot ?  QEMU_AGENT_SHUTDOWN_REBOOT :
1897         QEMU_AGENT_SHUTDOWN_POWERDOWN;
1898 
1899     if (qemuDomainObjBeginAgentJob(driver, vm,
1900                                    QEMU_AGENT_JOB_MODIFY) < 0)
1901         return -1;
1902 
1903     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
1904         virReportError(VIR_ERR_OPERATION_INVALID,
1905                        "%s", _("domain is not running"));
1906         goto endjob;
1907     }
1908 
1909     if (!qemuDomainAgentAvailable(vm, reportError))
1910         goto endjob;
1911 
1912     qemuDomainSetFakeReboot(driver, vm, false);
1913     agent = qemuDomainObjEnterAgent(vm);
1914     ret = qemuAgentShutdown(agent, agentFlag);
1915     qemuDomainObjExitAgent(vm, agent);
1916 
1917  endjob:
1918     qemuDomainObjEndAgentJob(vm);
1919     return ret;
1920 }
1921 
1922 
1923 static int
qemuDomainShutdownFlagsMonitor(virQEMUDriver * driver,virDomainObj * vm,bool isReboot)1924 qemuDomainShutdownFlagsMonitor(virQEMUDriver *driver,
1925                                virDomainObj *vm,
1926                                bool isReboot)
1927 {
1928     int ret = -1;
1929     qemuDomainObjPrivate *priv;
1930 
1931     priv = vm->privateData;
1932 
1933     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1934         return -1;
1935 
1936     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
1937         virReportError(VIR_ERR_OPERATION_INVALID,
1938                        "%s", _("domain is not running"));
1939         goto endjob;
1940     }
1941 
1942     qemuDomainSetFakeReboot(driver, vm, isReboot);
1943     qemuDomainObjEnterMonitor(driver, vm);
1944     ret = qemuMonitorSystemPowerdown(priv->mon);
1945     if (qemuDomainObjExitMonitor(driver, vm) < 0)
1946         ret = -1;
1947 
1948  endjob:
1949     qemuDomainObjEndJob(driver, vm);
1950     return ret;
1951 }
1952 
1953 
qemuDomainShutdownFlags(virDomainPtr dom,unsigned int flags)1954 static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
1955 {
1956     virQEMUDriver *driver = dom->conn->privateData;
1957     virDomainObj *vm;
1958     int ret = -1;
1959     qemuDomainObjPrivate *priv;
1960     bool useAgent = false, agentRequested, acpiRequested;
1961     bool isReboot = false;
1962     bool agentForced;
1963 
1964     virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
1965                   VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
1966 
1967     if (!(vm = qemuDomainObjFromDomain(dom)))
1968         goto cleanup;
1969 
1970     if (vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART ||
1971         vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME) {
1972         isReboot = true;
1973         VIR_INFO("Domain on_poweroff setting overridden, attempting reboot");
1974     }
1975 
1976     priv = vm->privateData;
1977     agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT;
1978     acpiRequested  = flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
1979 
1980     /* Prefer agent unless we were requested to not to. */
1981     if (agentRequested || (!flags && priv->agent))
1982         useAgent = true;
1983 
1984     if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1985         goto cleanup;
1986 
1987     agentForced = agentRequested && !acpiRequested;
1988     if (useAgent) {
1989         ret = qemuDomainShutdownFlagsAgent(driver, vm, isReboot, agentForced);
1990         if (ret < 0 && agentForced)
1991             goto cleanup;
1992     }
1993 
1994     /* If we are not enforced to use just an agent, try ACPI
1995      * shutdown as well in case agent did not succeed.
1996      */
1997     if (!useAgent || (ret < 0 && (acpiRequested || !flags))) {
1998         /* Even if agent failed, we have to check if guest went away
1999          * by itself while our locks were down.  */
2000         if (useAgent && !virDomainObjIsActive(vm)) {
2001             ret = 0;
2002             goto cleanup;
2003         }
2004 
2005         ret = qemuDomainShutdownFlagsMonitor(driver, vm, isReboot);
2006     }
2007 
2008  cleanup:
2009     virDomainObjEndAPI(&vm);
2010     return ret;
2011 }
2012 
qemuDomainShutdown(virDomainPtr dom)2013 static int qemuDomainShutdown(virDomainPtr dom)
2014 {
2015     return qemuDomainShutdownFlags(dom, 0);
2016 }
2017 
2018 
2019 static int
qemuDomainRebootAgent(virQEMUDriver * driver,virDomainObj * vm,bool isReboot,bool agentForced)2020 qemuDomainRebootAgent(virQEMUDriver *driver,
2021                       virDomainObj *vm,
2022                       bool isReboot,
2023                       bool agentForced)
2024 {
2025     qemuAgent *agent;
2026     int ret = -1;
2027     int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
2028 
2029     if (!isReboot)
2030         agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
2031 
2032     if (qemuDomainObjBeginAgentJob(driver, vm,
2033                                    QEMU_AGENT_JOB_MODIFY) < 0)
2034         return -1;
2035 
2036     if (!qemuDomainAgentAvailable(vm, agentForced))
2037         goto endjob;
2038 
2039     if (virDomainObjCheckActive(vm) < 0)
2040         goto endjob;
2041 
2042     qemuDomainSetFakeReboot(driver, vm, false);
2043     agent = qemuDomainObjEnterAgent(vm);
2044     ret = qemuAgentShutdown(agent, agentFlag);
2045     qemuDomainObjExitAgent(vm, agent);
2046 
2047  endjob:
2048     qemuDomainObjEndAgentJob(vm);
2049     return ret;
2050 }
2051 
2052 
2053 static int
qemuDomainRebootMonitor(virQEMUDriver * driver,virDomainObj * vm,bool isReboot)2054 qemuDomainRebootMonitor(virQEMUDriver *driver,
2055                         virDomainObj *vm,
2056                         bool isReboot)
2057 {
2058     qemuDomainObjPrivate *priv = vm->privateData;
2059     int ret = -1;
2060 
2061     if (qemuDomainObjBeginJob(driver, vm,
2062                               QEMU_JOB_MODIFY) < 0)
2063         return -1;
2064 
2065     if (virDomainObjCheckActive(vm) < 0)
2066         goto endjob;
2067 
2068     qemuDomainSetFakeReboot(driver, vm, isReboot);
2069     qemuDomainObjEnterMonitor(driver, vm);
2070     ret = qemuMonitorSystemPowerdown(priv->mon);
2071     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2072         ret = -1;
2073 
2074  endjob:
2075     qemuDomainObjEndJob(driver, vm);
2076     return ret;
2077 }
2078 
2079 
2080 static int
qemuDomainReboot(virDomainPtr dom,unsigned int flags)2081 qemuDomainReboot(virDomainPtr dom, unsigned int flags)
2082 {
2083     virQEMUDriver *driver = dom->conn->privateData;
2084     virDomainObj *vm;
2085     int ret = -1;
2086     qemuDomainObjPrivate *priv;
2087     bool useAgent = false, agentRequested, acpiRequested;
2088     bool isReboot = true;
2089     bool agentForced;
2090 
2091     virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
2092                   VIR_DOMAIN_REBOOT_GUEST_AGENT, -1);
2093 
2094     if (!(vm = qemuDomainObjFromDomain(dom)))
2095         goto cleanup;
2096 
2097     if (vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY ||
2098         vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE) {
2099         isReboot = false;
2100         VIR_INFO("Domain on_reboot setting overridden, shutting down");
2101     }
2102 
2103     priv = vm->privateData;
2104     agentRequested = flags & VIR_DOMAIN_REBOOT_GUEST_AGENT;
2105     acpiRequested  = flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
2106 
2107     /* Prefer agent unless we were requested to not to. */
2108     if (agentRequested || (!flags && priv->agent))
2109         useAgent = true;
2110 
2111     if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
2112         goto cleanup;
2113 
2114     agentForced = agentRequested && !acpiRequested;
2115     if (useAgent)
2116         ret = qemuDomainRebootAgent(driver, vm, isReboot, agentForced);
2117 
2118     if (ret < 0 && agentForced)
2119         goto cleanup;
2120 
2121     /* If we are not enforced to use just an agent, try ACPI
2122      * shutdown as well in case agent did not succeed.
2123      */
2124     if ((!useAgent) ||
2125         (ret < 0 && (acpiRequested || !flags))) {
2126         ret = qemuDomainRebootMonitor(driver, vm, isReboot);
2127     }
2128 
2129  cleanup:
2130     virDomainObjEndAPI(&vm);
2131     return ret;
2132 }
2133 
2134 
2135 static int
qemuDomainReset(virDomainPtr dom,unsigned int flags)2136 qemuDomainReset(virDomainPtr dom, unsigned int flags)
2137 {
2138     virQEMUDriver *driver = dom->conn->privateData;
2139     virDomainObj *vm;
2140     int ret = -1;
2141     qemuDomainObjPrivate *priv;
2142     virDomainState state;
2143 
2144     virCheckFlags(0, -1);
2145 
2146     if (!(vm = qemuDomainObjFromDomain(dom)))
2147         goto cleanup;
2148 
2149     if (virDomainResetEnsureACL(dom->conn, vm->def) < 0)
2150         goto cleanup;
2151 
2152     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2153         goto cleanup;
2154 
2155     if (virDomainObjCheckActive(vm) < 0)
2156         goto endjob;
2157 
2158     priv = vm->privateData;
2159     qemuDomainObjEnterMonitor(driver, vm);
2160     ret = qemuMonitorSystemReset(priv->mon);
2161     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2162         ret = -1;
2163 
2164     priv->fakeReboot = false;
2165 
2166     state = virDomainObjGetState(vm, NULL);
2167     if (state == VIR_DOMAIN_CRASHED)
2168         virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_CRASHED);
2169 
2170  endjob:
2171     qemuDomainObjEndJob(driver, vm);
2172 
2173  cleanup:
2174     virDomainObjEndAPI(&vm);
2175     return ret;
2176 }
2177 
2178 
2179 static int
qemuDomainDestroyFlags(virDomainPtr dom,unsigned int flags)2180 qemuDomainDestroyFlags(virDomainPtr dom,
2181                        unsigned int flags)
2182 {
2183     virQEMUDriver *driver = dom->conn->privateData;
2184     virDomainObj *vm;
2185     int ret = -1;
2186     virObjectEvent *event = NULL;
2187     qemuDomainObjPrivate *priv;
2188     unsigned int stopFlags = 0;
2189     int state;
2190     int reason;
2191     bool starting;
2192 
2193     virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);
2194 
2195     if (!(vm = qemuDomainObjFromDomain(dom)))
2196         return -1;
2197 
2198     priv = vm->privateData;
2199 
2200     if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
2201         goto cleanup;
2202 
2203     if (virDomainObjCheckActive(vm) < 0)
2204         goto cleanup;
2205 
2206     state = virDomainObjGetState(vm, &reason);
2207     starting = (state == VIR_DOMAIN_PAUSED &&
2208                 reason == VIR_DOMAIN_PAUSED_STARTING_UP &&
2209                 !priv->beingDestroyed);
2210 
2211     if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY,
2212                                 !(flags & VIR_DOMAIN_DESTROY_GRACEFUL)) < 0)
2213         goto cleanup;
2214 
2215     if (!virDomainObjIsActive(vm)) {
2216         if (starting) {
2217             VIR_DEBUG("Domain %s is not running anymore", vm->def->name);
2218             ret = 0;
2219         } else {
2220             virReportError(VIR_ERR_OPERATION_INVALID,
2221                            "%s", _("domain is not running"));
2222         }
2223         goto endjob;
2224     }
2225 
2226     qemuDomainSetFakeReboot(driver, vm, false);
2227 
2228     if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN)
2229         stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
2230 
2231     qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED,
2232                     QEMU_ASYNC_JOB_NONE, stopFlags);
2233     event = virDomainEventLifecycleNewFromObj(vm,
2234                                      VIR_DOMAIN_EVENT_STOPPED,
2235                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2236     virDomainAuditStop(vm, "destroyed");
2237 
2238     ret = 0;
2239  endjob:
2240     if (ret == 0)
2241         qemuDomainRemoveInactive(driver, vm);
2242     qemuDomainObjEndJob(driver, vm);
2243 
2244  cleanup:
2245     virDomainObjEndAPI(&vm);
2246     virObjectEventStateQueue(driver->domainEventState, event);
2247     return ret;
2248 }
2249 
2250 static int
qemuDomainDestroy(virDomainPtr dom)2251 qemuDomainDestroy(virDomainPtr dom)
2252 {
2253     return qemuDomainDestroyFlags(dom, 0);
2254 }
2255 
qemuDomainGetOSType(virDomainPtr dom)2256 static char *qemuDomainGetOSType(virDomainPtr dom) {
2257     virDomainObj *vm;
2258     char *type = NULL;
2259 
2260     if (!(vm = qemuDomainObjFromDomain(dom)))
2261         goto cleanup;
2262 
2263     if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
2264         goto cleanup;
2265 
2266     type = g_strdup(virDomainOSTypeToString(vm->def->os.type));
2267 
2268  cleanup:
2269     virDomainObjEndAPI(&vm);
2270     return type;
2271 }
2272 
2273 /* Returns max memory in kb, 0 if error */
2274 static unsigned long long
qemuDomainGetMaxMemory(virDomainPtr dom)2275 qemuDomainGetMaxMemory(virDomainPtr dom)
2276 {
2277     virDomainObj *vm;
2278     unsigned long long ret = 0;
2279 
2280     if (!(vm = qemuDomainObjFromDomain(dom)))
2281         goto cleanup;
2282 
2283     if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
2284         goto cleanup;
2285 
2286     ret = virDomainDefGetMemoryTotal(vm->def);
2287 
2288  cleanup:
2289     virDomainObjEndAPI(&vm);
2290     return ret;
2291 }
2292 
qemuDomainSetMemoryFlags(virDomainPtr dom,unsigned long newmem,unsigned int flags)2293 static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
2294                                     unsigned int flags)
2295 {
2296     virQEMUDriver *driver = dom->conn->privateData;
2297     qemuDomainObjPrivate *priv;
2298     virDomainObj *vm;
2299     virDomainDef *def;
2300     virDomainDef *persistentDef;
2301     int ret = -1, r;
2302     g_autoptr(virQEMUDriverConfig) cfg = NULL;
2303 
2304     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2305                   VIR_DOMAIN_AFFECT_CONFIG |
2306                   VIR_DOMAIN_MEM_MAXIMUM, -1);
2307 
2308     if (!(vm = qemuDomainObjFromDomain(dom)))
2309         goto cleanup;
2310 
2311     cfg = virQEMUDriverGetConfig(driver);
2312 
2313     if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2314         goto cleanup;
2315 
2316     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2317         goto cleanup;
2318 
2319     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
2320         goto endjob;
2321 
2322 
2323     if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
2324         /* resize the maximum memory */
2325 
2326         if (def) {
2327             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2328                            _("cannot resize the maximum memory on an "
2329                              "active domain"));
2330             goto endjob;
2331         }
2332 
2333         if (persistentDef) {
2334             /* resizing memory with NUMA nodes specified doesn't work as there
2335              * is no way to change the individual node sizes with this API */
2336             if (virDomainNumaGetNodeCount(persistentDef->numa) > 0) {
2337                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2338                                _("initial memory size of a domain with NUMA "
2339                                  "nodes cannot be modified with this API"));
2340                 goto endjob;
2341             }
2342 
2343             if (persistentDef->mem.max_memory &&
2344                 persistentDef->mem.max_memory < newmem) {
2345                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2346                                _("cannot set initial memory size greater than "
2347                                  "the maximum memory size"));
2348                 goto endjob;
2349             }
2350 
2351             virDomainDefSetMemoryTotal(persistentDef, newmem);
2352 
2353             if (persistentDef->mem.cur_balloon > newmem)
2354                 persistentDef->mem.cur_balloon = newmem;
2355             ret = virDomainDefSave(persistentDef, driver->xmlopt,
2356                                    cfg->configDir);
2357             goto endjob;
2358         }
2359 
2360     } else {
2361         /* resize the current memory */
2362         unsigned long oldmax = 0;
2363         size_t i;
2364 
2365         if (def) {
2366             oldmax = virDomainDefGetMemoryTotal(def);
2367 
2368             /* While virtio-mem is regular mem from guest POV, it can't be
2369              * modified through this API. */
2370             for (i = 0; i < def->nmems; i++) {
2371                 if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM)
2372                     oldmax -= def->mems[i]->size;
2373             }
2374         }
2375 
2376         if (persistentDef) {
2377             if (!def || oldmax > virDomainDefGetMemoryTotal(persistentDef)) {
2378                 oldmax = virDomainDefGetMemoryTotal(persistentDef);
2379 
2380                 for (i = 0; i < persistentDef->nmems; i++) {
2381                     if (persistentDef->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM)
2382                         oldmax -= persistentDef->mems[i]->size;
2383                 }
2384             }
2385         }
2386 
2387         if (newmem > oldmax) {
2388             virReportError(VIR_ERR_INVALID_ARG, "%s",
2389                            _("cannot set memory higher than max memory"));
2390             goto endjob;
2391         }
2392 
2393         if (def) {
2394             priv = vm->privateData;
2395             qemuDomainObjEnterMonitor(driver, vm);
2396             r = qemuMonitorSetBalloon(priv->mon, newmem);
2397             if (qemuDomainObjExitMonitor(driver, vm) < 0 || r < 0)
2398                 goto endjob;
2399 
2400             /* Lack of balloon support is a fatal error */
2401             if (r == 0) {
2402                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2403                                _("Unable to change memory of active domain without "
2404                                  "the balloon device and guest OS balloon driver"));
2405                 goto endjob;
2406             }
2407         }
2408 
2409         if (persistentDef) {
2410             persistentDef->mem.cur_balloon = newmem;
2411             ret = virDomainDefSave(persistentDef, driver->xmlopt,
2412                                    cfg->configDir);
2413             goto endjob;
2414         }
2415     }
2416 
2417     ret = 0;
2418  endjob:
2419     qemuDomainObjEndJob(driver, vm);
2420 
2421  cleanup:
2422     virDomainObjEndAPI(&vm);
2423     return ret;
2424 }
2425 
qemuDomainSetMemory(virDomainPtr dom,unsigned long newmem)2426 static int qemuDomainSetMemory(virDomainPtr dom, unsigned long newmem)
2427 {
2428     return qemuDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_AFFECT_LIVE);
2429 }
2430 
qemuDomainSetMaxMemory(virDomainPtr dom,unsigned long memory)2431 static int qemuDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
2432 {
2433     return qemuDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
2434 }
2435 
qemuDomainSetMemoryStatsPeriod(virDomainPtr dom,int period,unsigned int flags)2436 static int qemuDomainSetMemoryStatsPeriod(virDomainPtr dom, int period,
2437                                           unsigned int flags)
2438 {
2439     virQEMUDriver *driver = dom->conn->privateData;
2440     qemuDomainObjPrivate *priv;
2441     virDomainObj *vm;
2442     virDomainDef *def;
2443     virDomainDef *persistentDef;
2444     int ret = -1, r;
2445     g_autoptr(virQEMUDriverConfig) cfg = NULL;
2446 
2447     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2448                   VIR_DOMAIN_AFFECT_CONFIG, -1);
2449 
2450     if (!(vm = qemuDomainObjFromDomain(dom)))
2451         goto cleanup;
2452 
2453     cfg = virQEMUDriverGetConfig(driver);
2454 
2455     if (virDomainSetMemoryStatsPeriodEnsureACL(dom->conn, vm->def, flags) < 0)
2456         goto cleanup;
2457 
2458     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2459         goto cleanup;
2460 
2461     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
2462         goto endjob;
2463 
2464     /* Set the balloon driver collection interval */
2465     priv = vm->privateData;
2466 
2467     if (def) {
2468         if (!virDomainDefHasMemballoon(def)) {
2469             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2470                            _("No memory balloon device configured, "
2471                              "can not set the collection period"));
2472             goto endjob;
2473         }
2474 
2475         qemuDomainObjEnterMonitor(driver, vm);
2476         r = qemuMonitorSetMemoryStatsPeriod(priv->mon, def->memballoon, period);
2477         if (qemuDomainObjExitMonitor(driver, vm) < 0)
2478             goto endjob;
2479         if (r < 0) {
2480             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2481                            _("unable to set balloon driver collection period"));
2482             goto endjob;
2483         }
2484 
2485         def->memballoon->period = period;
2486         qemuDomainSaveStatus(vm);
2487     }
2488 
2489     if (persistentDef) {
2490         if (!virDomainDefHasMemballoon(persistentDef)) {
2491             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2492                            _("No memory balloon device configured, "
2493                              "can not set the collection period"));
2494             goto endjob;
2495         }
2496         persistentDef->memballoon->period = period;
2497         ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);
2498         goto endjob;
2499     }
2500 
2501     ret = 0;
2502  endjob:
2503     qemuDomainObjEndJob(driver, vm);
2504 
2505  cleanup:
2506     virDomainObjEndAPI(&vm);
2507     return ret;
2508 }
2509 
qemuDomainInjectNMI(virDomainPtr domain,unsigned int flags)2510 static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
2511 {
2512     virQEMUDriver *driver = domain->conn->privateData;
2513     virDomainObj *vm = NULL;
2514     int ret = -1;
2515     qemuDomainObjPrivate *priv;
2516 
2517     virCheckFlags(0, -1);
2518 
2519     if (!(vm = qemuDomainObjFromDomain(domain)))
2520         return -1;
2521 
2522     if (virDomainInjectNMIEnsureACL(domain->conn, vm->def) < 0)
2523         goto cleanup;
2524 
2525     priv = vm->privateData;
2526 
2527     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2528         goto cleanup;
2529 
2530     if (virDomainObjCheckActive(vm) < 0)
2531         goto endjob;
2532 
2533     qemuDomainObjEnterMonitor(driver, vm);
2534     ret = qemuMonitorInjectNMI(priv->mon);
2535     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2536         ret = -1;
2537 
2538  endjob:
2539     qemuDomainObjEndJob(driver, vm);
2540 
2541  cleanup:
2542     virDomainObjEndAPI(&vm);
2543     return ret;
2544 }
2545 
qemuDomainSendKey(virDomainPtr domain,unsigned int codeset,unsigned int holdtime,unsigned int * keycodes,int nkeycodes,unsigned int flags)2546 static int qemuDomainSendKey(virDomainPtr domain,
2547                              unsigned int codeset,
2548                              unsigned int holdtime,
2549                              unsigned int *keycodes,
2550                              int nkeycodes,
2551                              unsigned int flags)
2552 {
2553     virQEMUDriver *driver = domain->conn->privateData;
2554     virDomainObj *vm = NULL;
2555     int ret = -1;
2556     qemuDomainObjPrivate *priv;
2557 
2558     virCheckFlags(0, -1);
2559 
2560     /* translate the keycode to QNUM for qemu driver */
2561     if (codeset != VIR_KEYCODE_SET_QNUM) {
2562         size_t i;
2563         int keycode;
2564 
2565         for (i = 0; i < nkeycodes; i++) {
2566             keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_QNUM,
2567                                                keycodes[i]);
2568             if (keycode < 0) {
2569                 virReportError(VIR_ERR_INTERNAL_ERROR,
2570                                _("cannot translate keycode %u of %s codeset to qnum keycode"),
2571                                keycodes[i],
2572                                virKeycodeSetTypeToString(codeset));
2573                 return -1;
2574             }
2575             keycodes[i] = keycode;
2576         }
2577     }
2578 
2579     if (!(vm = qemuDomainObjFromDomain(domain)))
2580         goto cleanup;
2581 
2582     priv = vm->privateData;
2583 
2584     if (virDomainSendKeyEnsureACL(domain->conn, vm->def) < 0)
2585         goto cleanup;
2586 
2587     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2588         goto cleanup;
2589 
2590     if (virDomainObjCheckActive(vm) < 0)
2591         goto endjob;
2592 
2593     qemuDomainObjEnterMonitor(driver, vm);
2594     ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
2595     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2596         ret = -1;
2597 
2598  endjob:
2599     qemuDomainObjEndJob(driver, vm);
2600 
2601  cleanup:
2602     virDomainObjEndAPI(&vm);
2603     return ret;
2604 }
2605 
2606 
2607 static int
qemuDomainGetInfo(virDomainPtr dom,virDomainInfoPtr info)2608 qemuDomainGetInfo(virDomainPtr dom,
2609                   virDomainInfoPtr info)
2610 {
2611     unsigned long long maxmem;
2612     virDomainObj *vm;
2613     int ret = -1;
2614 
2615     if (!(vm = qemuDomainObjFromDomain(dom)))
2616         goto cleanup;
2617 
2618     if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
2619         goto cleanup;
2620 
2621     qemuDomainUpdateCurrentMemorySize(vm);
2622 
2623     memset(info, 0, sizeof(*info));
2624 
2625     info->state = virDomainObjGetState(vm, NULL);
2626 
2627     maxmem = virDomainDefGetMemoryTotal(vm->def);
2628     if (VIR_ASSIGN_IS_OVERFLOW(info->maxMem, maxmem)) {
2629         virReportError(VIR_ERR_OVERFLOW, "%s",
2630                        _("Initial memory size too large"));
2631         goto cleanup;
2632     }
2633 
2634     if (VIR_ASSIGN_IS_OVERFLOW(info->memory, vm->def->mem.cur_balloon)) {
2635         virReportError(VIR_ERR_OVERFLOW, "%s",
2636                        _("Current memory size too large"));
2637         goto cleanup;
2638     }
2639 
2640     if (virDomainObjIsActive(vm)) {
2641         if (qemuGetProcessInfo(&(info->cpuTime), NULL, NULL, vm->pid, 0) < 0) {
2642             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2643                            _("cannot read cputime for domain"));
2644             goto cleanup;
2645         }
2646     }
2647 
2648     if (VIR_ASSIGN_IS_OVERFLOW(info->nrVirtCpu, virDomainDefGetVcpus(vm->def))) {
2649         virReportError(VIR_ERR_OVERFLOW, "%s", _("cpu count too large"));
2650         goto cleanup;
2651     }
2652 
2653     ret = 0;
2654 
2655  cleanup:
2656     virDomainObjEndAPI(&vm);
2657     return ret;
2658 }
2659 
2660 static int
qemuDomainGetState(virDomainPtr dom,int * state,int * reason,unsigned int flags)2661 qemuDomainGetState(virDomainPtr dom,
2662                    int *state,
2663                    int *reason,
2664                    unsigned int flags)
2665 {
2666     virDomainObj *vm;
2667     int ret = -1;
2668 
2669     virCheckFlags(0, -1);
2670 
2671     if (!(vm = qemuDomainObjFromDomain(dom)))
2672         goto cleanup;
2673 
2674     if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
2675         goto cleanup;
2676 
2677     *state = virDomainObjGetState(vm, reason);
2678     ret = 0;
2679 
2680  cleanup:
2681     virDomainObjEndAPI(&vm);
2682     return ret;
2683 }
2684 
2685 static int
qemuDomainGetControlInfo(virDomainPtr dom,virDomainControlInfoPtr info,unsigned int flags)2686 qemuDomainGetControlInfo(virDomainPtr dom,
2687                           virDomainControlInfoPtr info,
2688                           unsigned int flags)
2689 {
2690     virDomainObj *vm;
2691     qemuDomainObjPrivate *priv;
2692     int ret = -1;
2693 
2694     virCheckFlags(0, -1);
2695 
2696     if (!(vm = qemuDomainObjFromDomain(dom)))
2697         goto cleanup;
2698 
2699     if (virDomainGetControlInfoEnsureACL(dom->conn, vm->def) < 0)
2700         goto cleanup;
2701 
2702     if (virDomainObjCheckActive(vm) < 0)
2703         goto cleanup;
2704 
2705     priv = vm->privateData;
2706 
2707     memset(info, 0, sizeof(*info));
2708 
2709     if (priv->monError) {
2710         info->state = VIR_DOMAIN_CONTROL_ERROR;
2711         info->details = VIR_DOMAIN_CONTROL_ERROR_REASON_MONITOR;
2712     } else if (priv->job.active) {
2713         if (virTimeMillisNow(&info->stateTime) < 0)
2714             goto cleanup;
2715         if (priv->job.current) {
2716             info->state = VIR_DOMAIN_CONTROL_JOB;
2717             info->stateTime -= priv->job.current->started;
2718         } else {
2719             if (priv->monStart > 0) {
2720                 info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
2721                 info->stateTime -= priv->monStart;
2722             } else {
2723                 /* At this point the domain has an active job, but monitor was
2724                  * not entered and the domain object lock is not held thus we
2725                  * are stuck in the job forever due to a programming error.
2726                  */
2727                 info->state = VIR_DOMAIN_CONTROL_ERROR;
2728                 info->details = VIR_DOMAIN_CONTROL_ERROR_REASON_INTERNAL;
2729                 info->stateTime = 0;
2730             }
2731         }
2732     } else {
2733         info->state = VIR_DOMAIN_CONTROL_OK;
2734     }
2735 
2736     ret = 0;
2737 
2738  cleanup:
2739     virDomainObjEndAPI(&vm);
2740     return ret;
2741 }
2742 
2743 
2744 /* The vm must be active + locked. Vm will be unlocked and
2745  * potentially free'd after this returns (eg transient VMs are freed
2746  * shutdown). So 'vm' must not be referenced by the caller after
2747  * this returns (whether returning success or failure).
2748  */
2749 static int
qemuDomainSaveInternal(virQEMUDriver * driver,virDomainObj * vm,const char * path,int compressed,virCommand * compressor,const char * xmlin,unsigned int flags)2750 qemuDomainSaveInternal(virQEMUDriver *driver,
2751                        virDomainObj *vm, const char *path,
2752                        int compressed, virCommand *compressor,
2753                        const char *xmlin, unsigned int flags)
2754 {
2755     g_autofree char *xml = NULL;
2756     bool was_running = false;
2757     int ret = -1;
2758     virObjectEvent *event = NULL;
2759     qemuDomainObjPrivate *priv = vm->privateData;
2760     virQEMUSaveData *data = NULL;
2761     g_autoptr(qemuDomainSaveCookie) cookie = NULL;
2762 
2763     if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
2764         goto cleanup;
2765 
2766     if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_SAVE,
2767                                    VIR_DOMAIN_JOB_OPERATION_SAVE, flags) < 0)
2768         goto cleanup;
2769 
2770     if (!virDomainObjIsActive(vm)) {
2771         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2772                        _("guest unexpectedly quit"));
2773         goto endjob;
2774     }
2775 
2776     priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
2777 
2778     /* Pause */
2779     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2780         was_running = true;
2781         if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
2782                                 QEMU_ASYNC_JOB_SAVE) < 0)
2783             goto endjob;
2784 
2785         if (!virDomainObjIsActive(vm)) {
2786             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2787                            _("guest unexpectedly quit"));
2788             goto endjob;
2789         }
2790     }
2791 
2792    /* libvirt-domain.c already guaranteed these two flags are exclusive.  */
2793     if (flags & VIR_DOMAIN_SAVE_RUNNING)
2794         was_running = true;
2795     else if (flags & VIR_DOMAIN_SAVE_PAUSED)
2796         was_running = false;
2797 
2798     /* Get XML for the domain.  Restore needs only the inactive xml,
2799      * including secure.  We should get the same result whether xmlin
2800      * is NULL or whether it was the live xml of the domain moments
2801      * before.  */
2802     if (xmlin) {
2803         g_autoptr(virDomainDef) def = NULL;
2804 
2805         if (!(def = virDomainDefParseString(xmlin, driver->xmlopt,
2806                                             priv->qemuCaps,
2807                                             VIR_DOMAIN_DEF_PARSE_INACTIVE |
2808                                             VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) {
2809             goto endjob;
2810         }
2811         if (!qemuDomainCheckABIStability(driver, vm, def))
2812             goto endjob;
2813         xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, def, NULL, true, true);
2814     } else {
2815         xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, vm->def,
2816                                       priv->origCPU, true, true);
2817     }
2818     if (!xml) {
2819         virReportError(VIR_ERR_OPERATION_FAILED,
2820                        "%s", _("failed to get domain xml"));
2821         goto endjob;
2822     }
2823 
2824     if (!(cookie = qemuDomainSaveCookieNew(vm)))
2825         goto endjob;
2826 
2827     if (!(data = virQEMUSaveDataNew(xml, cookie, was_running, compressed,
2828                                     driver->xmlopt)))
2829         goto endjob;
2830     xml = NULL;
2831 
2832     ret = qemuSaveImageCreate(driver, vm, path, data, compressor,
2833                               flags, QEMU_ASYNC_JOB_SAVE);
2834     if (ret < 0)
2835         goto endjob;
2836 
2837     /* Shut it down */
2838     qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED,
2839                     QEMU_ASYNC_JOB_SAVE, 0);
2840     virDomainAuditStop(vm, "saved");
2841     event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
2842                                               VIR_DOMAIN_EVENT_STOPPED_SAVED);
2843  endjob:
2844     if (ret < 0) {
2845         if (was_running && virDomainObjIsActive(vm)) {
2846             virErrorPtr save_err;
2847             virErrorPreserveLast(&save_err);
2848             if (qemuProcessStartCPUs(driver, vm,
2849                                      VIR_DOMAIN_RUNNING_SAVE_CANCELED,
2850                                      QEMU_ASYNC_JOB_SAVE) < 0) {
2851                 VIR_WARN("Unable to resume guest CPUs after save failure");
2852                 virObjectEventStateQueue(driver->domainEventState,
2853                                      virDomainEventLifecycleNewFromObj(vm,
2854                                          VIR_DOMAIN_EVENT_SUSPENDED,
2855                                          VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR));
2856             }
2857             virErrorRestore(&save_err);
2858         }
2859     }
2860     qemuDomainObjEndAsyncJob(driver, vm);
2861     if (ret == 0)
2862         qemuDomainRemoveInactiveJob(driver, vm);
2863 
2864  cleanup:
2865     virQEMUSaveDataFree(data);
2866     virObjectEventStateQueue(driver->domainEventState, event);
2867     return ret;
2868 }
2869 
2870 
2871 static int
qemuDomainSaveFlags(virDomainPtr dom,const char * path,const char * dxml,unsigned int flags)2872 qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
2873                     unsigned int flags)
2874 {
2875     virQEMUDriver *driver = dom->conn->privateData;
2876     int compressed;
2877     g_autoptr(virCommand) compressor = NULL;
2878     int ret = -1;
2879     virDomainObj *vm = NULL;
2880     g_autoptr(virQEMUDriverConfig) cfg = NULL;
2881 
2882     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
2883                   VIR_DOMAIN_SAVE_RUNNING |
2884                   VIR_DOMAIN_SAVE_PAUSED, -1);
2885 
2886     cfg = virQEMUDriverGetConfig(driver);
2887     if ((compressed = qemuSaveImageGetCompressionProgram(cfg->saveImageFormat,
2888                                                          &compressor,
2889                                                          "save", false)) < 0)
2890         goto cleanup;
2891 
2892     if (!(vm = qemuDomainObjFromDomain(dom)))
2893         goto cleanup;
2894 
2895     if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
2896         goto cleanup;
2897 
2898     if (virDomainObjCheckActive(vm) < 0)
2899         goto cleanup;
2900 
2901     ret = qemuDomainSaveInternal(driver, vm, path, compressed,
2902                                  compressor, dxml, flags);
2903 
2904  cleanup:
2905     virDomainObjEndAPI(&vm);
2906     return ret;
2907 }
2908 
2909 static int
qemuDomainSave(virDomainPtr dom,const char * path)2910 qemuDomainSave(virDomainPtr dom, const char *path)
2911 {
2912     return qemuDomainSaveFlags(dom, path, NULL, 0);
2913 }
2914 
2915 static char *
qemuDomainManagedSavePath(virQEMUDriver * driver,virDomainObj * vm)2916 qemuDomainManagedSavePath(virQEMUDriver *driver, virDomainObj *vm)
2917 {
2918     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
2919 
2920     return g_strdup_printf("%s/%s.save", cfg->saveDir, vm->def->name);
2921 }
2922 
2923 static int
qemuDomainManagedSave(virDomainPtr dom,unsigned int flags)2924 qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
2925 {
2926     virQEMUDriver *driver = dom->conn->privateData;
2927     g_autoptr(virQEMUDriverConfig) cfg = NULL;
2928     int compressed;
2929     g_autoptr(virCommand) compressor = NULL;
2930     virDomainObj *vm;
2931     g_autofree char *name = NULL;
2932     int ret = -1;
2933 
2934     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
2935                   VIR_DOMAIN_SAVE_RUNNING |
2936                   VIR_DOMAIN_SAVE_PAUSED, -1);
2937 
2938     if (!(vm = qemuDomainObjFromDomain(dom)))
2939         return -1;
2940 
2941     if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
2942         goto cleanup;
2943 
2944     if (virDomainObjCheckActive(vm) < 0)
2945         goto cleanup;
2946 
2947     if (!vm->persistent) {
2948         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2949                        _("cannot do managed save for transient domain"));
2950         goto cleanup;
2951     }
2952 
2953     cfg = virQEMUDriverGetConfig(driver);
2954     if ((compressed = qemuSaveImageGetCompressionProgram(cfg->saveImageFormat,
2955                                                          &compressor,
2956                                                          "save", false)) < 0)
2957         goto cleanup;
2958 
2959     if (!(name = qemuDomainManagedSavePath(driver, vm)))
2960         goto cleanup;
2961 
2962     VIR_INFO("Saving state of domain '%s' to '%s'", vm->def->name, name);
2963 
2964     ret = qemuDomainSaveInternal(driver, vm, name, compressed,
2965                                  compressor, NULL, flags);
2966     if (ret == 0)
2967         vm->hasManagedSave = true;
2968 
2969  cleanup:
2970     virDomainObjEndAPI(&vm);
2971 
2972     return ret;
2973 }
2974 
2975 static int
qemuDomainManagedSaveLoad(virDomainObj * vm,void * opaque)2976 qemuDomainManagedSaveLoad(virDomainObj *vm,
2977                           void *opaque)
2978 {
2979     virQEMUDriver *driver = opaque;
2980     g_autofree char *name = NULL;
2981     int ret = -1;
2982 
2983     virObjectLock(vm);
2984 
2985     if (!(name = qemuDomainManagedSavePath(driver, vm)))
2986         goto cleanup;
2987 
2988     vm->hasManagedSave = virFileExists(name);
2989 
2990     ret = 0;
2991  cleanup:
2992     virObjectUnlock(vm);
2993     return ret;
2994 }
2995 
2996 
2997 static int
qemuDomainHasManagedSaveImage(virDomainPtr dom,unsigned int flags)2998 qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
2999 {
3000     virDomainObj *vm = NULL;
3001     int ret = -1;
3002 
3003     virCheckFlags(0, -1);
3004 
3005     if (!(vm = qemuDomainObjFromDomain(dom)))
3006         return -1;
3007 
3008     if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
3009         goto cleanup;
3010 
3011     ret = vm->hasManagedSave;
3012 
3013  cleanup:
3014     virDomainObjEndAPI(&vm);
3015     return ret;
3016 }
3017 
3018 static int
qemuDomainManagedSaveRemove(virDomainPtr dom,unsigned int flags)3019 qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
3020 {
3021     virQEMUDriver *driver = dom->conn->privateData;
3022     virDomainObj *vm;
3023     int ret = -1;
3024     g_autofree char *name = NULL;
3025 
3026     virCheckFlags(0, -1);
3027 
3028     if (!(vm = qemuDomainObjFromDomain(dom)))
3029         return -1;
3030 
3031     if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
3032         goto cleanup;
3033 
3034     if (!(name = qemuDomainManagedSavePath(driver, vm)))
3035         goto cleanup;
3036 
3037     if (unlink(name) < 0) {
3038         virReportSystemError(errno,
3039                              _("Failed to remove managed save file '%s'"),
3040                              name);
3041         goto cleanup;
3042     }
3043 
3044     vm->hasManagedSave = false;
3045     ret = 0;
3046 
3047  cleanup:
3048     virDomainObjEndAPI(&vm);
3049     return ret;
3050 }
3051 
3052 
3053 /**
3054  * qemuDumpWaitForCompletion:
3055  * @vm: domain object
3056  *
3057  * If the query dump capability exists, then it's possible to start a
3058  * guest memory dump operation using a thread via a 'detach' qualifier
3059  * to the dump guest memory command. This allows the async check if the
3060  * dump is done.
3061  *
3062  * Returns 0 on success, -1 on failure
3063  */
3064 static int
qemuDumpWaitForCompletion(virDomainObj * vm)3065 qemuDumpWaitForCompletion(virDomainObj *vm)
3066 {
3067     qemuDomainObjPrivate *priv = vm->privateData;
3068     qemuDomainJobPrivate *jobPriv = priv->job.privateData;
3069 
3070     VIR_DEBUG("Waiting for dump completion");
3071     while (!jobPriv->dumpCompleted && !priv->job.abortJob) {
3072         if (virDomainObjWait(vm) < 0)
3073             return -1;
3074     }
3075 
3076     if (priv->job.current->stats.dump.status == QEMU_MONITOR_DUMP_STATUS_FAILED) {
3077         if (priv->job.error)
3078             virReportError(VIR_ERR_OPERATION_FAILED,
3079                            _("memory-only dump failed: %s"),
3080                            priv->job.error);
3081         else
3082             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3083                            _("memory-only dump failed for unknown reason"));
3084 
3085         return -1;
3086     }
3087     qemuDomainJobInfoUpdateTime(priv->job.current);
3088 
3089     return 0;
3090 }
3091 
3092 
3093 static int
qemuDumpToFd(virQEMUDriver * driver,virDomainObj * vm,int fd,qemuDomainAsyncJob asyncJob,const char * dumpformat)3094 qemuDumpToFd(virQEMUDriver *driver,
3095              virDomainObj *vm,
3096              int fd,
3097              qemuDomainAsyncJob asyncJob,
3098              const char *dumpformat)
3099 {
3100     qemuDomainObjPrivate *priv = vm->privateData;
3101     bool detach = false;
3102     int ret = -1;
3103 
3104     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
3105         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3106                        _("dump-guest-memory is not supported"));
3107         return -1;
3108     }
3109 
3110     detach = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_COMPLETED);
3111 
3112     if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
3113         return -1;
3114 
3115     if (detach)
3116         priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP;
3117     else
3118         g_clear_pointer(&priv->job.current, qemuDomainJobInfoFree);
3119 
3120     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
3121         return -1;
3122 
3123     if (dumpformat) {
3124         ret = qemuMonitorGetDumpGuestMemoryCapability(priv->mon, dumpformat);
3125 
3126         if (ret <= 0) {
3127             virReportError(VIR_ERR_INVALID_ARG,
3128                            _("unsupported dumpformat '%s' "
3129                              "for this QEMU binary"),
3130                            dumpformat);
3131             ignore_value(qemuDomainObjExitMonitor(driver, vm));
3132             return -1;
3133         }
3134     }
3135 
3136     ret = qemuMonitorDumpToFd(priv->mon, fd, dumpformat, detach);
3137 
3138     if ((qemuDomainObjExitMonitor(driver, vm) < 0) || ret < 0)
3139         return -1;
3140 
3141     if (detach)
3142         ret = qemuDumpWaitForCompletion(vm);
3143 
3144     return ret;
3145 }
3146 
3147 
3148 static int
doCoreDump(virQEMUDriver * driver,virDomainObj * vm,const char * path,unsigned int dump_flags,unsigned int dumpformat)3149 doCoreDump(virQEMUDriver *driver,
3150            virDomainObj *vm,
3151            const char *path,
3152            unsigned int dump_flags,
3153            unsigned int dumpformat)
3154 {
3155     int fd = -1;
3156     int ret = -1;
3157     virFileWrapperFd *wrapperFd = NULL;
3158     int directFlag = 0;
3159     bool needUnlink = false;
3160     unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
3161     const char *memory_dump_format = NULL;
3162     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
3163     g_autoptr(virCommand) compressor = NULL;
3164 
3165     /* We reuse "save" flag for "dump" here. Then, we can support the same
3166      * format in "save" and "dump". This path doesn't need the compression
3167      * program to exist and can ignore the return value - it only cares to
3168      * get the compressor */
3169     ignore_value(qemuSaveImageGetCompressionProgram(cfg->dumpImageFormat,
3170                                                     &compressor,
3171                                                     "dump", true));
3172 
3173     /* Create an empty file with appropriate ownership.  */
3174     if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
3175         flags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3176         directFlag = virFileDirectFdFlag();
3177         if (directFlag < 0) {
3178             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3179                            _("bypass cache unsupported by this system"));
3180             goto cleanup;
3181         }
3182     }
3183     if ((fd = virQEMUFileOpenAs(cfg->user, cfg->group, false, path,
3184                              O_CREAT | O_TRUNC | O_WRONLY | directFlag,
3185                              &needUnlink)) < 0)
3186         goto cleanup;
3187 
3188     if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
3189         goto cleanup;
3190 
3191     if (dump_flags & VIR_DUMP_MEMORY_ONLY) {
3192         if (!(memory_dump_format = qemuDumpFormatTypeToString(dumpformat))) {
3193             virReportError(VIR_ERR_INVALID_ARG,
3194                            _("unknown dumpformat '%d'"), dumpformat);
3195             goto cleanup;
3196         }
3197 
3198         /* qemu dumps in "elf" without dumpformat set */
3199         if (STREQ(memory_dump_format, "elf"))
3200             memory_dump_format = NULL;
3201 
3202         if (qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP,
3203                          memory_dump_format) < 0)
3204             goto cleanup;
3205     } else {
3206         if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) {
3207             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3208                            _("kdump-compressed format is only supported with "
3209                              "memory-only dump"));
3210             goto cleanup;
3211         }
3212 
3213         if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
3214             goto cleanup;
3215 
3216         if (qemuMigrationSrcToFile(driver, vm, fd, compressor,
3217                                    QEMU_ASYNC_JOB_DUMP) < 0)
3218             goto cleanup;
3219     }
3220 
3221     if (VIR_CLOSE(fd) < 0) {
3222         virReportSystemError(errno,
3223                              _("unable to close file %s"),
3224                              path);
3225         goto cleanup;
3226     }
3227     if (qemuDomainFileWrapperFDClose(vm, wrapperFd) < 0)
3228         goto cleanup;
3229 
3230     ret = 0;
3231 
3232  cleanup:
3233     VIR_FORCE_CLOSE(fd);
3234     if (qemuDomainFileWrapperFDClose(vm, wrapperFd) < 0)
3235         ret = -1;
3236     virFileWrapperFdFree(wrapperFd);
3237     if (ret != 0 && needUnlink)
3238         unlink(path);
3239     return ret;
3240 }
3241 
3242 
3243 static int
qemuDomainCoreDumpWithFormat(virDomainPtr dom,const char * path,unsigned int dumpformat,unsigned int flags)3244 qemuDomainCoreDumpWithFormat(virDomainPtr dom,
3245                              const char *path,
3246                              unsigned int dumpformat,
3247                              unsigned int flags)
3248 {
3249     virQEMUDriver *driver = dom->conn->privateData;
3250     virDomainObj *vm;
3251     qemuDomainObjPrivate *priv = NULL;
3252     bool resume = false, paused = false;
3253     int ret = -1;
3254     virObjectEvent *event = NULL;
3255 
3256     virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
3257                   VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
3258                   VIR_DUMP_MEMORY_ONLY, -1);
3259 
3260     if (!(vm = qemuDomainObjFromDomain(dom)))
3261         return -1;
3262 
3263     if (virDomainCoreDumpWithFormatEnsureACL(dom->conn, vm->def) < 0)
3264         goto cleanup;
3265 
3266     if (qemuDomainObjBeginAsyncJob(driver, vm,
3267                                    QEMU_ASYNC_JOB_DUMP,
3268                                    VIR_DOMAIN_JOB_OPERATION_DUMP,
3269                                    flags) < 0)
3270         goto cleanup;
3271 
3272     if (virDomainObjCheckActive(vm) < 0)
3273         goto endjob;
3274 
3275     priv = vm->privateData;
3276     priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
3277 
3278     /* Migrate will always stop the VM, so the resume condition is
3279        independent of whether the stop command is issued.  */
3280     resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
3281 
3282     /* Pause domain for non-live dump */
3283     if (!(flags & VIR_DUMP_LIVE) &&
3284         virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
3285         if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP,
3286                                 QEMU_ASYNC_JOB_DUMP) < 0)
3287             goto endjob;
3288         paused = true;
3289 
3290         if (!virDomainObjIsActive(vm)) {
3291             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3292                            _("guest unexpectedly quit"));
3293             goto endjob;
3294         }
3295     }
3296 
3297     if ((ret = doCoreDump(driver, vm, path, flags, dumpformat)) < 0)
3298         goto endjob;
3299 
3300     paused = true;
3301 
3302  endjob:
3303     if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
3304         qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED,
3305                         QEMU_ASYNC_JOB_DUMP, 0);
3306         virDomainAuditStop(vm, "crashed");
3307         event = virDomainEventLifecycleNewFromObj(vm,
3308                                          VIR_DOMAIN_EVENT_STOPPED,
3309                                          VIR_DOMAIN_EVENT_STOPPED_CRASHED);
3310     } else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
3311                virDomainObjIsActive(vm)) {
3312         if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
3313             qemuDomainObjEnterMonitor(driver, vm);
3314             ret = qemuMonitorSystemReset(priv->mon);
3315             if (qemuDomainObjExitMonitor(driver, vm) < 0)
3316                 ret = -1;
3317         }
3318 
3319         if (resume && virDomainObjIsActive(vm)) {
3320             if (qemuProcessStartCPUs(driver, vm,
3321                                      VIR_DOMAIN_RUNNING_UNPAUSED,
3322                                      QEMU_ASYNC_JOB_DUMP) < 0) {
3323                 event = virDomainEventLifecycleNewFromObj(vm,
3324                                                           VIR_DOMAIN_EVENT_SUSPENDED,
3325                                                           VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
3326                 if (virGetLastErrorCode() == VIR_ERR_OK)
3327                     virReportError(VIR_ERR_OPERATION_FAILED,
3328                                    "%s", _("resuming after dump failed"));
3329             }
3330         }
3331     }
3332 
3333     qemuDomainObjEndAsyncJob(driver, vm);
3334     if (ret == 0 && flags & VIR_DUMP_CRASH)
3335         qemuDomainRemoveInactiveJob(driver, vm);
3336 
3337  cleanup:
3338     virDomainObjEndAPI(&vm);
3339     virObjectEventStateQueue(driver->domainEventState, event);
3340     return ret;
3341 }
3342 
3343 
3344 static int
qemuDomainCoreDump(virDomainPtr dom,const char * path,unsigned int flags)3345 qemuDomainCoreDump(virDomainPtr dom,
3346                    const char *path,
3347                    unsigned int flags)
3348 {
3349     return qemuDomainCoreDumpWithFormat(dom, path,
3350                                         VIR_DOMAIN_CORE_DUMP_FORMAT_RAW,
3351                                         flags);
3352 }
3353 
3354 
3355 static char *
qemuDomainScreenshot(virDomainPtr dom,virStreamPtr st,unsigned int screen,unsigned int flags)3356 qemuDomainScreenshot(virDomainPtr dom,
3357                      virStreamPtr st,
3358                      unsigned int screen,
3359                      unsigned int flags)
3360 {
3361     virQEMUDriver *driver = dom->conn->privateData;
3362     virDomainObj *vm;
3363     qemuDomainObjPrivate *priv;
3364     g_autofree char *tmp = NULL;
3365     int tmp_fd = -1;
3366     size_t i;
3367     const char *videoAlias = NULL;
3368     char *ret = NULL;
3369     bool unlink_tmp = false;
3370 
3371     virCheckFlags(0, NULL);
3372 
3373     if (!(vm = qemuDomainObjFromDomain(dom)))
3374         goto cleanup;
3375 
3376     priv = vm->privateData;
3377 
3378     if (virDomainScreenshotEnsureACL(dom->conn, vm->def) < 0)
3379         goto cleanup;
3380 
3381     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
3382         goto cleanup;
3383 
3384     if (virDomainObjCheckActive(vm) < 0)
3385         goto endjob;
3386 
3387     if (!vm->def->nvideos) {
3388         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3389                       _("no screens to take screenshot from"));
3390         goto endjob;
3391     }
3392 
3393     if (screen) {
3394         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SCREENDUMP_DEVICE)) {
3395             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3396                            _("qemu does not allow specifying screen ID"));
3397             goto endjob;
3398         }
3399 
3400         for (i = 0; i < vm->def->nvideos; i++) {
3401             const virDomainVideoDef *video = vm->def->videos[i];
3402 
3403             if (screen < video->heads) {
3404                 videoAlias = video->info.alias;
3405                 break;
3406             }
3407 
3408             screen -= video->heads;
3409         }
3410 
3411         if (i == vm->def->nvideos) {
3412             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3413                            _("no such screen ID"));
3414             goto endjob;
3415         }
3416     }
3417 
3418     tmp = g_strdup_printf("%s/qemu.screendump.XXXXXX", priv->libDir);
3419 
3420     if ((tmp_fd = g_mkstemp_full(tmp, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) {
3421         virReportSystemError(errno, _("g_mkstemp(\"%s\") failed"), tmp);
3422         goto endjob;
3423     }
3424     unlink_tmp = true;
3425 
3426     qemuSecurityDomainSetPathLabel(driver, vm, tmp, false);
3427 
3428     qemuDomainObjEnterMonitor(driver, vm);
3429     if (qemuMonitorScreendump(priv->mon, videoAlias, screen, tmp) < 0) {
3430         ignore_value(qemuDomainObjExitMonitor(driver, vm));
3431         goto endjob;
3432     }
3433     if (qemuDomainObjExitMonitor(driver, vm) < 0)
3434         goto endjob;
3435 
3436     if (VIR_CLOSE(tmp_fd) < 0) {
3437         virReportSystemError(errno, _("unable to close %s"), tmp);
3438         goto endjob;
3439     }
3440 
3441     if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
3442         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3443                        _("unable to open stream"));
3444         goto endjob;
3445     }
3446 
3447     ret = g_strdup("image/x-portable-pixmap");
3448 
3449  endjob:
3450     VIR_FORCE_CLOSE(tmp_fd);
3451     if (unlink_tmp)
3452         unlink(tmp);
3453 
3454     qemuDomainObjEndJob(driver, vm);
3455 
3456  cleanup:
3457     virDomainObjEndAPI(&vm);
3458     return ret;
3459 }
3460 
3461 static char *
getAutoDumpPath(virQEMUDriver * driver,virDomainObj * vm)3462 getAutoDumpPath(virQEMUDriver *driver,
3463                 virDomainObj *vm)
3464 {
3465     const char *root = driver->embeddedRoot;
3466     g_autofree char *domname = virDomainDefGetShortName(vm->def);
3467     g_autoptr(GDateTime) now = g_date_time_new_now_local();
3468     g_autofree char *nowstr = NULL;
3469     g_autoptr(virQEMUDriverConfig) cfg = NULL;
3470 
3471     if (!domname)
3472         return NULL;
3473 
3474     cfg = virQEMUDriverGetConfig(driver);
3475 
3476     nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S");
3477 
3478     if (root && !STRPREFIX(cfg->autoDumpPath, root)) {
3479         g_autofree char * hash = virDomainDriverGenerateRootHash(QEMU_DRIVER_NAME, root);
3480         return g_strdup_printf("%s/%s-%s-%s", cfg->autoDumpPath, hash, domname, nowstr);
3481     }
3482 
3483     return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, nowstr);
3484 }
3485 
3486 static void
processWatchdogEvent(virQEMUDriver * driver,virDomainObj * vm,int action)3487 processWatchdogEvent(virQEMUDriver *driver,
3488                      virDomainObj *vm,
3489                      int action)
3490 {
3491     int ret;
3492     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
3493     g_autofree char *dumpfile = getAutoDumpPath(driver, vm);
3494     unsigned int flags = VIR_DUMP_MEMORY_ONLY;
3495 
3496     if (!dumpfile)
3497         return;
3498 
3499     switch (action) {
3500     case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
3501         if (qemuDomainObjBeginAsyncJob(driver, vm,
3502                                        QEMU_ASYNC_JOB_DUMP,
3503                                        VIR_DOMAIN_JOB_OPERATION_DUMP,
3504                                        flags) < 0) {
3505             return;
3506         }
3507 
3508         if (virDomainObjCheckActive(vm) < 0)
3509             goto endjob;
3510 
3511         flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
3512         if ((ret = doCoreDump(driver, vm, dumpfile, flags,
3513                               VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0)
3514             virReportError(VIR_ERR_OPERATION_FAILED,
3515                            "%s", _("Dump failed"));
3516 
3517         ret = qemuProcessStartCPUs(driver, vm,
3518                                    VIR_DOMAIN_RUNNING_UNPAUSED,
3519                                    QEMU_ASYNC_JOB_DUMP);
3520 
3521         if (ret < 0)
3522             virReportError(VIR_ERR_OPERATION_FAILED,
3523                            "%s", _("Resuming after dump failed"));
3524         break;
3525     default:
3526         return;
3527     }
3528 
3529  endjob:
3530     qemuDomainObjEndAsyncJob(driver, vm);
3531 }
3532 
3533 static int
doCoreDumpToAutoDumpPath(virQEMUDriver * driver,virDomainObj * vm,unsigned int flags)3534 doCoreDumpToAutoDumpPath(virQEMUDriver *driver,
3535                          virDomainObj *vm,
3536                          unsigned int flags)
3537 {
3538     int ret = -1;
3539     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
3540     g_autofree char *dumpfile = getAutoDumpPath(driver, vm);
3541 
3542     if (!dumpfile)
3543         return -1;
3544 
3545     flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
3546     if ((ret = doCoreDump(driver, vm, dumpfile, flags,
3547                           VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0)
3548         virReportError(VIR_ERR_OPERATION_FAILED,
3549                        "%s", _("Dump failed"));
3550     return ret;
3551 }
3552 
3553 
3554 static void
qemuProcessGuestPanicEventInfo(virQEMUDriver * driver,virDomainObj * vm,qemuMonitorEventPanicInfo * info)3555 qemuProcessGuestPanicEventInfo(virQEMUDriver *driver,
3556                                virDomainObj *vm,
3557                                qemuMonitorEventPanicInfo *info)
3558 {
3559     g_autofree char *msg = qemuMonitorGuestPanicEventInfoFormatMsg(info);
3560     g_autofree char *timestamp = virTimeStringNow();
3561 
3562     if (msg && timestamp)
3563         qemuDomainLogAppendMessage(driver, vm, "%s: panic %s\n", timestamp, msg);
3564 }
3565 
3566 
3567 static void
processGuestPanicEvent(virQEMUDriver * driver,virDomainObj * vm,int action,qemuMonitorEventPanicInfo * info)3568 processGuestPanicEvent(virQEMUDriver *driver,
3569                        virDomainObj *vm,
3570                        int action,
3571                        qemuMonitorEventPanicInfo *info)
3572 {
3573     qemuDomainObjPrivate *priv = vm->privateData;
3574     virObjectEvent *event = NULL;
3575     bool removeInactive = false;
3576     unsigned long flags = VIR_DUMP_MEMORY_ONLY;
3577 
3578     if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_DUMP,
3579                                    VIR_DOMAIN_JOB_OPERATION_DUMP, flags) < 0)
3580         return;
3581 
3582     if (!virDomainObjIsActive(vm)) {
3583         VIR_DEBUG("Ignoring GUEST_PANICKED event from inactive domain %s",
3584                   vm->def->name);
3585         goto endjob;
3586     }
3587 
3588     if (info)
3589         qemuProcessGuestPanicEventInfo(driver, vm, info);
3590 
3591     virDomainObjSetState(vm, VIR_DOMAIN_CRASHED, VIR_DOMAIN_CRASHED_PANICKED);
3592 
3593     event = virDomainEventLifecycleNewFromObj(vm,
3594                                               VIR_DOMAIN_EVENT_CRASHED,
3595                                               VIR_DOMAIN_EVENT_CRASHED_PANICKED);
3596 
3597     virObjectEventStateQueue(driver->domainEventState, event);
3598 
3599     qemuDomainSaveStatus(vm);
3600 
3601     if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
3602         VIR_WARN("Unable to release lease on %s", vm->def->name);
3603     VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
3604 
3605     switch (action) {
3606     case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY:
3607         if (doCoreDumpToAutoDumpPath(driver, vm, flags) < 0)
3608             goto endjob;
3609         G_GNUC_FALLTHROUGH;
3610 
3611     case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
3612         qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED,
3613                         QEMU_ASYNC_JOB_DUMP, 0);
3614         event = virDomainEventLifecycleNewFromObj(vm,
3615                                                   VIR_DOMAIN_EVENT_STOPPED,
3616                                                   VIR_DOMAIN_EVENT_STOPPED_CRASHED);
3617 
3618         virObjectEventStateQueue(driver->domainEventState, event);
3619         virDomainAuditStop(vm, "destroyed");
3620         removeInactive = true;
3621         break;
3622 
3623     case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_RESTART:
3624         if (doCoreDumpToAutoDumpPath(driver, vm, flags) < 0)
3625             goto endjob;
3626         G_GNUC_FALLTHROUGH;
3627 
3628     case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
3629         qemuDomainSetFakeReboot(driver, vm, true);
3630         qemuProcessShutdownOrReboot(driver, vm);
3631         break;
3632 
3633     case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
3634         /* the VM is kept around for debugging */
3635         break;
3636 
3637     default:
3638         break;
3639     }
3640 
3641  endjob:
3642     qemuDomainObjEndAsyncJob(driver, vm);
3643     if (removeInactive)
3644         qemuDomainRemoveInactiveJob(driver, vm);
3645 }
3646 
3647 
3648 static void
processDeviceDeletedEvent(virQEMUDriver * driver,virDomainObj * vm,const char * devAlias)3649 processDeviceDeletedEvent(virQEMUDriver *driver,
3650                           virDomainObj *vm,
3651                           const char *devAlias)
3652 {
3653     virDomainDeviceDef dev;
3654 
3655     VIR_DEBUG("Removing device %s from domain %p %s",
3656               devAlias, vm, vm->def->name);
3657 
3658     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
3659         return;
3660 
3661     if (!virDomainObjIsActive(vm)) {
3662         VIR_DEBUG("Domain is not running");
3663         goto endjob;
3664     }
3665 
3666     if (STRPREFIX(devAlias, "vcpu")) {
3667         qemuDomainRemoveVcpuAlias(driver, vm, devAlias);
3668     } else {
3669         if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
3670             goto endjob;
3671 
3672         if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
3673             goto endjob;
3674     }
3675 
3676     qemuDomainSaveStatus(vm);
3677 
3678  endjob:
3679     qemuDomainObjEndJob(driver, vm);
3680 }
3681 
3682 
3683 static void
syncNicRxFilterMacAddr(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3684 syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilter *guestFilter,
3685                        virNetDevRxFilter *hostFilter)
3686 {
3687     char newMacStr[VIR_MAC_STRING_BUFLEN];
3688 
3689     if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) {
3690         virMacAddrFormat(&guestFilter->mac, newMacStr);
3691 
3692         /* set new MAC address from guest to associated macvtap device */
3693         if (virNetDevSetMAC(ifname, &guestFilter->mac) < 0) {
3694             VIR_WARN("Couldn't set new MAC address %s to device %s "
3695                      "while responding to NIC_RX_FILTER_CHANGED",
3696                      newMacStr, ifname);
3697         } else {
3698             VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr);
3699         }
3700     }
3701 }
3702 
3703 
3704 static void
syncNicRxFilterGuestMulticast(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3705 syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilter *guestFilter,
3706                               virNetDevRxFilter *hostFilter)
3707 {
3708     size_t i, j;
3709     bool found;
3710     char macstr[VIR_MAC_STRING_BUFLEN];
3711 
3712     for (i = 0; i < guestFilter->multicast.nTable; i++) {
3713         found = false;
3714 
3715         for (j = 0; j < hostFilter->multicast.nTable; j++) {
3716             if (virMacAddrCmp(&guestFilter->multicast.table[i],
3717                               &hostFilter->multicast.table[j]) == 0) {
3718                 found = true;
3719                 break;
3720             }
3721         }
3722 
3723         if (!found) {
3724             virMacAddrFormat(&guestFilter->multicast.table[i], macstr);
3725 
3726             if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i]) < 0) {
3727                 VIR_WARN("Couldn't add new multicast MAC address %s to "
3728                          "device %s while responding to NIC_RX_FILTER_CHANGED",
3729                          macstr, ifname);
3730             } else {
3731                 VIR_DEBUG("Added multicast MAC %s to %s interface",
3732                           macstr, ifname);
3733             }
3734         }
3735     }
3736 }
3737 
3738 
3739 static void
syncNicRxFilterHostMulticast(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3740 syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilter *guestFilter,
3741                              virNetDevRxFilter *hostFilter)
3742 {
3743     size_t i, j;
3744     bool found;
3745     char macstr[VIR_MAC_STRING_BUFLEN];
3746 
3747     for (i = 0; i < hostFilter->multicast.nTable; i++) {
3748         found = false;
3749 
3750         for (j = 0; j < guestFilter->multicast.nTable; j++) {
3751             if (virMacAddrCmp(&hostFilter->multicast.table[i],
3752                               &guestFilter->multicast.table[j]) == 0) {
3753                 found = true;
3754                 break;
3755             }
3756         }
3757 
3758         if (!found) {
3759             virMacAddrFormat(&hostFilter->multicast.table[i], macstr);
3760 
3761             if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i]) < 0) {
3762                 VIR_WARN("Couldn't delete multicast MAC address %s from "
3763                          "device %s while responding to NIC_RX_FILTER_CHANGED",
3764                          macstr, ifname);
3765             } else {
3766                 VIR_DEBUG("Deleted multicast MAC %s from %s interface",
3767                           macstr, ifname);
3768             }
3769         }
3770     }
3771 }
3772 
3773 
3774 static void
syncNicRxFilterPromiscMode(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3775 syncNicRxFilterPromiscMode(char *ifname,
3776                            virNetDevRxFilter *guestFilter,
3777                            virNetDevRxFilter *hostFilter)
3778 {
3779     bool promisc;
3780     bool setpromisc = false;
3781 
3782     /* Set macvtap promisc mode to true if the guest has vlans defined */
3783     /* or synchronize the macvtap promisc mode if different from guest */
3784     if (guestFilter->vlan.nTable > 0) {
3785         if (!hostFilter->promiscuous) {
3786             setpromisc = true;
3787             promisc = true;
3788         }
3789     } else if (hostFilter->promiscuous != guestFilter->promiscuous) {
3790         setpromisc = true;
3791         promisc = guestFilter->promiscuous;
3792     }
3793 
3794     if (setpromisc) {
3795         if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
3796             VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
3797                      "while responding to NIC_RX_FILTER_CHANGED",
3798                      promisc ? "true" : "false", ifname);
3799         }
3800     }
3801 }
3802 
3803 
3804 static void
syncNicRxFilterMultiMode(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3805 syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilter *guestFilter,
3806                          virNetDevRxFilter *hostFilter)
3807 {
3808     if (hostFilter->multicast.mode != guestFilter->multicast.mode ||
3809         (guestFilter->multicast.overflow &&
3810          guestFilter->multicast.mode == VIR_NETDEV_RX_FILTER_MODE_NORMAL)) {
3811         switch (guestFilter->multicast.mode) {
3812         case VIR_NETDEV_RX_FILTER_MODE_ALL:
3813             if (virNetDevSetRcvAllMulti(ifname, true) < 0) {
3814                 VIR_WARN("Couldn't set allmulticast flag to 'on' for "
3815                          "device %s while responding to "
3816                          "NIC_RX_FILTER_CHANGED", ifname);
3817             }
3818             break;
3819 
3820         case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
3821             if (guestFilter->multicast.overflow &&
3822                 (hostFilter->multicast.mode == VIR_NETDEV_RX_FILTER_MODE_ALL)) {
3823                 break;
3824             }
3825 
3826             if (virNetDevSetRcvMulti(ifname, true) < 0) {
3827                 VIR_WARN("Couldn't set multicast flag to 'on' for "
3828                          "device %s while responding to "
3829                          "NIC_RX_FILTER_CHANGED", ifname);
3830             }
3831 
3832             if (virNetDevSetRcvAllMulti(ifname,
3833                                         guestFilter->multicast.overflow) < 0) {
3834                 VIR_WARN("Couldn't set allmulticast flag to '%s' for "
3835                          "device %s while responding to "
3836                          "NIC_RX_FILTER_CHANGED",
3837                          virTristateSwitchTypeToString(virTristateSwitchFromBool(guestFilter->multicast.overflow)),
3838                          ifname);
3839             }
3840             break;
3841 
3842         case VIR_NETDEV_RX_FILTER_MODE_NONE:
3843             if (virNetDevSetRcvAllMulti(ifname, false) < 0) {
3844                 VIR_WARN("Couldn't set allmulticast flag to 'off' for "
3845                          "device %s while responding to "
3846                          "NIC_RX_FILTER_CHANGED", ifname);
3847             }
3848 
3849             if (virNetDevSetRcvMulti(ifname, false) < 0) {
3850                 VIR_WARN("Couldn't set multicast flag to 'off' for "
3851                          "device %s while responding to "
3852                          "NIC_RX_FILTER_CHANGED",
3853                          ifname);
3854             }
3855             break;
3856         }
3857     }
3858 }
3859 
3860 
3861 static void
syncNicRxFilterDeviceOptions(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3862 syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilter *guestFilter,
3863                            virNetDevRxFilter *hostFilter)
3864 {
3865     syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
3866     syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
3867 }
3868 
3869 
3870 static void
syncNicRxFilterMulticast(char * ifname,virNetDevRxFilter * guestFilter,virNetDevRxFilter * hostFilter)3871 syncNicRxFilterMulticast(char *ifname,
3872                          virNetDevRxFilter *guestFilter,
3873                          virNetDevRxFilter *hostFilter)
3874 {
3875     syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter);
3876     syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter);
3877 }
3878 
3879 static void
processNicRxFilterChangedEvent(virQEMUDriver * driver,virDomainObj * vm,const char * devAlias)3880 processNicRxFilterChangedEvent(virQEMUDriver *driver,
3881                                virDomainObj *vm,
3882                                const char *devAlias)
3883 {
3884     qemuDomainObjPrivate *priv = vm->privateData;
3885     virDomainDeviceDef dev;
3886     virDomainNetDef *def;
3887     virNetDevRxFilter *guestFilter = NULL;
3888     virNetDevRxFilter *hostFilter = NULL;
3889     int ret;
3890 
3891     VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
3892               "from domain %p %s",
3893               devAlias, vm, vm->def->name);
3894 
3895     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
3896         goto cleanup;
3897 
3898     if (!virDomainObjIsActive(vm)) {
3899         VIR_DEBUG("Domain is not running");
3900         goto endjob;
3901     }
3902 
3903     if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
3904         VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
3905                  "non-existent device %s in domain %s",
3906                  devAlias, vm->def->name);
3907         goto endjob;
3908     }
3909     if (dev.type != VIR_DOMAIN_DEVICE_NET) {
3910         VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
3911                  "non-network device %s in domain %s",
3912                  devAlias, vm->def->name);
3913         goto endjob;
3914     }
3915     def = dev.data.net;
3916 
3917     if (!virDomainNetGetActualTrustGuestRxFilters(def)) {
3918         VIR_DEBUG("ignore NIC_RX_FILTER_CHANGED event for network "
3919                   "device %s in domain %s",
3920                   def->info.alias, vm->def->name);
3921         /* not sending "query-rx-filter" will also suppress any
3922          * further NIC_RX_FILTER_CHANGED events for this device
3923          */
3924         goto endjob;
3925     }
3926 
3927     /* handle the event - send query-rx-filter and respond to it. */
3928 
3929     VIR_DEBUG("process NIC_RX_FILTER_CHANGED event for network "
3930               "device %s in domain %s", def->info.alias, vm->def->name);
3931 
3932     qemuDomainObjEnterMonitor(driver, vm);
3933     ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &guestFilter);
3934     if (qemuDomainObjExitMonitor(driver, vm) < 0)
3935         ret = -1;
3936     if (ret < 0)
3937         goto endjob;
3938 
3939     if (virDomainNetGetActualType(def) == VIR_DOMAIN_NET_TYPE_DIRECT) {
3940 
3941         if (virNetDevGetRxFilter(def->ifname, &hostFilter)) {
3942             VIR_WARN("Couldn't get current RX filter for device %s "
3943                      "while responding to NIC_RX_FILTER_CHANGED",
3944                      def->ifname);
3945             goto endjob;
3946         }
3947 
3948         /* For macvtap connections, set the following macvtap network device
3949          * attributes to match those of the guest network device:
3950          * - MAC address
3951          * - Multicast MAC address table
3952          * - Device options:
3953          *   - PROMISC
3954          *   - MULTICAST
3955          *   - ALLMULTI
3956          */
3957         syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
3958         syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
3959         syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
3960     }
3961 
3962     if (virDomainNetGetActualType(def) == VIR_DOMAIN_NET_TYPE_NETWORK) {
3963         const char *brname = virDomainNetGetActualBridgeName(def);
3964 
3965         /* For libivrt network connections, set the following TUN/TAP network
3966          * device attributes to match those of the guest network device:
3967          * - QoS filters (which are based on MAC address)
3968          */
3969         if (virDomainNetGetActualBandwidth(def) &&
3970             def->data.network.actual &&
3971             virNetDevBandwidthUpdateFilter(brname, &guestFilter->mac,
3972                                            def->data.network.actual->class_id) < 0)
3973             goto endjob;
3974     }
3975 
3976  endjob:
3977     qemuDomainObjEndJob(driver, vm);
3978 
3979  cleanup:
3980     virNetDevRxFilterFree(hostFilter);
3981     virNetDevRxFilterFree(guestFilter);
3982 }
3983 
3984 
3985 static void
processSerialChangedEvent(virQEMUDriver * driver,virDomainObj * vm,const char * devAlias,bool connected)3986 processSerialChangedEvent(virQEMUDriver *driver,
3987                           virDomainObj *vm,
3988                           const char *devAlias,
3989                           bool connected)
3990 {
3991     virDomainChrDeviceState newstate;
3992     virObjectEvent *event = NULL;
3993     virDomainDeviceDef dev;
3994     qemuDomainObjPrivate *priv = vm->privateData;
3995 
3996     if (connected)
3997         newstate = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
3998     else
3999         newstate = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
4000 
4001     VIR_DEBUG("Changing serial port state %s in domain %p %s",
4002               devAlias, vm, vm->def->name);
4003 
4004     if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED &&
4005         virDomainObjIsActive(vm) && priv->agent) {
4006         /* peek into the domain definition to find the channel */
4007         if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) == 0 &&
4008             dev.type == VIR_DOMAIN_DEVICE_CHR &&
4009             dev.data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
4010             dev.data.chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
4011             STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0"))
4012             /* Close agent monitor early, so that other threads
4013              * waiting for the agent to reply can finish and our
4014              * job we acquire below can succeed. */
4015             qemuAgentNotifyClose(priv->agent);
4016 
4017         /* now discard the data, since it may possibly change once we unlock
4018          * while entering the job */
4019         memset(&dev, 0, sizeof(dev));
4020     }
4021 
4022     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4023         return;
4024 
4025     if (!virDomainObjIsActive(vm)) {
4026         VIR_DEBUG("Domain is not running");
4027         goto endjob;
4028     }
4029 
4030     if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
4031         goto endjob;
4032 
4033     /* we care only about certain devices */
4034     if (dev.type != VIR_DOMAIN_DEVICE_CHR ||
4035         dev.data.chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL ||
4036         dev.data.chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
4037         goto endjob;
4038 
4039     dev.data.chr->state = newstate;
4040 
4041     qemuDomainSaveStatus(vm);
4042 
4043     if (STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0")) {
4044         if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED) {
4045             if (qemuConnectAgent(driver, vm) < 0)
4046                 goto endjob;
4047         } else {
4048             if (priv->agent) {
4049                 qemuAgentClose(priv->agent);
4050                 priv->agent = NULL;
4051             }
4052             priv->agentError = false;
4053         }
4054 
4055         event = virDomainEventAgentLifecycleNewFromObj(vm, newstate,
4056                                                        VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL);
4057         virObjectEventStateQueue(driver->domainEventState, event);
4058     }
4059 
4060  endjob:
4061     qemuDomainObjEndJob(driver, vm);
4062 }
4063 
4064 
4065 static void
processBlockJobEvent(virQEMUDriver * driver,virDomainObj * vm,const char * diskAlias,int type,int status)4066 processBlockJobEvent(virQEMUDriver *driver,
4067                      virDomainObj *vm,
4068                      const char *diskAlias,
4069                      int type,
4070                      int status)
4071 {
4072     virDomainDiskDef *disk;
4073     g_autoptr(qemuBlockJobData) job = NULL;
4074 
4075     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4076         return;
4077 
4078     if (!virDomainObjIsActive(vm)) {
4079         VIR_DEBUG("Domain is not running");
4080         goto endjob;
4081     }
4082 
4083     if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL))) {
4084         VIR_DEBUG("disk %s not found", diskAlias);
4085         goto endjob;
4086     }
4087 
4088     if (!(job = qemuBlockJobDiskGetJob(disk))) {
4089         VIR_DEBUG("creating new block job object for '%s'", diskAlias);
4090         if (!(job = qemuBlockJobDiskNew(vm, disk, type, diskAlias)))
4091             goto endjob;
4092         job->state = QEMU_BLOCKJOB_STATE_RUNNING;
4093     }
4094 
4095     job->newstate = status;
4096 
4097     qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
4098 
4099  endjob:
4100     qemuDomainObjEndJob(driver, vm);
4101 }
4102 
4103 
4104 static void
processJobStatusChangeEvent(virQEMUDriver * driver,virDomainObj * vm,qemuBlockJobData * job)4105 processJobStatusChangeEvent(virQEMUDriver *driver,
4106                             virDomainObj *vm,
4107                             qemuBlockJobData *job)
4108 {
4109     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4110         return;
4111 
4112     if (!virDomainObjIsActive(vm)) {
4113         VIR_DEBUG("Domain is not running");
4114         goto endjob;
4115     }
4116 
4117     qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
4118 
4119  endjob:
4120     qemuDomainObjEndJob(driver, vm);
4121 }
4122 
4123 
4124 static void
processMonitorEOFEvent(virQEMUDriver * driver,virDomainObj * vm)4125 processMonitorEOFEvent(virQEMUDriver *driver,
4126                        virDomainObj *vm)
4127 {
4128     qemuDomainObjPrivate *priv = vm->privateData;
4129     int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
4130     int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
4131     const char *auditReason = "shutdown";
4132     unsigned int stopFlags = 0;
4133     virObjectEvent *event = NULL;
4134 
4135     if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY, true) < 0)
4136         return;
4137 
4138     if (!virDomainObjIsActive(vm)) {
4139         VIR_DEBUG("Domain %p '%s' is not active, ignoring EOF",
4140                   vm, vm->def->name);
4141         goto endjob;
4142     }
4143 
4144     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTDOWN) {
4145         VIR_DEBUG("Monitor connection to '%s' closed without SHUTDOWN event; "
4146                   "assuming the domain crashed", vm->def->name);
4147         eventReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
4148         stopReason = VIR_DOMAIN_SHUTOFF_CRASHED;
4149         auditReason = "failed";
4150     }
4151 
4152     if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
4153         stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
4154         qemuMigrationDstErrorSave(driver, vm->def->name,
4155                                   qemuMonitorLastError(priv->mon));
4156     }
4157 
4158     event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
4159                                               eventReason);
4160     qemuProcessStop(driver, vm, stopReason, QEMU_ASYNC_JOB_NONE, stopFlags);
4161     virDomainAuditStop(vm, auditReason);
4162     virObjectEventStateQueue(driver->domainEventState, event);
4163 
4164  endjob:
4165     qemuDomainRemoveInactive(driver, vm);
4166     qemuDomainObjEndJob(driver, vm);
4167 }
4168 
4169 
4170 static void
processPRDisconnectEvent(virDomainObj * vm)4171 processPRDisconnectEvent(virDomainObj *vm)
4172 {
4173     qemuDomainObjPrivate *priv = vm->privateData;
4174 
4175     if (!virDomainObjIsActive(vm))
4176         return;
4177 
4178     if (!priv->prDaemonRunning &&
4179         qemuDomainDefHasManagedPR(vm))
4180         qemuProcessStartManagedPRDaemon(vm);
4181 }
4182 
4183 
4184 static void
processRdmaGidStatusChangedEvent(virDomainObj * vm,qemuMonitorRdmaGidStatus * info)4185 processRdmaGidStatusChangedEvent(virDomainObj *vm,
4186                                  qemuMonitorRdmaGidStatus *info)
4187 {
4188     unsigned int prefix_len;
4189     virSocketAddr addr;
4190     g_autofree char *addrStr = NULL;
4191     int rc;
4192 
4193     if (!virDomainObjIsActive(vm))
4194         return;
4195 
4196     VIR_DEBUG("netdev=%s, gid_status=%d, subnet_prefix=0x%llx, interface_id=0x%llx",
4197               info->netdev, info->gid_status, info->subnet_prefix,
4198               info->interface_id);
4199 
4200     if (info->subnet_prefix) {
4201         uint32_t ipv6[4] = {0};
4202 
4203         prefix_len = 64;
4204         memcpy(&ipv6[0], &info->subnet_prefix, sizeof(info->subnet_prefix));
4205         memcpy(&ipv6[2], &info->interface_id, sizeof(info->interface_id));
4206         virSocketAddrSetIPv6AddrNetOrder(&addr, ipv6);
4207     } else {
4208         prefix_len = 24;
4209         virSocketAddrSetIPv4AddrNetOrder(&addr, info->interface_id >> 32);
4210     }
4211 
4212     if (!(addrStr = virSocketAddrFormat(&addr)))
4213         return;
4214 
4215     if (info->gid_status) {
4216         VIR_DEBUG("Adding %s to %s", addrStr, info->netdev);
4217         rc = virNetDevIPAddrAdd(info->netdev, &addr, NULL, prefix_len);
4218     } else {
4219         VIR_DEBUG("Removing %s from %s", addrStr, info->netdev);
4220         rc = virNetDevIPAddrDel(info->netdev, &addr, prefix_len);
4221     }
4222 
4223     if (rc < 0)
4224         VIR_WARN("Fail to update address %s to %s", addrStr, info->netdev);
4225 }
4226 
4227 
4228 static void
processGuestCrashloadedEvent(virQEMUDriver * driver,virDomainObj * vm)4229 processGuestCrashloadedEvent(virQEMUDriver *driver,
4230                              virDomainObj *vm)
4231 {
4232     virObjectEvent *event = NULL;
4233 
4234     event = virDomainEventLifecycleNewFromObj(vm,
4235                                               VIR_DOMAIN_EVENT_CRASHED,
4236                                               VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED);
4237 
4238     virObjectEventStateQueue(driver->domainEventState, event);
4239 }
4240 
4241 
4242 static void
processMemoryDeviceSizeChange(virQEMUDriver * driver,virDomainObj * vm,qemuMonitorMemoryDeviceSizeChange * info)4243 processMemoryDeviceSizeChange(virQEMUDriver *driver,
4244                               virDomainObj *vm,
4245                               qemuMonitorMemoryDeviceSizeChange *info)
4246 {
4247     virDomainMemoryDef *mem = NULL;
4248     virObjectEvent *event = NULL;
4249     unsigned long long balloon;
4250 
4251     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4252         return;
4253 
4254     if (!virDomainObjIsActive(vm)) {
4255         VIR_DEBUG("Domain is not running");
4256         goto endjob;
4257     }
4258 
4259     mem = virDomainMemoryFindByDeviceAlias(vm->def, info->devAlias);
4260     if (!mem) {
4261         VIR_DEBUG("Memory device '%s' not found", info->devAlias);
4262         goto endjob;
4263     }
4264 
4265     /* If this looks weird it's because it is. The balloon size
4266      * as reported by QEMU does not include any of @currentsize.
4267      * It really contains just the balloon size. But in domain
4268      * definition we want to report also sum of @currentsize. Do
4269      * a bit of math to fix the domain definition. */
4270     balloon = vm->def->mem.cur_balloon - mem->currentsize;
4271     mem->currentsize = VIR_DIV_UP(info->size, 1024);
4272     balloon += mem->currentsize;
4273     vm->def->mem.cur_balloon = balloon;
4274 
4275     event = virDomainEventMemoryDeviceSizeChangeNewFromObj(vm,
4276                                                            info->devAlias,
4277                                                            mem->currentsize);
4278 
4279  endjob:
4280     qemuDomainObjEndJob(driver, vm);
4281     virObjectEventStateQueue(driver->domainEventState, event);
4282 }
4283 
4284 
qemuProcessEventHandler(void * data,void * opaque)4285 static void qemuProcessEventHandler(void *data, void *opaque)
4286 {
4287     struct qemuProcessEvent *processEvent = data;
4288     virDomainObj *vm = processEvent->vm;
4289     virQEMUDriver *driver = opaque;
4290 
4291     VIR_DEBUG("vm=%p, event=%d", vm, processEvent->eventType);
4292 
4293     virObjectLock(vm);
4294 
4295     switch (processEvent->eventType) {
4296     case QEMU_PROCESS_EVENT_WATCHDOG:
4297         processWatchdogEvent(driver, vm, processEvent->action);
4298         break;
4299     case QEMU_PROCESS_EVENT_GUESTPANIC:
4300         processGuestPanicEvent(driver, vm, processEvent->action,
4301                                processEvent->data);
4302         break;
4303     case QEMU_PROCESS_EVENT_DEVICE_DELETED:
4304         processDeviceDeletedEvent(driver, vm, processEvent->data);
4305         break;
4306     case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
4307         processNicRxFilterChangedEvent(driver, vm, processEvent->data);
4308         break;
4309     case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
4310         processSerialChangedEvent(driver, vm, processEvent->data,
4311                                   processEvent->action);
4312         break;
4313     case QEMU_PROCESS_EVENT_BLOCK_JOB:
4314         processBlockJobEvent(driver, vm,
4315                              processEvent->data,
4316                              processEvent->action,
4317                              processEvent->status);
4318         break;
4319     case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
4320         processJobStatusChangeEvent(driver, vm, processEvent->data);
4321         break;
4322     case QEMU_PROCESS_EVENT_MONITOR_EOF:
4323         processMonitorEOFEvent(driver, vm);
4324         break;
4325     case QEMU_PROCESS_EVENT_PR_DISCONNECT:
4326         processPRDisconnectEvent(vm);
4327         break;
4328     case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
4329         processRdmaGidStatusChangedEvent(vm, processEvent->data);
4330         break;
4331     case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
4332         processGuestCrashloadedEvent(driver, vm);
4333         break;
4334     case QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE:
4335         processMemoryDeviceSizeChange(driver, vm, processEvent->data);
4336         break;
4337     case QEMU_PROCESS_EVENT_LAST:
4338         break;
4339     }
4340 
4341     virDomainObjEndAPI(&vm);
4342     qemuProcessEventFree(processEvent);
4343 }
4344 
4345 
4346 static int
qemuDomainSetVcpusAgent(virDomainObj * vm,unsigned int nvcpus)4347 qemuDomainSetVcpusAgent(virDomainObj *vm,
4348                         unsigned int nvcpus)
4349 {
4350     qemuAgentCPUInfo *cpuinfo = NULL;
4351     qemuAgent *agent;
4352     int ncpuinfo;
4353     int ret = -1;
4354 
4355     if (!qemuDomainAgentAvailable(vm, true))
4356         goto cleanup;
4357 
4358     if (nvcpus > virDomainDefGetVcpus(vm->def)) {
4359         virReportError(VIR_ERR_INVALID_ARG,
4360                        _("requested vcpu count is greater than the count "
4361                          "of enabled vcpus in the domain: %d > %d"),
4362                        nvcpus, virDomainDefGetVcpus(vm->def));
4363         goto cleanup;
4364     }
4365 
4366     agent = qemuDomainObjEnterAgent(vm);
4367     ncpuinfo = qemuAgentGetVCPUs(agent, &cpuinfo);
4368     qemuDomainObjExitAgent(vm, agent);
4369     agent = NULL;
4370 
4371     if (ncpuinfo < 0)
4372         goto cleanup;
4373 
4374     if (qemuAgentUpdateCPUInfo(nvcpus, cpuinfo, ncpuinfo) < 0)
4375         goto cleanup;
4376 
4377     if (!qemuDomainAgentAvailable(vm, true))
4378         goto cleanup;
4379 
4380     agent = qemuDomainObjEnterAgent(vm);
4381     ret = qemuAgentSetVCPUs(agent, cpuinfo, ncpuinfo);
4382     qemuDomainObjExitAgent(vm, agent);
4383 
4384  cleanup:
4385     VIR_FREE(cpuinfo);
4386 
4387     return ret;
4388 }
4389 
4390 
4391 static int
qemuDomainSetVcpusMax(virQEMUDriver * driver,virDomainObj * vm,virDomainDef * def,virDomainDef * persistentDef,unsigned int nvcpus)4392 qemuDomainSetVcpusMax(virQEMUDriver *driver,
4393                       virDomainObj *vm,
4394                       virDomainDef *def,
4395                       virDomainDef *persistentDef,
4396                       unsigned int nvcpus)
4397 {
4398     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
4399     qemuDomainObjPrivate *priv = vm->privateData;
4400     unsigned int topologycpus;
4401 
4402     if (def) {
4403         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4404                        _("maximum vcpu count of a live domain can't be modified"));
4405         return -1;
4406     }
4407 
4408     if (virDomainNumaGetCPUCountTotal(persistentDef->numa) > nvcpus) {
4409         virReportError(VIR_ERR_INVALID_ARG, "%s",
4410                        _("Number of CPUs in <numa> exceeds the desired "
4411                          "maximum vcpu count"));
4412         return -1;
4413     }
4414 
4415     if (virDomainDefGetVcpusTopology(persistentDef, &topologycpus) == 0 &&
4416         nvcpus != topologycpus) {
4417         /* allow setting a valid vcpu count for the topology so an invalid
4418          * setting may be corrected via this API */
4419         virReportError(VIR_ERR_INVALID_ARG, "%s",
4420                        _("CPU topology doesn't match the desired vcpu count"));
4421         return -1;
4422     }
4423 
4424     /* ordering information may become invalid, thus clear it */
4425     virDomainDefVcpuOrderClear(persistentDef);
4426 
4427     if (virDomainDefSetVcpusMax(persistentDef, nvcpus, driver->xmlopt) < 0)
4428         return -1;
4429 
4430     if (qemuDomainDefNumaCPUsRectify(persistentDef, priv->qemuCaps) < 0)
4431         return -1;
4432 
4433     if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
4434         return -1;
4435 
4436     return 0;
4437 }
4438 
4439 
4440 static int
qemuDomainSetVcpusFlags(virDomainPtr dom,unsigned int nvcpus,unsigned int flags)4441 qemuDomainSetVcpusFlags(virDomainPtr dom,
4442                         unsigned int nvcpus,
4443                         unsigned int flags)
4444 {
4445     virQEMUDriver *driver = dom->conn->privateData;
4446     virDomainObj *vm = NULL;
4447     virDomainDef *def;
4448     virDomainDef *persistentDef;
4449     bool hotpluggable = !!(flags & VIR_DOMAIN_VCPU_HOTPLUGGABLE);
4450     bool useAgent = !!(flags & VIR_DOMAIN_VCPU_GUEST);
4451     int ret = -1;
4452 
4453     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
4454                   VIR_DOMAIN_AFFECT_CONFIG |
4455                   VIR_DOMAIN_VCPU_MAXIMUM |
4456                   VIR_DOMAIN_VCPU_GUEST |
4457                   VIR_DOMAIN_VCPU_HOTPLUGGABLE, -1);
4458 
4459     if (!(vm = qemuDomainObjFromDomain(dom)))
4460         goto cleanup;
4461 
4462     if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
4463         goto cleanup;
4464 
4465 
4466     if (useAgent) {
4467         if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
4468             goto cleanup;
4469     } else {
4470         if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4471             goto cleanup;
4472     }
4473 
4474     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
4475         goto endjob;
4476 
4477     if (useAgent)
4478         ret = qemuDomainSetVcpusAgent(vm, nvcpus);
4479     else if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
4480         ret = qemuDomainSetVcpusMax(driver, vm, def, persistentDef, nvcpus);
4481     else
4482         ret = qemuDomainSetVcpusInternal(driver, vm, def, persistentDef,
4483                                          nvcpus, hotpluggable);
4484 
4485  endjob:
4486     if (useAgent)
4487         qemuDomainObjEndAgentJob(vm);
4488     else
4489         qemuDomainObjEndJob(driver, vm);
4490 
4491  cleanup:
4492     virDomainObjEndAPI(&vm);
4493     return ret;
4494 }
4495 
4496 
4497 static int
qemuDomainSetVcpus(virDomainPtr dom,unsigned int nvcpus)4498 qemuDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
4499 {
4500     return qemuDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
4501 }
4502 
4503 
4504 static int
qemuDomainPinVcpuLive(virDomainObj * vm,virDomainDef * def,int vcpu,virQEMUDriver * driver,virBitmap * cpumap)4505 qemuDomainPinVcpuLive(virDomainObj *vm,
4506                       virDomainDef *def,
4507                       int vcpu,
4508                       virQEMUDriver *driver,
4509                       virBitmap *cpumap)
4510 {
4511     virBitmap *tmpmap = NULL;
4512     virDomainVcpuDef *vcpuinfo;
4513     qemuDomainObjPrivate *priv = vm->privateData;
4514     g_autoptr(virCgroup) cgroup_vcpu = NULL;
4515     g_autofree char *str = NULL;
4516     virObjectEvent *event = NULL;
4517     char paramField[VIR_TYPED_PARAM_FIELD_LENGTH] = "";
4518     virTypedParameterPtr eventParams = NULL;
4519     int eventNparams = 0;
4520     int eventMaxparams = 0;
4521     int ret = -1;
4522 
4523     if (!qemuDomainHasVcpuPids(vm)) {
4524         virReportError(VIR_ERR_OPERATION_INVALID,
4525                        "%s", _("cpu affinity is not supported"));
4526         goto cleanup;
4527     }
4528 
4529     if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
4530         virReportError(VIR_ERR_INVALID_ARG,
4531                        _("vcpu %d is out of range of live cpu count %d"),
4532                        vcpu, virDomainDefGetVcpusMax(def));
4533         goto cleanup;
4534     }
4535 
4536     tmpmap = virBitmapNewCopy(cpumap);
4537 
4538     if (!(str = virBitmapFormat(cpumap)))
4539         goto cleanup;
4540 
4541     if (vcpuinfo->online) {
4542         /* Configure the corresponding cpuset cgroup before set affinity. */
4543         if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
4544             if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
4545                                    false, &cgroup_vcpu) < 0)
4546                 goto cleanup;
4547             if (qemuSetupCgroupCpusetCpus(cgroup_vcpu, cpumap) < 0)
4548                 goto cleanup;
4549         }
4550 
4551         if (virProcessSetAffinity(qemuDomainGetVcpuPid(vm, vcpu),
4552                                   cpumap, false) < 0)
4553             goto cleanup;
4554     }
4555 
4556     virBitmapFree(vcpuinfo->cpumask);
4557     vcpuinfo->cpumask = tmpmap;
4558     tmpmap = NULL;
4559 
4560     qemuDomainSaveStatus(vm);
4561 
4562     if (g_snprintf(paramField, VIR_TYPED_PARAM_FIELD_LENGTH,
4563                    VIR_DOMAIN_TUNABLE_CPU_VCPUPIN, vcpu) < 0) {
4564         goto cleanup;
4565     }
4566 
4567     if (virTypedParamsAddString(&eventParams, &eventNparams,
4568                                 &eventMaxparams, paramField, str) < 0)
4569         goto cleanup;
4570 
4571     event = virDomainEventTunableNewFromObj(vm, eventParams, eventNparams);
4572 
4573     ret = 0;
4574 
4575  cleanup:
4576     virBitmapFree(tmpmap);
4577     virObjectEventStateQueue(driver->domainEventState, event);
4578     return ret;
4579 }
4580 
4581 
4582 static int
qemuDomainPinVcpuFlags(virDomainPtr dom,unsigned int vcpu,unsigned char * cpumap,int maplen,unsigned int flags)4583 qemuDomainPinVcpuFlags(virDomainPtr dom,
4584                        unsigned int vcpu,
4585                        unsigned char *cpumap,
4586                        int maplen,
4587                        unsigned int flags)
4588 {
4589     virQEMUDriver *driver = dom->conn->privateData;
4590     virDomainObj *vm;
4591     virDomainDef *def;
4592     virDomainDef *persistentDef;
4593     int ret = -1;
4594     virBitmap *pcpumap = NULL;
4595     virDomainVcpuDef *vcpuinfo = NULL;
4596     g_autoptr(virQEMUDriverConfig) cfg = NULL;
4597 
4598     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
4599                   VIR_DOMAIN_AFFECT_CONFIG, -1);
4600 
4601     cfg = virQEMUDriverGetConfig(driver);
4602 
4603     if (!(vm = qemuDomainObjFromDomain(dom)))
4604         goto cleanup;
4605 
4606     if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
4607         goto cleanup;
4608 
4609     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4610         goto cleanup;
4611 
4612     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
4613         goto endjob;
4614 
4615     if (persistentDef &&
4616         !(vcpuinfo = virDomainDefGetVcpu(persistentDef, vcpu))) {
4617         virReportError(VIR_ERR_INVALID_ARG,
4618                        _("vcpu %d is out of range of persistent cpu count %d"),
4619                        vcpu, virDomainDefGetVcpus(persistentDef));
4620         goto endjob;
4621     }
4622 
4623     if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
4624         goto endjob;
4625 
4626     if (virBitmapIsAllClear(pcpumap)) {
4627         virReportError(VIR_ERR_INVALID_ARG, "%s",
4628                        _("Empty cpu list for pinning"));
4629         goto endjob;
4630     }
4631 
4632     if (def &&
4633         qemuDomainPinVcpuLive(vm, def, vcpu, driver, pcpumap) < 0)
4634         goto endjob;
4635 
4636     if (persistentDef) {
4637         virBitmapFree(vcpuinfo->cpumask);
4638         vcpuinfo->cpumask = pcpumap;
4639         pcpumap = NULL;
4640 
4641         ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);
4642         goto endjob;
4643     }
4644 
4645     ret = 0;
4646 
4647  endjob:
4648     qemuDomainObjEndJob(driver, vm);
4649 
4650  cleanup:
4651     virDomainObjEndAPI(&vm);
4652     virBitmapFree(pcpumap);
4653     return ret;
4654 }
4655 
4656 static int
qemuDomainPinVcpu(virDomainPtr dom,unsigned int vcpu,unsigned char * cpumap,int maplen)4657 qemuDomainPinVcpu(virDomainPtr dom,
4658                    unsigned int vcpu,
4659                    unsigned char *cpumap,
4660                    int maplen)
4661 {
4662     return qemuDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
4663                                   VIR_DOMAIN_AFFECT_LIVE);
4664 }
4665 
4666 static int
qemuDomainGetVcpuPinInfo(virDomainPtr dom,int ncpumaps,unsigned char * cpumaps,int maplen,unsigned int flags)4667 qemuDomainGetVcpuPinInfo(virDomainPtr dom,
4668                          int ncpumaps,
4669                          unsigned char *cpumaps,
4670                          int maplen,
4671                          unsigned int flags)
4672 {
4673     virDomainObj *vm = NULL;
4674     virDomainDef *def;
4675     bool live;
4676     int ret = -1;
4677     g_autoptr(virBitmap) hostcpus = NULL;
4678     virBitmap *autoCpuset = NULL;
4679 
4680     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
4681                   VIR_DOMAIN_AFFECT_CONFIG, -1);
4682 
4683     if (!(vm = qemuDomainObjFromDomain(dom)))
4684         goto cleanup;
4685 
4686     if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
4687         goto cleanup;
4688 
4689     if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
4690         goto cleanup;
4691 
4692     if (!(hostcpus = virHostCPUGetAvailableCPUsBitmap()))
4693         goto cleanup;
4694 
4695     if (live)
4696         autoCpuset = QEMU_DOMAIN_PRIVATE(vm)->autoCpuset;
4697 
4698     ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
4699                                            hostcpus, autoCpuset);
4700  cleanup:
4701     virDomainObjEndAPI(&vm);
4702     return ret;
4703 }
4704 
4705 static int
qemuDomainPinEmulator(virDomainPtr dom,unsigned char * cpumap,int maplen,unsigned int flags)4706 qemuDomainPinEmulator(virDomainPtr dom,
4707                       unsigned char *cpumap,
4708                       int maplen,
4709                       unsigned int flags)
4710 {
4711     virQEMUDriver *driver = dom->conn->privateData;
4712     virDomainObj *vm;
4713     g_autoptr(virCgroup) cgroup_emulator = NULL;
4714     virDomainDef *def;
4715     virDomainDef *persistentDef;
4716     int ret = -1;
4717     qemuDomainObjPrivate *priv;
4718     virBitmap *pcpumap = NULL;
4719     g_autoptr(virQEMUDriverConfig) cfg = NULL;
4720     virObjectEvent *event = NULL;
4721     g_autofree char *str = NULL;
4722     virTypedParameterPtr eventParams = NULL;
4723     int eventNparams = 0;
4724     int eventMaxparams = 0;
4725 
4726     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
4727                   VIR_DOMAIN_AFFECT_CONFIG, -1);
4728 
4729     cfg = virQEMUDriverGetConfig(driver);
4730 
4731     if (!(vm = qemuDomainObjFromDomain(dom)))
4732         goto cleanup;
4733 
4734     if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
4735         goto cleanup;
4736 
4737     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4738         goto cleanup;
4739 
4740     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
4741         goto endjob;
4742 
4743     priv = vm->privateData;
4744 
4745     if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
4746         goto endjob;
4747 
4748     if (virBitmapIsAllClear(pcpumap)) {
4749         virReportError(VIR_ERR_INVALID_ARG, "%s",
4750                        _("Empty cpu list for pinning"));
4751         goto endjob;
4752     }
4753 
4754     if (def) {
4755         if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
4756             if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
4757                                    0, false, &cgroup_emulator) < 0)
4758                 goto endjob;
4759 
4760             if (qemuSetupCgroupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
4761                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4762                                _("failed to set cpuset.cpus in cgroup"
4763                                  " for emulator threads"));
4764                 goto endjob;
4765             }
4766         }
4767 
4768         if (virProcessSetAffinity(vm->pid, pcpumap, false) < 0)
4769             goto endjob;
4770 
4771         virBitmapFree(def->cputune.emulatorpin);
4772         def->cputune.emulatorpin = virBitmapNewCopy(pcpumap);
4773 
4774         qemuDomainSaveStatus(vm);
4775 
4776         str = virBitmapFormat(pcpumap);
4777         if (virTypedParamsAddString(&eventParams, &eventNparams,
4778                                     &eventMaxparams,
4779                                     VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
4780                                     str) < 0)
4781             goto endjob;
4782 
4783         event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
4784     }
4785 
4786     if (persistentDef) {
4787         virBitmapFree(persistentDef->cputune.emulatorpin);
4788         persistentDef->cputune.emulatorpin = virBitmapNewCopy(pcpumap);
4789 
4790         ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);
4791         goto endjob;
4792     }
4793 
4794     ret = 0;
4795 
4796  endjob:
4797     qemuDomainObjEndJob(driver, vm);
4798 
4799  cleanup:
4800     virObjectEventStateQueue(driver->domainEventState, event);
4801     virBitmapFree(pcpumap);
4802     virDomainObjEndAPI(&vm);
4803     return ret;
4804 }
4805 
4806 static int
qemuDomainGetEmulatorPinInfo(virDomainPtr dom,unsigned char * cpumaps,int maplen,unsigned int flags)4807 qemuDomainGetEmulatorPinInfo(virDomainPtr dom,
4808                              unsigned char *cpumaps,
4809                              int maplen,
4810                              unsigned int flags)
4811 {
4812     virDomainObj *vm = NULL;
4813     virDomainDef *def;
4814     bool live;
4815     int ret = -1;
4816     virBitmap *cpumask = NULL;
4817     g_autoptr(virBitmap) bitmap = NULL;
4818     virBitmap *autoCpuset = NULL;
4819 
4820     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
4821                   VIR_DOMAIN_AFFECT_CONFIG, -1);
4822 
4823     if (!(vm = qemuDomainObjFromDomain(dom)))
4824         goto cleanup;
4825 
4826     if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
4827         goto cleanup;
4828 
4829     if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
4830         goto cleanup;
4831 
4832     if (live)
4833         autoCpuset = QEMU_DOMAIN_PRIVATE(vm)->autoCpuset;
4834 
4835     if (def->cputune.emulatorpin) {
4836         cpumask = def->cputune.emulatorpin;
4837     } else if (def->cpumask) {
4838         cpumask = def->cpumask;
4839     } else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
4840                autoCpuset) {
4841         cpumask = autoCpuset;
4842     } else {
4843         if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
4844             goto cleanup;
4845         cpumask = bitmap;
4846     }
4847 
4848     virBitmapToDataBuf(cpumask, cpumaps, maplen);
4849 
4850     ret = 1;
4851 
4852  cleanup:
4853     virDomainObjEndAPI(&vm);
4854     return ret;
4855 }
4856 
4857 static int
qemuDomainGetVcpus(virDomainPtr dom,virVcpuInfoPtr info,int maxinfo,unsigned char * cpumaps,int maplen)4858 qemuDomainGetVcpus(virDomainPtr dom,
4859                    virVcpuInfoPtr info,
4860                    int maxinfo,
4861                    unsigned char *cpumaps,
4862                    int maplen)
4863 {
4864     virDomainObj *vm;
4865     int ret = -1;
4866 
4867     if (!(vm = qemuDomainObjFromDomain(dom)))
4868         goto cleanup;
4869 
4870     if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
4871         goto cleanup;
4872 
4873     if (!virDomainObjIsActive(vm)) {
4874         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4875                        _("cannot retrieve vcpu information for inactive domain"));
4876         goto cleanup;
4877     }
4878 
4879     ret = qemuDomainHelperGetVcpus(vm, info, NULL, NULL, maxinfo, cpumaps, maplen);
4880 
4881  cleanup:
4882     virDomainObjEndAPI(&vm);
4883     return ret;
4884 }
4885 
4886 
4887 static int
qemuDomainGetVcpusFlags(virDomainPtr dom,unsigned int flags)4888 qemuDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
4889 {
4890     virQEMUDriver *driver = dom->conn->privateData;
4891     virDomainObj *vm;
4892     virDomainDef *def;
4893     int ret = -1;
4894     qemuAgentCPUInfo *cpuinfo = NULL;
4895     qemuAgent *agent;
4896     int ncpuinfo = -1;
4897     size_t i;
4898 
4899     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
4900                   VIR_DOMAIN_AFFECT_CONFIG |
4901                   VIR_DOMAIN_VCPU_MAXIMUM |
4902                   VIR_DOMAIN_VCPU_GUEST, -1);
4903 
4904     if (!(vm = qemuDomainObjFromDomain(dom)))
4905         return -1;
4906 
4907     if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
4908         goto cleanup;
4909 
4910     if (!(def = virDomainObjGetOneDef(vm, flags)))
4911         goto cleanup;
4912 
4913     if (flags & VIR_DOMAIN_VCPU_GUEST) {
4914         if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
4915             goto cleanup;
4916 
4917         if (!virDomainObjIsActive(vm)) {
4918             virReportError(VIR_ERR_INVALID_ARG, "%s",
4919                            _("vCPU count provided by the guest agent can only be "
4920                              "requested for live domains"));
4921             goto endjob;
4922         }
4923 
4924         if (!qemuDomainAgentAvailable(vm, true))
4925             goto endjob;
4926 
4927         agent = qemuDomainObjEnterAgent(vm);
4928         ncpuinfo = qemuAgentGetVCPUs(agent, &cpuinfo);
4929         qemuDomainObjExitAgent(vm, agent);
4930 
4931  endjob:
4932         qemuDomainObjEndAgentJob(vm);
4933 
4934         if (ncpuinfo < 0)
4935             goto cleanup;
4936 
4937         if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
4938             ret = ncpuinfo;
4939             goto cleanup;
4940         }
4941 
4942         /* count the online vcpus */
4943         ret = 0;
4944         for (i = 0; i < ncpuinfo; i++) {
4945             if (cpuinfo[i].online)
4946                 ret++;
4947         }
4948     } else {
4949         if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
4950             ret = virDomainDefGetVcpusMax(def);
4951         else
4952             ret = virDomainDefGetVcpus(def);
4953     }
4954 
4955 
4956  cleanup:
4957     virDomainObjEndAPI(&vm);
4958     VIR_FREE(cpuinfo);
4959     return ret;
4960 }
4961 
4962 static int
qemuDomainGetMaxVcpus(virDomainPtr dom)4963 qemuDomainGetMaxVcpus(virDomainPtr dom)
4964 {
4965     return qemuDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
4966                                          VIR_DOMAIN_VCPU_MAXIMUM));
4967 }
4968 
4969 
4970 static int
qemuDomainGetIOThreadsMon(virQEMUDriver * driver,virDomainObj * vm,qemuMonitorIOThreadInfo *** iothreads,int * niothreads)4971 qemuDomainGetIOThreadsMon(virQEMUDriver *driver,
4972                           virDomainObj *vm,
4973                           qemuMonitorIOThreadInfo ***iothreads,
4974                           int *niothreads)
4975 {
4976     qemuDomainObjPrivate *priv = vm->privateData;
4977     int ret = -1;
4978 
4979     qemuDomainObjEnterMonitor(driver, vm);
4980     ret = qemuMonitorGetIOThreads(priv->mon, iothreads, niothreads);
4981     if (qemuDomainObjExitMonitor(driver, vm) < 0)
4982         return -1;
4983 
4984     return ret;
4985 }
4986 
4987 
4988 static int
qemuDomainGetIOThreadsLive(virQEMUDriver * driver,virDomainObj * vm,virDomainIOThreadInfoPtr ** info)4989 qemuDomainGetIOThreadsLive(virQEMUDriver *driver,
4990                            virDomainObj *vm,
4991                            virDomainIOThreadInfoPtr **info)
4992 {
4993     qemuDomainObjPrivate *priv;
4994     qemuMonitorIOThreadInfo **iothreads = NULL;
4995     virDomainIOThreadInfoPtr *info_ret = NULL;
4996     int niothreads = 0;
4997     size_t i;
4998     int ret = -1;
4999 
5000     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
5001         goto cleanup;
5002 
5003     if (!virDomainObjIsActive(vm)) {
5004         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5005                        _("cannot list IOThreads for an inactive domain"));
5006         goto endjob;
5007     }
5008 
5009     priv = vm->privateData;
5010     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
5011         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5012                        _("IOThreads not supported with this binary"));
5013         goto endjob;
5014     }
5015 
5016     if ((ret = qemuDomainGetIOThreadsMon(driver, vm, &iothreads, &niothreads)) < 0)
5017         goto endjob;
5018 
5019     /* Nothing to do */
5020     if (niothreads == 0) {
5021         ret = 0;
5022         goto endjob;
5023     }
5024 
5025     info_ret = g_new0(virDomainIOThreadInfoPtr, niothreads);
5026 
5027     for (i = 0; i < niothreads; i++) {
5028         virBitmap *map = NULL;
5029 
5030         info_ret[i] = g_new0(virDomainIOThreadInfo, 1);
5031         info_ret[i]->iothread_id = iothreads[i]->iothread_id;
5032 
5033         if (!(map = virProcessGetAffinity(iothreads[i]->thread_id)))
5034             goto endjob;
5035 
5036         if (virBitmapToData(map, &info_ret[i]->cpumap,
5037                             &info_ret[i]->cpumaplen) < 0) {
5038             virBitmapFree(map);
5039             goto endjob;
5040         }
5041         virBitmapFree(map);
5042     }
5043 
5044     *info = g_steal_pointer(&info_ret);
5045     ret = niothreads;
5046 
5047  endjob:
5048     qemuDomainObjEndJob(driver, vm);
5049 
5050  cleanup:
5051     if (info_ret) {
5052         for (i = 0; i < niothreads; i++)
5053             virDomainIOThreadInfoFree(info_ret[i]);
5054         VIR_FREE(info_ret);
5055     }
5056     if (iothreads) {
5057         for (i = 0; i < niothreads; i++)
5058             VIR_FREE(iothreads[i]);
5059         VIR_FREE(iothreads);
5060     }
5061 
5062     return ret;
5063 }
5064 
5065 
5066 static int
qemuDomainGetIOThreadInfo(virDomainPtr dom,virDomainIOThreadInfoPtr ** info,unsigned int flags)5067 qemuDomainGetIOThreadInfo(virDomainPtr dom,
5068                           virDomainIOThreadInfoPtr **info,
5069                           unsigned int flags)
5070 {
5071     virQEMUDriver *driver = dom->conn->privateData;
5072     virDomainObj *vm;
5073     virDomainDef *targetDef = NULL;
5074     int ret = -1;
5075 
5076     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5077                   VIR_DOMAIN_AFFECT_CONFIG, -1);
5078 
5079     if (!(vm = qemuDomainObjFromDomain(dom)))
5080         goto cleanup;
5081 
5082     if (virDomainGetIOThreadInfoEnsureACL(dom->conn, vm->def) < 0)
5083         goto cleanup;
5084 
5085     if (virDomainObjGetDefs(vm, flags, NULL, &targetDef) < 0)
5086         goto cleanup;
5087 
5088     if (!targetDef)
5089         ret = qemuDomainGetIOThreadsLive(driver, vm, info);
5090     else
5091         ret = virDomainDriverGetIOThreadsConfig(targetDef, info, 0);
5092 
5093  cleanup:
5094     virDomainObjEndAPI(&vm);
5095     return ret;
5096 }
5097 
5098 static int
qemuDomainPinIOThread(virDomainPtr dom,unsigned int iothread_id,unsigned char * cpumap,int maplen,unsigned int flags)5099 qemuDomainPinIOThread(virDomainPtr dom,
5100                       unsigned int iothread_id,
5101                       unsigned char *cpumap,
5102                       int maplen,
5103                       unsigned int flags)
5104 {
5105     int ret = -1;
5106     virQEMUDriver *driver = dom->conn->privateData;
5107     g_autoptr(virQEMUDriverConfig) cfg = NULL;
5108     virDomainObj *vm;
5109     virDomainDef *def;
5110     virDomainDef *persistentDef;
5111     virBitmap *pcpumap = NULL;
5112     qemuDomainObjPrivate *priv;
5113     g_autoptr(virCgroup) cgroup_iothread = NULL;
5114     virObjectEvent *event = NULL;
5115     char paramField[VIR_TYPED_PARAM_FIELD_LENGTH] = "";
5116     g_autofree char *str = NULL;
5117     virTypedParameterPtr eventParams = NULL;
5118     int eventNparams = 0;
5119     int eventMaxparams = 0;
5120 
5121     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5122                   VIR_DOMAIN_AFFECT_CONFIG, -1);
5123 
5124     cfg = virQEMUDriverGetConfig(driver);
5125 
5126     if (!(vm = qemuDomainObjFromDomain(dom)))
5127         goto cleanup;
5128     priv = vm->privateData;
5129 
5130     if (virDomainPinIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
5131         goto cleanup;
5132 
5133     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5134         goto cleanup;
5135 
5136     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5137         goto endjob;
5138 
5139     if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5140         goto endjob;
5141 
5142     if (virBitmapIsAllClear(pcpumap)) {
5143         virReportError(VIR_ERR_INVALID_ARG, "%s",
5144                        _("Empty iothread cpumap list for pinning"));
5145         goto endjob;
5146     }
5147 
5148     if (def) {
5149         virDomainIOThreadIDDef *iothrid;
5150         virBitmap *cpumask;
5151 
5152         if (!(iothrid = virDomainIOThreadIDFind(def, iothread_id))) {
5153             virReportError(VIR_ERR_INVALID_ARG,
5154                            _("iothread %d not found"), iothread_id);
5155             goto endjob;
5156         }
5157 
5158         if (!(cpumask = virBitmapNewData(cpumap, maplen)))
5159             goto endjob;
5160 
5161         virBitmapFree(iothrid->cpumask);
5162         iothrid->cpumask = cpumask;
5163         iothrid->autofill = false;
5164 
5165         /* Configure the corresponding cpuset cgroup before set affinity. */
5166         if (virCgroupHasController(priv->cgroup,
5167                                    VIR_CGROUP_CONTROLLER_CPUSET)) {
5168             if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
5169                                    iothread_id, false, &cgroup_iothread) < 0)
5170                 goto endjob;
5171             if (qemuSetupCgroupCpusetCpus(cgroup_iothread, pcpumap) < 0) {
5172                 virReportError(VIR_ERR_OPERATION_INVALID,
5173                                _("failed to set cpuset.cpus in cgroup"
5174                                  " for iothread %d"), iothread_id);
5175                 goto endjob;
5176             }
5177         }
5178 
5179         if (virProcessSetAffinity(iothrid->thread_id, pcpumap, false) < 0)
5180             goto endjob;
5181 
5182         qemuDomainSaveStatus(vm);
5183 
5184         if (g_snprintf(paramField, VIR_TYPED_PARAM_FIELD_LENGTH,
5185                        VIR_DOMAIN_TUNABLE_CPU_IOTHREADSPIN, iothread_id) < 0) {
5186             goto endjob;
5187         }
5188 
5189         str = virBitmapFormat(pcpumap);
5190         if (virTypedParamsAddString(&eventParams, &eventNparams,
5191                                     &eventMaxparams, paramField, str) < 0)
5192             goto endjob;
5193 
5194         event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
5195     }
5196 
5197     if (persistentDef) {
5198         virDomainIOThreadIDDef *iothrid;
5199         virBitmap *cpumask;
5200 
5201         if (!(iothrid = virDomainIOThreadIDFind(persistentDef, iothread_id))) {
5202             virReportError(VIR_ERR_INVALID_ARG,
5203                            _("iothreadid %d not found"), iothread_id);
5204             goto endjob;
5205         }
5206 
5207         if (!(cpumask = virBitmapNewData(cpumap, maplen)))
5208             goto endjob;
5209 
5210         virBitmapFree(iothrid->cpumask);
5211         iothrid->cpumask = cpumask;
5212         iothrid->autofill = false;
5213 
5214         ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);
5215         goto endjob;
5216     }
5217 
5218     ret = 0;
5219 
5220  endjob:
5221     qemuDomainObjEndJob(driver, vm);
5222 
5223  cleanup:
5224     virObjectEventStateQueue(driver->domainEventState, event);
5225     virBitmapFree(pcpumap);
5226     virDomainObjEndAPI(&vm);
5227     return ret;
5228 }
5229 
5230 static int
qemuDomainHotplugAddIOThread(virQEMUDriver * driver,virDomainObj * vm,unsigned int iothread_id)5231 qemuDomainHotplugAddIOThread(virQEMUDriver *driver,
5232                              virDomainObj *vm,
5233                              unsigned int iothread_id)
5234 {
5235     qemuDomainObjPrivate *priv = vm->privateData;
5236     g_autofree char *alias = NULL;
5237     size_t idx;
5238     int ret = -1;
5239     unsigned int orig_niothreads = vm->def->niothreadids;
5240     unsigned int exp_niothreads = vm->def->niothreadids;
5241     int new_niothreads = 0;
5242     qemuMonitorIOThreadInfo **new_iothreads = NULL;
5243     virDomainIOThreadIDDef *iothrid;
5244     virJSONValue *props = NULL;
5245     bool threadAdded = false;
5246     bool objectAdded = false;
5247 
5248     alias = g_strdup_printf("iothread%u", iothread_id);
5249 
5250     if (qemuMonitorCreateObjectProps(&props, "iothread", alias, NULL) < 0)
5251         goto cleanup;
5252 
5253     qemuDomainObjEnterMonitor(driver, vm);
5254 
5255     if (qemuMonitorAddObject(priv->mon, &props, NULL) < 0)
5256         goto exit_monitor;
5257 
5258     objectAdded = true;
5259 
5260     exp_niothreads++;
5261 
5262     /* After hotplugging the IOThreads we need to re-detect the
5263      * IOThreads thread_id's, adjust the cgroups, thread affinity,
5264      * and add the thread_id to the vm->def->iothreadids list.
5265      */
5266     if (qemuMonitorGetIOThreads(priv->mon, &new_iothreads, &new_niothreads) < 0)
5267         goto exit_monitor;
5268 
5269     if (qemuDomainObjExitMonitor(driver, vm) < 0)
5270         goto cleanup;
5271 
5272     if (new_niothreads != exp_niothreads) {
5273         virReportError(VIR_ERR_INTERNAL_ERROR,
5274                        _("got wrong number of IOThread ids from QEMU monitor. "
5275                          "got %d, wanted %d"),
5276                        new_niothreads, exp_niothreads);
5277         goto cleanup;
5278     }
5279 
5280     /*
5281      * If we've successfully added an IOThread, find out where we added it
5282      * in the QEMU IOThread list, so we can add it to our iothreadids list
5283      */
5284     for (idx = 0; idx < new_niothreads; idx++) {
5285         if (new_iothreads[idx]->iothread_id == iothread_id)
5286             break;
5287     }
5288 
5289     if (idx == new_niothreads) {
5290         virReportError(VIR_ERR_INTERNAL_ERROR,
5291                        _("cannot find new IOThread '%u' in QEMU monitor."),
5292                        iothread_id);
5293         goto cleanup;
5294     }
5295 
5296     if (!(iothrid = virDomainIOThreadIDAdd(vm->def, iothread_id)))
5297         goto cleanup;
5298 
5299     threadAdded = true;
5300     iothrid->thread_id = new_iothreads[idx]->thread_id;
5301 
5302     if (qemuProcessSetupIOThread(vm, iothrid) < 0)
5303         goto cleanup;
5304 
5305     ret = 0;
5306 
5307  cleanup:
5308     if (ret < 0) {
5309         if (threadAdded)
5310             virDomainIOThreadIDDel(vm->def, iothread_id);
5311 
5312         if (objectAdded) {
5313             qemuDomainObjEnterMonitor(driver, vm);
5314             if (qemuMonitorDelObject(priv->mon, alias, true) < 0)
5315                 VIR_WARN("deletion of iothread object %d of domain %s failed when cleanup",
5316                          iothread_id, vm->def->name);
5317             ignore_value(qemuDomainObjExitMonitor(driver, vm));
5318         }
5319     }
5320 
5321     if (new_iothreads) {
5322         for (idx = 0; idx < new_niothreads; idx++)
5323             VIR_FREE(new_iothreads[idx]);
5324         VIR_FREE(new_iothreads);
5325     }
5326     virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
5327                            "update", ret == 0);
5328     virJSONValueFree(props);
5329     return ret;
5330 
5331  exit_monitor:
5332     ignore_value(qemuDomainObjExitMonitor(driver, vm));
5333     goto cleanup;
5334 }
5335 
5336 
5337 static int
qemuDomainHotplugModIOThread(virQEMUDriver * driver,virDomainObj * vm,qemuMonitorIOThreadInfo iothread)5338 qemuDomainHotplugModIOThread(virQEMUDriver *driver,
5339                              virDomainObj *vm,
5340                              qemuMonitorIOThreadInfo iothread)
5341 {
5342     qemuDomainObjPrivate *priv = vm->privateData;
5343     int rc;
5344 
5345     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLLING)) {
5346         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5347                        _("IOThreads polling is not supported for this QEMU"));
5348         return -1;
5349     }
5350 
5351     qemuDomainObjEnterMonitor(driver, vm);
5352 
5353     rc = qemuMonitorSetIOThread(priv->mon, &iothread);
5354 
5355     if (qemuDomainObjExitMonitor(driver, vm) < 0)
5356         return -1;
5357 
5358     if (rc < 0)
5359         return -1;
5360 
5361     return 0;
5362 }
5363 
5364 
5365 static int
qemuDomainHotplugDelIOThread(virQEMUDriver * driver,virDomainObj * vm,unsigned int iothread_id)5366 qemuDomainHotplugDelIOThread(virQEMUDriver *driver,
5367                              virDomainObj *vm,
5368                              unsigned int iothread_id)
5369 {
5370     qemuDomainObjPrivate *priv = vm->privateData;
5371     size_t idx;
5372     g_autofree char *alias = NULL;
5373     int rc = -1;
5374     int ret = -1;
5375     unsigned int orig_niothreads = vm->def->niothreadids;
5376     unsigned int exp_niothreads = vm->def->niothreadids;
5377     int new_niothreads = 0;
5378     qemuMonitorIOThreadInfo **new_iothreads = NULL;
5379 
5380     alias = g_strdup_printf("iothread%u", iothread_id);
5381 
5382     qemuDomainObjEnterMonitor(driver, vm);
5383 
5384     rc = qemuMonitorDelObject(priv->mon, alias, true);
5385     exp_niothreads--;
5386     if (rc < 0)
5387         goto exit_monitor;
5388 
5389     if (qemuMonitorGetIOThreads(priv->mon, &new_iothreads, &new_niothreads) < 0)
5390         goto exit_monitor;
5391 
5392     if (qemuDomainObjExitMonitor(driver, vm) < 0)
5393         goto cleanup;
5394 
5395     if (new_niothreads != exp_niothreads) {
5396         virReportError(VIR_ERR_INTERNAL_ERROR,
5397                        _("got wrong number of IOThread ids from QEMU monitor. "
5398                          "got %d, wanted %d"),
5399                        new_niothreads, exp_niothreads);
5400         goto cleanup;
5401     }
5402 
5403     virDomainIOThreadIDDel(vm->def, iothread_id);
5404 
5405     if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
5406                            iothread_id) < 0)
5407         goto cleanup;
5408 
5409     ret = 0;
5410 
5411  cleanup:
5412     if (new_iothreads) {
5413         for (idx = 0; idx < new_niothreads; idx++)
5414             VIR_FREE(new_iothreads[idx]);
5415         VIR_FREE(new_iothreads);
5416     }
5417     virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
5418                            "update", rc == 0);
5419     return ret;
5420 
5421  exit_monitor:
5422     ignore_value(qemuDomainObjExitMonitor(driver, vm));
5423     goto cleanup;
5424 }
5425 
5426 
5427 /**
5428  * @params: Pointer to params list
5429  * @nparams: Number of params to be parsed
5430  * @iothread: Buffer to store the values
5431  *
5432  * The following is a description of each value parsed:
5433  *
5434  *  - "poll-max-ns" for each IOThread is the maximum time in nanoseconds
5435  *    to allow each polling interval to occur. A polling interval is a
5436  *    period of time allowed for a thread to process data before it returns
5437  *    the CPU quantum back to the host. A value set too small will not allow
5438  *    the IOThread to run long enough on a CPU to process data. A value set
5439  *    too high will consume too much CPU time per IOThread failing to allow
5440  *    other threads running on the CPU to get time. A value of 0 (zero) will
5441  *    disable the polling.
5442  *
5443  * - "poll-grow" - factor to grow the current polling time when deemed
5444  *   necessary. If a 0 (zero) value is provided, QEMU currently doubles
5445  *   its polling interval unless the current value is greater than the
5446  *   poll-max-ns.
5447  *
5448  * - "poll-shrink" - divisor to reduced the current polling time when deemed
5449  *   necessary. If a 0 (zero) value is provided, QEMU resets the polling
5450  *   interval to 0 (zero) allowing the poll-grow to manipulate the time.
5451  *
5452  * QEMU keeps track of the polling time elapsed and may grow or shrink the
5453  * its polling interval based upon its heuristic algorithm. It is possible
5454  * that calculations determine that it has found a "sweet spot" and no
5455  * adjustments are made. The polling time value is not available.
5456  *
5457  * Returns 0 on success, -1 on failure with error set.
5458  */
5459 static int
qemuDomainIOThreadParseParams(virTypedParameterPtr params,int nparams,qemuMonitorIOThreadInfo * iothread)5460 qemuDomainIOThreadParseParams(virTypedParameterPtr params,
5461                               int nparams,
5462                               qemuMonitorIOThreadInfo *iothread)
5463 {
5464     int rc;
5465 
5466     if (virTypedParamsValidate(params, nparams,
5467                                VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
5468                                VIR_TYPED_PARAM_ULLONG,
5469                                VIR_DOMAIN_IOTHREAD_POLL_GROW,
5470                                VIR_TYPED_PARAM_UINT,
5471                                VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
5472                                VIR_TYPED_PARAM_UINT,
5473                                NULL) < 0)
5474         return -1;
5475 
5476     if ((rc = virTypedParamsGetULLong(params, nparams,
5477                                       VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
5478                                       &iothread->poll_max_ns)) < 0)
5479         return -1;
5480     if (rc == 1)
5481         iothread->set_poll_max_ns = true;
5482 
5483     if ((rc = virTypedParamsGetUInt(params, nparams,
5484                                     VIR_DOMAIN_IOTHREAD_POLL_GROW,
5485                                     &iothread->poll_grow)) < 0)
5486         return -1;
5487     if (rc == 1)
5488         iothread->set_poll_grow = true;
5489 
5490     if ((rc = virTypedParamsGetUInt(params, nparams,
5491                                     VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
5492                                     &iothread->poll_shrink)) < 0)
5493         return -1;
5494     if (rc == 1)
5495         iothread->set_poll_shrink = true;
5496 
5497     if (iothread->set_poll_max_ns && iothread->poll_max_ns > INT_MAX) {
5498         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5499                        _("poll-max-ns (%llu) must be less than or equal to %d"),
5500                        iothread->poll_max_ns, INT_MAX);
5501         return -1;
5502     }
5503 
5504     if (iothread->set_poll_grow && iothread->poll_grow > INT_MAX) {
5505         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5506                        _("poll-grow (%u) must be less than or equal to %d"),
5507                          iothread->poll_grow, INT_MAX);
5508         return -1;
5509     }
5510 
5511     if (iothread->set_poll_shrink && iothread->poll_shrink > INT_MAX) {
5512         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5513                        _("poll-shrink (%u) must be less than or equal to %d"),
5514                        iothread->poll_shrink, INT_MAX);
5515         return -1;
5516     }
5517 
5518     return 0;
5519 }
5520 
5521 
5522 typedef enum {
5523     VIR_DOMAIN_IOTHREAD_ACTION_ADD,
5524     VIR_DOMAIN_IOTHREAD_ACTION_DEL,
5525     VIR_DOMAIN_IOTHREAD_ACTION_MOD,
5526 } virDomainIOThreadAction;
5527 
5528 static int
qemuDomainChgIOThread(virQEMUDriver * driver,virDomainObj * vm,qemuMonitorIOThreadInfo iothread,virDomainIOThreadAction action,unsigned int flags)5529 qemuDomainChgIOThread(virQEMUDriver *driver,
5530                       virDomainObj *vm,
5531                       qemuMonitorIOThreadInfo iothread,
5532                       virDomainIOThreadAction action,
5533                       unsigned int flags)
5534 {
5535     g_autoptr(virQEMUDriverConfig) cfg = NULL;
5536     qemuDomainObjPrivate *priv;
5537     virDomainDef *def;
5538     virDomainDef *persistentDef;
5539     int ret = -1;
5540 
5541     cfg = virQEMUDriverGetConfig(driver);
5542 
5543     priv = vm->privateData;
5544 
5545     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5546         return -1;
5547 
5548     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5549         goto endjob;
5550 
5551     if (def) {
5552         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
5553             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5554                            _("IOThreads not supported with this binary"));
5555             goto endjob;
5556         }
5557 
5558         switch (action) {
5559         case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
5560             if (virDomainDriverAddIOThreadCheck(def, iothread.iothread_id) < 0)
5561                 goto endjob;
5562 
5563             if (qemuDomainHotplugAddIOThread(driver, vm, iothread.iothread_id) < 0)
5564                 goto endjob;
5565 
5566             break;
5567 
5568         case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
5569             if (virDomainDriverDelIOThreadCheck(def, iothread.iothread_id) < 0)
5570                 goto endjob;
5571 
5572             if (qemuDomainHotplugDelIOThread(driver, vm, iothread.iothread_id) < 0)
5573                 goto endjob;
5574 
5575             break;
5576 
5577         case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
5578             if (!(virDomainIOThreadIDFind(def, iothread.iothread_id))) {
5579                 virReportError(VIR_ERR_INVALID_ARG,
5580                                _("cannot find IOThread '%u' in iothreadids"),
5581                                iothread.iothread_id);
5582                 goto endjob;
5583             }
5584 
5585             if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0)
5586                 goto endjob;
5587 
5588             break;
5589 
5590         }
5591 
5592         qemuDomainSaveStatus(vm);
5593     }
5594 
5595     if (persistentDef) {
5596         switch (action) {
5597         case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
5598             if (virDomainDriverAddIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
5599                 goto endjob;
5600 
5601             if (!virDomainIOThreadIDAdd(persistentDef, iothread.iothread_id))
5602                 goto endjob;
5603 
5604             break;
5605 
5606         case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
5607             if (virDomainDriverDelIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
5608                 goto endjob;
5609 
5610             virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);
5611 
5612             break;
5613 
5614         case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
5615             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
5616                            _("configuring persistent polling values is "
5617                              "not supported"));
5618             goto endjob;
5619 
5620             break;
5621         }
5622 
5623         if (virDomainDefSave(persistentDef, driver->xmlopt,
5624                              cfg->configDir) < 0)
5625             goto endjob;
5626     }
5627 
5628     ret = 0;
5629 
5630  endjob:
5631     qemuDomainObjEndJob(driver, vm);
5632 
5633     return ret;
5634 }
5635 
5636 static int
qemuDomainAddIOThread(virDomainPtr dom,unsigned int iothread_id,unsigned int flags)5637 qemuDomainAddIOThread(virDomainPtr dom,
5638                       unsigned int iothread_id,
5639                       unsigned int flags)
5640 {
5641     virQEMUDriver *driver = dom->conn->privateData;
5642     virDomainObj *vm = NULL;
5643     qemuMonitorIOThreadInfo iothread = {0};
5644     int ret = -1;
5645 
5646     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5647                   VIR_DOMAIN_AFFECT_CONFIG, -1);
5648 
5649     if (iothread_id == 0) {
5650         virReportError(VIR_ERR_INVALID_ARG, "%s",
5651                        _("invalid value of 0 for iothread_id"));
5652         return -1;
5653     }
5654 
5655     if (!(vm = qemuDomainObjFromDomain(dom)))
5656         goto cleanup;
5657 
5658     if (virDomainAddIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
5659         goto cleanup;
5660 
5661     iothread.iothread_id = iothread_id;
5662     ret = qemuDomainChgIOThread(driver, vm, iothread,
5663                                 VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags);
5664 
5665  cleanup:
5666     virDomainObjEndAPI(&vm);
5667     return ret;
5668 }
5669 
5670 
5671 static int
qemuDomainDelIOThread(virDomainPtr dom,unsigned int iothread_id,unsigned int flags)5672 qemuDomainDelIOThread(virDomainPtr dom,
5673                       unsigned int iothread_id,
5674                       unsigned int flags)
5675 {
5676     virQEMUDriver *driver = dom->conn->privateData;
5677     virDomainObj *vm = NULL;
5678     qemuMonitorIOThreadInfo iothread = {0};
5679     int ret = -1;
5680 
5681     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5682                   VIR_DOMAIN_AFFECT_CONFIG, -1);
5683 
5684     if (iothread_id == 0) {
5685         virReportError(VIR_ERR_INVALID_ARG, "%s",
5686                        _("invalid value of 0 for iothread_id"));
5687         return -1;
5688     }
5689 
5690     if (!(vm = qemuDomainObjFromDomain(dom)))
5691         goto cleanup;
5692 
5693     if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
5694            goto cleanup;
5695 
5696     iothread.iothread_id = iothread_id;
5697     ret = qemuDomainChgIOThread(driver, vm, iothread,
5698                                 VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags);
5699 
5700  cleanup:
5701     virDomainObjEndAPI(&vm);
5702     return ret;
5703 }
5704 
5705 
5706 /**
5707  * @dom: Domain to set IOThread params
5708  * @iothread_id: IOThread 'id' that will be modified
5709  * @params: List of parameters to change
5710  * @nparams: Number of parameters in the list
5711  * @flags: Flags for the set (only supports live alteration)
5712  *
5713  * Alter the specified @iothread_id with the values provided.
5714  *
5715  * Returns 0 on success, -1 on failure
5716  */
5717 static int
qemuDomainSetIOThreadParams(virDomainPtr dom,unsigned int iothread_id,virTypedParameterPtr params,int nparams,unsigned int flags)5718 qemuDomainSetIOThreadParams(virDomainPtr dom,
5719                             unsigned int iothread_id,
5720                             virTypedParameterPtr params,
5721                             int nparams,
5722                             unsigned int flags)
5723 {
5724     virQEMUDriver *driver = dom->conn->privateData;
5725     virDomainObj *vm = NULL;
5726     qemuMonitorIOThreadInfo iothread = {0};
5727     int ret = -1;
5728 
5729     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE, -1);
5730 
5731     if (iothread_id == 0) {
5732         virReportError(VIR_ERR_INVALID_ARG, "%s",
5733                        _("invalid value of 0 for iothread_id"));
5734         goto cleanup;
5735     }
5736 
5737     iothread.iothread_id = iothread_id;
5738 
5739     if (!(vm = qemuDomainObjFromDomain(dom)))
5740         goto cleanup;
5741 
5742     if (virDomainSetIOThreadParamsEnsureACL(dom->conn, vm->def, flags) < 0)
5743         goto cleanup;
5744 
5745     if (qemuDomainIOThreadParseParams(params, nparams, &iothread) < 0)
5746         goto cleanup;
5747 
5748     ret = qemuDomainChgIOThread(driver, vm, iothread,
5749                                 VIR_DOMAIN_IOTHREAD_ACTION_MOD, flags);
5750 
5751  cleanup:
5752     virDomainObjEndAPI(&vm);
5753     return ret;
5754 }
5755 
5756 
qemuDomainGetSecurityLabel(virDomainPtr dom,virSecurityLabelPtr seclabel)5757 static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
5758 {
5759     virQEMUDriver *driver = dom->conn->privateData;
5760     virDomainObj *vm;
5761     int ret = -1;
5762 
5763     memset(seclabel, 0, sizeof(*seclabel));
5764 
5765     if (!(vm = qemuDomainObjFromDomain(dom)))
5766         return -1;
5767 
5768     if (virDomainGetSecurityLabelEnsureACL(dom->conn, vm->def) < 0)
5769         goto cleanup;
5770 
5771     /*
5772      * Theoretically, the pid can be replaced during this operation and
5773      * return the label of a different process.  If atomicity is needed,
5774      * further validation will be required.
5775      *
5776      * Comment from Dan Berrange:
5777      *
5778      *   Well the PID as stored in the virDomainObj *can't be changed
5779      *   because you've got a locked object.  The OS level PID could have
5780      *   exited, though and in extreme circumstances have cycled through all
5781      *   PIDs back to ours. We could sanity check that our PID still exists
5782      *   after reading the label, by checking that our FD connecting to the
5783      *   QEMU monitor hasn't seen SIGHUP/ERR on poll().
5784      */
5785     if (virDomainObjIsActive(vm)) {
5786         if (qemuSecurityGetProcessLabel(driver->securityManager,
5787                                         vm->def, vm->pid, seclabel) < 0)
5788             goto cleanup;
5789     }
5790 
5791     ret = 0;
5792 
5793  cleanup:
5794     virDomainObjEndAPI(&vm);
5795     return ret;
5796 }
5797 
qemuDomainGetSecurityLabelList(virDomainPtr dom,virSecurityLabelPtr * seclabels)5798 static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
5799                                           virSecurityLabelPtr* seclabels)
5800 {
5801     virQEMUDriver *driver = dom->conn->privateData;
5802     virDomainObj *vm;
5803     size_t i;
5804     int ret = -1;
5805 
5806     if (!(vm = qemuDomainObjFromDomain(dom)))
5807         return -1;
5808 
5809     if (virDomainGetSecurityLabelListEnsureACL(dom->conn, vm->def) < 0)
5810         goto cleanup;
5811 
5812     /*
5813      * Check the comment in qemuDomainGetSecurityLabel function.
5814      */
5815     if (!virDomainObjIsActive(vm)) {
5816         /* No seclabels */
5817         *seclabels = NULL;
5818         ret = 0;
5819     } else {
5820         int len = 0;
5821         virSecurityManager ** mgrs = qemuSecurityGetNested(driver->securityManager);
5822         if (!mgrs)
5823             goto cleanup;
5824 
5825         /* Allocate seclabels array */
5826         for (i = 0; mgrs[i]; i++)
5827             len++;
5828 
5829         (*seclabels) = g_new0(virSecurityLabel, len);
5830         memset(*seclabels, 0, sizeof(**seclabels) * len);
5831 
5832         /* Fill the array */
5833         for (i = 0; i < len; i++) {
5834             if (qemuSecurityGetProcessLabel(mgrs[i], vm->def, vm->pid,
5835                                             &(*seclabels)[i]) < 0) {
5836                 VIR_FREE(mgrs);
5837                 VIR_FREE(*seclabels);
5838                 goto cleanup;
5839             }
5840         }
5841         ret = len;
5842         VIR_FREE(mgrs);
5843     }
5844 
5845  cleanup:
5846     virDomainObjEndAPI(&vm);
5847     return ret;
5848 }
5849 
5850 
qemuNodeGetSecurityModel(virConnectPtr conn,virSecurityModelPtr secmodel)5851 static int qemuNodeGetSecurityModel(virConnectPtr conn,
5852                                     virSecurityModelPtr secmodel)
5853 {
5854     virQEMUDriver *driver = conn->privateData;
5855     g_autoptr(virCaps) caps = NULL;
5856 
5857     memset(secmodel, 0, sizeof(*secmodel));
5858 
5859     if (virNodeGetSecurityModelEnsureACL(conn) < 0)
5860         return -1;
5861 
5862     /* We treat no driver as success, but simply return no data in *secmodel */
5863     if (!(caps = virQEMUDriverGetCapabilities(driver, false)) ||
5864         caps->host.nsecModels == 0 ||
5865         caps->host.secModels[0].model == NULL)
5866         return 0;
5867 
5868     if (virStrcpy(secmodel->model, caps->host.secModels[0].model,
5869                   VIR_SECURITY_MODEL_BUFLEN) < 0) {
5870         virReportError(VIR_ERR_INTERNAL_ERROR,
5871                        _("security model string exceeds max %d bytes"),
5872                        VIR_SECURITY_MODEL_BUFLEN - 1);
5873         return -1;
5874     }
5875 
5876     if (virStrcpy(secmodel->doi, caps->host.secModels[0].doi,
5877                   VIR_SECURITY_DOI_BUFLEN) < 0) {
5878         virReportError(VIR_ERR_INTERNAL_ERROR,
5879                        _("security DOI string exceeds max %d bytes"),
5880                        VIR_SECURITY_DOI_BUFLEN - 1);
5881         return -1;
5882     }
5883 
5884     return 0;
5885 }
5886 
5887 
5888 static int
qemuDomainRestoreFlags(virConnectPtr conn,const char * path,const char * dxml,unsigned int flags)5889 qemuDomainRestoreFlags(virConnectPtr conn,
5890                        const char *path,
5891                        const char *dxml,
5892                        unsigned int flags)
5893 {
5894     virQEMUDriver *driver = conn->privateData;
5895     qemuDomainObjPrivate *priv = NULL;
5896     g_autoptr(virDomainDef) def = NULL;
5897     virDomainObj *vm = NULL;
5898     g_autofree char *xmlout = NULL;
5899     const char *newxml = dxml;
5900     int fd = -1;
5901     int ret = -1;
5902     virQEMUSaveData *data = NULL;
5903     virFileWrapperFd *wrapperFd = NULL;
5904     bool hook_taint = false;
5905 
5906     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
5907                   VIR_DOMAIN_SAVE_RUNNING |
5908                   VIR_DOMAIN_SAVE_PAUSED, -1);
5909 
5910 
5911     virNWFilterReadLockFilterUpdates();
5912 
5913     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
5914                            (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
5915                            &wrapperFd, false, false);
5916     if (fd < 0)
5917         goto cleanup;
5918 
5919     if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
5920         goto cleanup;
5921 
5922     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
5923         int hookret;
5924 
5925         if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
5926                                    VIR_HOOK_QEMU_OP_RESTORE,
5927                                    VIR_HOOK_SUBOP_BEGIN,
5928                                    NULL,
5929                                    dxml ? dxml : data->xml,
5930                                    &xmlout)) < 0)
5931             goto cleanup;
5932 
5933         if (hookret == 0 && !virStringIsEmpty(xmlout)) {
5934             VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
5935             hook_taint = true;
5936             newxml = xmlout;
5937         }
5938     }
5939 
5940     if (newxml) {
5941         virDomainDef *tmp;
5942         if (!(tmp = qemuSaveImageUpdateDef(driver, def, newxml)))
5943             goto cleanup;
5944 
5945         virDomainDefFree(def);
5946         def = tmp;
5947     }
5948 
5949     if (!(vm = virDomainObjListAdd(driver->domains, &def,
5950                                    driver->xmlopt,
5951                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
5952                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
5953                                    NULL)))
5954         goto cleanup;
5955 
5956     if (flags & VIR_DOMAIN_SAVE_RUNNING)
5957         data->header.was_running = 1;
5958     else if (flags & VIR_DOMAIN_SAVE_PAUSED)
5959         data->header.was_running = 0;
5960 
5961     if (hook_taint) {
5962         priv = vm->privateData;
5963         priv->hookRun = true;
5964     }
5965 
5966     if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_RESTORE,
5967                             flags) < 0)
5968         goto cleanup;
5969 
5970     ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
5971                                false, QEMU_ASYNC_JOB_START);
5972 
5973     qemuProcessEndJob(driver, vm);
5974 
5975  cleanup:
5976     VIR_FORCE_CLOSE(fd);
5977     if (virFileWrapperFdClose(wrapperFd) < 0)
5978         ret = -1;
5979     virFileWrapperFdFree(wrapperFd);
5980     virQEMUSaveDataFree(data);
5981     if (vm && ret < 0)
5982         qemuDomainRemoveInactiveJob(driver, vm);
5983     virDomainObjEndAPI(&vm);
5984     virNWFilterUnlockFilterUpdates();
5985     return ret;
5986 }
5987 
5988 static int
qemuDomainRestore(virConnectPtr conn,const char * path)5989 qemuDomainRestore(virConnectPtr conn,
5990                   const char *path)
5991 {
5992     return qemuDomainRestoreFlags(conn, path, NULL, 0);
5993 }
5994 
5995 static char *
qemuDomainSaveImageGetXMLDesc(virConnectPtr conn,const char * path,unsigned int flags)5996 qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
5997                               unsigned int flags)
5998 {
5999     virQEMUDriver *driver = conn->privateData;
6000     char *ret = NULL;
6001     g_autoptr(virDomainDef) def = NULL;
6002     int fd = -1;
6003     virQEMUSaveData *data = NULL;
6004 
6005     virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
6006 
6007     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
6008                            false, NULL, false, false);
6009 
6010     if (fd < 0)
6011         goto cleanup;
6012 
6013     if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0)
6014         goto cleanup;
6015 
6016     ret = qemuDomainDefFormatXML(driver, NULL, def, flags);
6017 
6018  cleanup:
6019     virQEMUSaveDataFree(data);
6020     VIR_FORCE_CLOSE(fd);
6021     return ret;
6022 }
6023 
6024 static int
qemuDomainSaveImageDefineXML(virConnectPtr conn,const char * path,const char * dxml,unsigned int flags)6025 qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
6026                              const char *dxml, unsigned int flags)
6027 {
6028     virQEMUDriver *driver = conn->privateData;
6029     int ret = -1;
6030     g_autoptr(virDomainDef) def = NULL;
6031     g_autoptr(virDomainDef) newdef = NULL;
6032     int fd = -1;
6033     virQEMUSaveData *data = NULL;
6034     int state = -1;
6035 
6036     virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
6037                   VIR_DOMAIN_SAVE_PAUSED, -1);
6038 
6039     if (flags & VIR_DOMAIN_SAVE_RUNNING)
6040         state = 1;
6041     else if (flags & VIR_DOMAIN_SAVE_PAUSED)
6042         state = 0;
6043 
6044     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
6045                            false, NULL, true, false);
6046 
6047     if (fd < 0)
6048         goto cleanup;
6049 
6050     if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0)
6051         goto cleanup;
6052 
6053     if (STREQ(data->xml, dxml) &&
6054         (state < 0 || state == data->header.was_running)) {
6055         /* no change to the XML */
6056         ret = 0;
6057         goto cleanup;
6058     }
6059 
6060     if (state >= 0)
6061         data->header.was_running = state;
6062 
6063     if (!(newdef = qemuSaveImageUpdateDef(driver, def, dxml)))
6064         goto cleanup;
6065 
6066     VIR_FREE(data->xml);
6067 
6068     if (!(data->xml = qemuDomainDefFormatXML(driver, NULL, newdef,
6069                                              VIR_DOMAIN_XML_INACTIVE |
6070                                              VIR_DOMAIN_XML_SECURE |
6071                                              VIR_DOMAIN_XML_MIGRATABLE)))
6072         goto cleanup;
6073 
6074     if (lseek(fd, 0, SEEK_SET) != 0) {
6075         virReportSystemError(errno, _("cannot seek in '%s'"), path);
6076         goto cleanup;
6077     }
6078 
6079     if (virQEMUSaveDataWrite(data, fd, path) < 0)
6080         goto cleanup;
6081 
6082     if (VIR_CLOSE(fd) < 0) {
6083         virReportSystemError(errno, _("failed to write header data to '%s'"), path);
6084         goto cleanup;
6085     }
6086 
6087     ret = 0;
6088 
6089  cleanup:
6090     VIR_FORCE_CLOSE(fd);
6091     virQEMUSaveDataFree(data);
6092     return ret;
6093 }
6094 
6095 static char *
qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom,unsigned int flags)6096 qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags)
6097 {
6098     virQEMUDriver *driver = dom->conn->privateData;
6099     virDomainObj *vm;
6100     g_autofree char *path = NULL;
6101     char *ret = NULL;
6102     g_autoptr(virDomainDef) def = NULL;
6103     int fd = -1;
6104     virQEMUSaveData *data = NULL;
6105     qemuDomainObjPrivate *priv;
6106 
6107     virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
6108 
6109     if (!(vm = qemuDomainObjFromDomain(dom)))
6110         return ret;
6111 
6112     priv = vm->privateData;
6113 
6114     if (virDomainManagedSaveGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
6115         goto cleanup;
6116 
6117     if (!(path = qemuDomainManagedSavePath(driver, vm)))
6118         goto cleanup;
6119 
6120     if (!virFileExists(path)) {
6121         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6122                        _("domain does not have managed save image"));
6123         goto cleanup;
6124     }
6125 
6126     if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data,
6127                                 false, NULL, false, false)) < 0)
6128         goto cleanup;
6129 
6130     ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags);
6131 
6132  cleanup:
6133     virQEMUSaveDataFree(data);
6134     VIR_FORCE_CLOSE(fd);
6135     virDomainObjEndAPI(&vm);
6136     return ret;
6137 }
6138 
6139 static int
qemuDomainManagedSaveDefineXML(virDomainPtr dom,const char * dxml,unsigned int flags)6140 qemuDomainManagedSaveDefineXML(virDomainPtr dom, const char *dxml,
6141                                unsigned int flags)
6142 {
6143     virQEMUDriver *driver = dom->conn->privateData;
6144     virConnectPtr conn = dom->conn;
6145     virDomainObj *vm;
6146     g_autofree char *path = NULL;
6147     int ret = -1;
6148 
6149     if (!(vm = qemuDomainObjFromDomain(dom)))
6150         return -1;
6151 
6152     if (virDomainManagedSaveDefineXMLEnsureACL(conn, vm->def) < 0)
6153         goto cleanup;
6154 
6155     if (!(path = qemuDomainManagedSavePath(driver, vm)))
6156         goto cleanup;
6157 
6158     if (!virFileExists(path)) {
6159         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6160                        _("domain does not have managed save image"));
6161         goto cleanup;
6162     }
6163 
6164     ret = qemuDomainSaveImageDefineXML(conn, path, dxml, flags);
6165 
6166  cleanup:
6167     virDomainObjEndAPI(&vm);
6168     return ret;
6169 }
6170 
6171 /* Return 0 on success, 1 if incomplete saved image was silently unlinked,
6172  * and -1 on failure with error raised.  */
6173 static int
qemuDomainObjRestore(virConnectPtr conn,virQEMUDriver * driver,virDomainObj * vm,const char * path,bool start_paused,bool bypass_cache,qemuDomainAsyncJob asyncJob)6174 qemuDomainObjRestore(virConnectPtr conn,
6175                      virQEMUDriver *driver,
6176                      virDomainObj *vm,
6177                      const char *path,
6178                      bool start_paused,
6179                      bool bypass_cache,
6180                      qemuDomainAsyncJob asyncJob)
6181 {
6182     g_autoptr(virDomainDef) def = NULL;
6183     qemuDomainObjPrivate *priv = vm->privateData;
6184     int fd = -1;
6185     int ret = -1;
6186     g_autofree char *xmlout = NULL;
6187     virQEMUSaveData *data = NULL;
6188     virFileWrapperFd *wrapperFd = NULL;
6189 
6190     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
6191                            bypass_cache, &wrapperFd, false, true);
6192     if (fd < 0) {
6193         if (fd == -3)
6194             ret = 1;
6195         goto cleanup;
6196     }
6197 
6198     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
6199         int hookret;
6200 
6201         if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
6202                                    VIR_HOOK_QEMU_OP_RESTORE,
6203                                    VIR_HOOK_SUBOP_BEGIN,
6204                                    NULL, data->xml, &xmlout)) < 0)
6205             goto cleanup;
6206 
6207         if (hookret == 0 && !virStringIsEmpty(xmlout)) {
6208             virDomainDef *tmp;
6209 
6210             VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
6211 
6212             if (!(tmp = qemuSaveImageUpdateDef(driver, def, xmlout)))
6213                 goto cleanup;
6214 
6215             virDomainDefFree(def);
6216             def = tmp;
6217             priv->hookRun = true;
6218         }
6219     }
6220 
6221     if (STRNEQ(vm->def->name, def->name) ||
6222         memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
6223         char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
6224         char def_uuidstr[VIR_UUID_STRING_BUFLEN];
6225         virUUIDFormat(vm->def->uuid, vm_uuidstr);
6226         virUUIDFormat(def->uuid, def_uuidstr);
6227         virReportError(VIR_ERR_OPERATION_FAILED,
6228                        _("cannot restore domain '%s' uuid %s from a file"
6229                          " which belongs to domain '%s' uuid %s"),
6230                        vm->def->name, vm_uuidstr,
6231                        def->name, def_uuidstr);
6232         goto cleanup;
6233     }
6234 
6235     virDomainObjAssignDef(vm, &def, true, NULL);
6236 
6237     ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
6238                                start_paused, asyncJob);
6239 
6240  cleanup:
6241     virQEMUSaveDataFree(data);
6242     VIR_FORCE_CLOSE(fd);
6243     if (virFileWrapperFdClose(wrapperFd) < 0)
6244         ret = -1;
6245     virFileWrapperFdFree(wrapperFd);
6246     return ret;
6247 }
6248 
6249 
6250 static char
qemuDomainGetXMLDesc(virDomainPtr dom,unsigned int flags)6251 *qemuDomainGetXMLDesc(virDomainPtr dom,
6252                       unsigned int flags)
6253 {
6254     virQEMUDriver *driver = dom->conn->privateData;
6255     virDomainObj *vm;
6256     char *ret = NULL;
6257 
6258     virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS | VIR_DOMAIN_XML_UPDATE_CPU,
6259                   NULL);
6260 
6261     if (!(vm = qemuDomainObjFromDomain(dom)))
6262         goto cleanup;
6263 
6264     if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
6265         goto cleanup;
6266 
6267     qemuDomainUpdateCurrentMemorySize(vm);
6268 
6269     if ((flags & VIR_DOMAIN_XML_MIGRATABLE))
6270         flags |= QEMU_DOMAIN_FORMAT_LIVE_FLAGS;
6271 
6272     /* The CPU is already updated in the domain's live definition, we need to
6273      * ignore the VIR_DOMAIN_XML_UPDATE_CPU flag.
6274      */
6275     if (virDomainObjIsActive(vm) &&
6276         !(flags & VIR_DOMAIN_XML_INACTIVE))
6277         flags &= ~VIR_DOMAIN_XML_UPDATE_CPU;
6278 
6279     ret = qemuDomainFormatXML(driver, vm, flags);
6280 
6281  cleanup:
6282     virDomainObjEndAPI(&vm);
6283     return ret;
6284 }
6285 
6286 
6287 static int
qemuConnectDomainXMLToNativePrepareHostHostdev(virDomainHostdevDef * hostdev)6288 qemuConnectDomainXMLToNativePrepareHostHostdev(virDomainHostdevDef *hostdev)
6289 {
6290     if (virHostdevIsSCSIDevice(hostdev)) {
6291         virDomainHostdevSubsysSCSI *scsisrc = &hostdev->source.subsys.u.scsi;
6292 
6293         switch ((virDomainHostdevSCSIProtocolType) scsisrc->protocol) {
6294         case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE: {
6295             virDomainHostdevSubsysSCSIHost *scsihostsrc = &scsisrc->u.host;
6296             virStorageSource *src = scsisrc->u.host.src;
6297             g_autofree char *devstr = NULL;
6298 
6299             if (!(devstr = virSCSIDeviceGetSgName(NULL,
6300                                                   scsihostsrc->adapter,
6301                                                   scsihostsrc->bus,
6302                                                   scsihostsrc->target,
6303                                                   scsihostsrc->unit)))
6304                 return -1;
6305 
6306             src->path = g_strdup_printf("/dev/%s", devstr);
6307             break;
6308         }
6309 
6310         case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI:
6311             break;
6312 
6313         case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST:
6314         default:
6315             virReportEnumRangeError(virDomainHostdevSCSIProtocolType, scsisrc->protocol);
6316             return -1;
6317         }
6318     }
6319 
6320     return 0;
6321 }
6322 
6323 
6324 static int
qemuConnectDomainXMLToNativePrepareHost(virDomainObj * vm)6325 qemuConnectDomainXMLToNativePrepareHost(virDomainObj *vm)
6326 {
6327     size_t i;
6328 
6329     for (i = 0; i < vm->def->nhostdevs; i++) {
6330         virDomainHostdevDef *hostdev = vm->def->hostdevs[i];
6331 
6332         if (qemuConnectDomainXMLToNativePrepareHostHostdev(hostdev) < 0)
6333             return -1;
6334     }
6335 
6336     return 0;
6337 }
6338 
6339 
qemuConnectDomainXMLToNative(virConnectPtr conn,const char * format,const char * xmlData,unsigned int flags)6340 static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
6341                                           const char *format,
6342                                           const char *xmlData,
6343                                           unsigned int flags)
6344 {
6345     virQEMUDriver *driver = conn->privateData;
6346     virDomainObj *vm = NULL;
6347     virCommand *cmd = NULL;
6348     char *ret = NULL;
6349     size_t i;
6350 
6351     virCheckFlags(0, NULL);
6352 
6353     if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
6354         goto cleanup;
6355 
6356     if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
6357         virReportError(VIR_ERR_INVALID_ARG,
6358                        _("unsupported config type %s"), format);
6359         goto cleanup;
6360     }
6361 
6362     if (!(vm = virDomainObjNew(driver->xmlopt)))
6363         goto cleanup;
6364 
6365     if (!(vm->def = virDomainDefParseString(xmlData, driver->xmlopt, NULL,
6366                                             VIR_DOMAIN_DEF_PARSE_INACTIVE |
6367                                             VIR_DOMAIN_DEF_PARSE_ABI_UPDATE)))
6368         goto cleanup;
6369 
6370     /* Since we're just exporting args, we can't do bridge/network/direct
6371      * setups, since libvirt will normally create TAP/macvtap devices
6372      * directly. We convert those configs into generic 'ethernet'
6373      * config and assume the user has suitable 'ifup-qemu' scripts
6374      */
6375     for (i = 0; i < vm->def->nnets; i++) {
6376         virDomainNetDef *net = vm->def->nets[i];
6377         virDomainNetDef *newNet = virDomainNetDefNew(driver->xmlopt);
6378 
6379         if (!newNet)
6380             goto cleanup;
6381 
6382         newNet->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
6383         newNet->info.bootIndex = net->info.bootIndex;
6384         newNet->model = net->model;
6385         newNet->modelstr = g_steal_pointer(&net->modelstr);
6386         newNet->mac = net->mac;
6387         newNet->script = g_steal_pointer(&net->script);
6388 
6389         virDomainNetDefFree(net);
6390         vm->def->nets[i] = newNet;
6391     }
6392 
6393     if (qemuProcessCreatePretendCmdPrepare(driver, vm, NULL, true,
6394                                            VIR_QEMU_PROCESS_START_COLD) < 0)
6395         goto cleanup;
6396 
6397     if (qemuConnectDomainXMLToNativePrepareHost(vm) < 0)
6398         goto cleanup;
6399 
6400     if (!(cmd = qemuProcessCreatePretendCmdBuild(driver, vm, NULL,
6401                                                  qemuCheckFips(vm), true)))
6402         goto cleanup;
6403 
6404     ret = virCommandToString(cmd, false);
6405 
6406  cleanup:
6407     virCommandFree(cmd);
6408     virObjectUnref(vm);
6409     return ret;
6410 }
6411 
6412 
qemuConnectListDefinedDomains(virConnectPtr conn,char ** const names,int nnames)6413 static int qemuConnectListDefinedDomains(virConnectPtr conn,
6414                                          char **const names, int nnames) {
6415     virQEMUDriver *driver = conn->privateData;
6416 
6417     if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
6418         return -1;
6419 
6420     return virDomainObjListGetInactiveNames(driver->domains, names, nnames,
6421                                             virConnectListDefinedDomainsCheckACL,
6422                                             conn);
6423 }
6424 
qemuConnectNumOfDefinedDomains(virConnectPtr conn)6425 static int qemuConnectNumOfDefinedDomains(virConnectPtr conn)
6426 {
6427     virQEMUDriver *driver = conn->privateData;
6428 
6429     if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
6430         return -1;
6431 
6432     return virDomainObjListNumOfDomains(driver->domains, false,
6433                                         virConnectNumOfDefinedDomainsCheckACL,
6434                                         conn);
6435 }
6436 
6437 
6438 static int
qemuDomainObjStart(virConnectPtr conn,virQEMUDriver * driver,virDomainObj * vm,unsigned int flags,qemuDomainAsyncJob asyncJob)6439 qemuDomainObjStart(virConnectPtr conn,
6440                    virQEMUDriver *driver,
6441                    virDomainObj *vm,
6442                    unsigned int flags,
6443                    qemuDomainAsyncJob asyncJob)
6444 {
6445     int ret = -1;
6446     g_autofree char *managed_save = NULL;
6447     bool start_paused = (flags & VIR_DOMAIN_START_PAUSED) != 0;
6448     bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0;
6449     bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0;
6450     bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0;
6451     unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
6452     qemuDomainObjPrivate *priv = vm->privateData;
6453 
6454     start_flags |= start_paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
6455     start_flags |= autodestroy ? VIR_QEMU_PROCESS_START_AUTODESTROY : 0;
6456 
6457     /*
6458      * If there is a managed saved state restore it instead of starting
6459      * from scratch. The old state is removed once the restoring succeeded.
6460      */
6461     managed_save = qemuDomainManagedSavePath(driver, vm);
6462 
6463     if (!managed_save)
6464         return ret;
6465 
6466     if (virFileExists(managed_save)) {
6467         if (force_boot) {
6468             if (unlink(managed_save) < 0) {
6469                 virReportSystemError(errno,
6470                                      _("cannot remove managed save file %s"),
6471                                      managed_save);
6472                 return ret;
6473             }
6474             vm->hasManagedSave = false;
6475         } else {
6476             virDomainJobOperation op = priv->job.current->operation;
6477             priv->job.current->operation = VIR_DOMAIN_JOB_OPERATION_RESTORE;
6478 
6479             ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
6480                                        start_paused, bypass_cache, asyncJob);
6481 
6482             if (ret == 0) {
6483                 if (unlink(managed_save) < 0)
6484                     VIR_WARN("Failed to remove the managed state %s", managed_save);
6485                 else
6486                     vm->hasManagedSave = false;
6487 
6488                 return ret;
6489             } else if (ret < 0) {
6490                 VIR_WARN("Unable to restore from managed state %s. "
6491                          "Maybe the file is corrupted?", managed_save);
6492                 return ret;
6493             } else {
6494                 VIR_WARN("Ignoring incomplete managed state %s", managed_save);
6495                 priv->job.current->operation = op;
6496                 vm->hasManagedSave = false;
6497             }
6498         }
6499     }
6500 
6501     ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
6502                            NULL, -1, NULL, NULL,
6503                            VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
6504     virDomainAuditStart(vm, "booted", ret >= 0);
6505     if (ret >= 0) {
6506         virObjectEvent *event =
6507             virDomainEventLifecycleNewFromObj(vm,
6508                                      VIR_DOMAIN_EVENT_STARTED,
6509                                      VIR_DOMAIN_EVENT_STARTED_BOOTED);
6510         virObjectEventStateQueue(driver->domainEventState, event);
6511         if (start_paused) {
6512             event = virDomainEventLifecycleNewFromObj(vm,
6513                                              VIR_DOMAIN_EVENT_SUSPENDED,
6514                                              VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
6515             virObjectEventStateQueue(driver->domainEventState, event);
6516         }
6517     }
6518 
6519     return ret;
6520 }
6521 
6522 static int
qemuDomainCreateWithFlags(virDomainPtr dom,unsigned int flags)6523 qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
6524 {
6525     virQEMUDriver *driver = dom->conn->privateData;
6526     virDomainObj *vm;
6527     int ret = -1;
6528 
6529     virCheckFlags(VIR_DOMAIN_START_PAUSED |
6530                   VIR_DOMAIN_START_AUTODESTROY |
6531                   VIR_DOMAIN_START_BYPASS_CACHE |
6532                   VIR_DOMAIN_START_FORCE_BOOT, -1);
6533 
6534     virNWFilterReadLockFilterUpdates();
6535 
6536     if (!(vm = qemuDomainObjFromDomain(dom)))
6537         goto cleanup;
6538 
6539     if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
6540         goto cleanup;
6541 
6542     if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_START,
6543                             flags) < 0)
6544         goto cleanup;
6545 
6546     if (virDomainObjIsActive(vm)) {
6547         virReportError(VIR_ERR_OPERATION_INVALID,
6548                        "%s", _("domain is already running"));
6549         goto endjob;
6550     }
6551 
6552     if (qemuDomainObjStart(dom->conn, driver, vm, flags,
6553                            QEMU_ASYNC_JOB_START) < 0)
6554         goto endjob;
6555 
6556     dom->id = vm->def->id;
6557     ret = 0;
6558 
6559  endjob:
6560     qemuProcessEndJob(driver, vm);
6561 
6562  cleanup:
6563     virDomainObjEndAPI(&vm);
6564     virNWFilterUnlockFilterUpdates();
6565     return ret;
6566 }
6567 
6568 static int
qemuDomainCreate(virDomainPtr dom)6569 qemuDomainCreate(virDomainPtr dom)
6570 {
6571     return qemuDomainCreateWithFlags(dom, 0);
6572 }
6573 
6574 static virDomainPtr
qemuDomainDefineXMLFlags(virConnectPtr conn,const char * xml,unsigned int flags)6575 qemuDomainDefineXMLFlags(virConnectPtr conn,
6576                          const char *xml,
6577                          unsigned int flags)
6578 {
6579     virQEMUDriver *driver = conn->privateData;
6580     g_autoptr(virDomainDef) def = NULL;
6581     g_autoptr(virDomainDef) oldDef = NULL;
6582     virDomainObj *vm = NULL;
6583     virDomainPtr dom = NULL;
6584     virObjectEvent *event = NULL;
6585     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
6586     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
6587                                VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
6588 
6589     virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
6590 
6591     if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
6592         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
6593 
6594     if (!(def = virDomainDefParseString(xml, driver->xmlopt,
6595                                         NULL, parse_flags)))
6596         return NULL;
6597 
6598     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
6599         goto cleanup;
6600 
6601     if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
6602         goto cleanup;
6603 
6604     if (!(vm = virDomainObjListAdd(driver->domains, &def,
6605                                    driver->xmlopt,
6606                                    0, &oldDef)))
6607         goto cleanup;
6608 
6609     if (!oldDef && qemuDomainNamePathsCleanup(cfg, vm->def->name, false) < 0)
6610         goto cleanup;
6611 
6612     if (virDomainDefSave(vm->newDef ? vm->newDef : vm->def,
6613                          driver->xmlopt, cfg->configDir) < 0)
6614         goto cleanup;
6615 
6616     vm->persistent = 1;
6617 
6618     event = virDomainEventLifecycleNewFromObj(vm,
6619                                      VIR_DOMAIN_EVENT_DEFINED,
6620                                      !oldDef ?
6621                                      VIR_DOMAIN_EVENT_DEFINED_ADDED :
6622                                      VIR_DOMAIN_EVENT_DEFINED_UPDATED);
6623 
6624     VIR_INFO("Creating domain '%s'", vm->def->name);
6625     dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
6626 
6627  cleanup:
6628     if (!dom && !def) {
6629         if (oldDef) {
6630             /* There is backup so this VM was defined before.
6631              * Just restore the backup. */
6632             VIR_INFO("Restoring domain '%s' definition", vm->def->name);
6633             if (virDomainObjIsActive(vm))
6634                 vm->newDef = oldDef;
6635             else
6636                 vm->def = oldDef;
6637             oldDef = NULL;
6638         } else {
6639             /* Brand new domain. Remove it */
6640             VIR_INFO("Deleting domain '%s'", vm->def->name);
6641             qemuDomainRemoveInactiveJob(driver, vm);
6642         }
6643     }
6644 
6645     virDomainObjEndAPI(&vm);
6646     virObjectEventStateQueue(driver->domainEventState, event);
6647     return dom;
6648 }
6649 
6650 static virDomainPtr
qemuDomainDefineXML(virConnectPtr conn,const char * xml)6651 qemuDomainDefineXML(virConnectPtr conn, const char *xml)
6652 {
6653     return qemuDomainDefineXMLFlags(conn, xml, 0);
6654 }
6655 
6656 static int
qemuDomainUndefineFlags(virDomainPtr dom,unsigned int flags)6657 qemuDomainUndefineFlags(virDomainPtr dom,
6658                         unsigned int flags)
6659 {
6660     virQEMUDriver *driver = dom->conn->privateData;
6661     virDomainObj *vm;
6662     virObjectEvent *event = NULL;
6663     g_autofree char *name = NULL;
6664     int ret = -1;
6665     int nsnapshots;
6666     int ncheckpoints;
6667     g_autoptr(virQEMUDriverConfig) cfg = NULL;
6668     g_autofree char *nvram_path = NULL;
6669 
6670     virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
6671                   VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
6672                   VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA |
6673                   VIR_DOMAIN_UNDEFINE_NVRAM |
6674                   VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, -1);
6675 
6676     if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM) &&
6677         (flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
6678         virReportError(VIR_ERR_OPERATION_INVALID,
6679                        "%s", _("cannot both keep and delete nvram"));
6680         return -1;
6681     }
6682 
6683     if (!(vm = qemuDomainObjFromDomain(dom)))
6684         return -1;
6685 
6686     cfg = virQEMUDriverGetConfig(driver);
6687 
6688     if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
6689         goto cleanup;
6690 
6691     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
6692         goto cleanup;
6693 
6694     if (!vm->persistent) {
6695         virReportError(VIR_ERR_OPERATION_INVALID,
6696                        "%s", _("cannot undefine transient domain"));
6697         goto endjob;
6698     }
6699 
6700     if (!virDomainObjIsActive(vm) &&
6701         (nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0))) {
6702         if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
6703             virReportError(VIR_ERR_OPERATION_INVALID,
6704                            _("cannot delete inactive domain with %d "
6705                              "snapshots"),
6706                            nsnapshots);
6707             goto endjob;
6708         }
6709         if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0)
6710             goto endjob;
6711     }
6712     if (!virDomainObjIsActive(vm) &&
6713         (ncheckpoints = virDomainListCheckpoints(vm->checkpoints, NULL, dom,
6714                                                  NULL, flags)) > 0) {
6715         if (!(flags & VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA)) {
6716             virReportError(VIR_ERR_OPERATION_INVALID,
6717                            _("cannot delete inactive domain with %d "
6718                              "checkpoints"),
6719                            ncheckpoints);
6720             goto endjob;
6721         }
6722         if (qemuCheckpointDiscardAllMetadata(driver, vm) < 0)
6723             goto endjob;
6724     }
6725 
6726     name = qemuDomainManagedSavePath(driver, vm);
6727     if (name == NULL)
6728         goto endjob;
6729 
6730     if (virFileExists(name)) {
6731         if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
6732             if (unlink(name) < 0) {
6733                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6734                                _("Failed to remove domain managed "
6735                                  "save image"));
6736                 goto endjob;
6737             }
6738         } else {
6739             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6740                            _("Refusing to undefine while domain managed "
6741                              "save image exists"));
6742             goto endjob;
6743         }
6744     }
6745 
6746     if (vm->def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) {
6747         qemuDomainNVRAMPathFormat(cfg, vm->def, &nvram_path);
6748     } else {
6749         if (vm->def->os.loader)
6750             nvram_path = g_strdup(vm->def->os.loader->nvram);
6751     }
6752 
6753     if (nvram_path && virFileExists(nvram_path)) {
6754         if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
6755             if (unlink(nvram_path) < 0) {
6756                 virReportSystemError(errno,
6757                                      _("failed to remove nvram: %s"),
6758                                      nvram_path);
6759                 goto endjob;
6760             }
6761         } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
6762             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6763                            _("cannot undefine domain with nvram"));
6764             goto endjob;
6765         }
6766     }
6767 
6768     if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
6769         goto endjob;
6770 
6771     event = virDomainEventLifecycleNewFromObj(vm,
6772                                      VIR_DOMAIN_EVENT_UNDEFINED,
6773                                      VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
6774 
6775     VIR_INFO("Undefining domain '%s'", vm->def->name);
6776 
6777     /* If the domain is active, keep it running but set it as transient.
6778      * domainDestroy and domainShutdown will take care of removing the
6779      * domain obj from the hash table.
6780      */
6781     vm->persistent = 0;
6782     if (!virDomainObjIsActive(vm))
6783         qemuDomainRemoveInactive(driver, vm);
6784 
6785     ret = 0;
6786  endjob:
6787     qemuDomainObjEndJob(driver, vm);
6788 
6789  cleanup:
6790     virDomainObjEndAPI(&vm);
6791     virObjectEventStateQueue(driver->domainEventState, event);
6792     return ret;
6793 }
6794 
6795 static int
qemuDomainUndefine(virDomainPtr dom)6796 qemuDomainUndefine(virDomainPtr dom)
6797 {
6798     return qemuDomainUndefineFlags(dom, 0);
6799 }
6800 
6801 static int
qemuDomainAttachDeviceLive(virDomainObj * vm,virDomainDeviceDef * dev,virQEMUDriver * driver)6802 qemuDomainAttachDeviceLive(virDomainObj *vm,
6803                            virDomainDeviceDef *dev,
6804                            virQEMUDriver *driver)
6805 {
6806     int ret = -1;
6807     const char *alias = NULL;
6808 
6809     switch ((virDomainDeviceType)dev->type) {
6810     case VIR_DOMAIN_DEVICE_DISK:
6811         qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
6812         ret = qemuDomainAttachDeviceDiskLive(driver, vm, dev);
6813         if (!ret) {
6814             alias = dev->data.disk->info.alias;
6815             dev->data.disk = NULL;
6816         }
6817         break;
6818 
6819     case VIR_DOMAIN_DEVICE_CONTROLLER:
6820         ret = qemuDomainAttachControllerDevice(driver, vm, dev->data.controller);
6821         if (!ret) {
6822             alias = dev->data.controller->info.alias;
6823             dev->data.controller = NULL;
6824         }
6825         break;
6826 
6827     case VIR_DOMAIN_DEVICE_LEASE:
6828         ret = qemuDomainAttachLease(driver, vm,
6829                                     dev->data.lease);
6830         if (ret == 0)
6831             dev->data.lease = NULL;
6832         break;
6833 
6834     case VIR_DOMAIN_DEVICE_NET:
6835         qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, NULL);
6836         ret = qemuDomainAttachNetDevice(driver, vm, dev->data.net);
6837         if (!ret) {
6838             alias = dev->data.net->info.alias;
6839             dev->data.net = NULL;
6840         }
6841         break;
6842 
6843     case VIR_DOMAIN_DEVICE_HOSTDEV:
6844         qemuDomainObjCheckHostdevTaint(driver, vm, dev->data.hostdev, NULL);
6845         ret = qemuDomainAttachHostDevice(driver, vm,
6846                                          dev->data.hostdev);
6847         if (!ret) {
6848             alias = dev->data.hostdev->info->alias;
6849             dev->data.hostdev = NULL;
6850         }
6851         break;
6852 
6853     case VIR_DOMAIN_DEVICE_REDIRDEV:
6854         ret = qemuDomainAttachRedirdevDevice(driver, vm,
6855                                              dev->data.redirdev);
6856         if (!ret) {
6857             alias = dev->data.redirdev->info.alias;
6858             dev->data.redirdev = NULL;
6859         }
6860         break;
6861 
6862     case VIR_DOMAIN_DEVICE_CHR:
6863         ret = qemuDomainAttachChrDevice(driver, vm,
6864                                         dev->data.chr);
6865         if (!ret) {
6866             alias = dev->data.chr->info.alias;
6867             dev->data.chr = NULL;
6868         }
6869         break;
6870 
6871     case VIR_DOMAIN_DEVICE_RNG:
6872         ret = qemuDomainAttachRNGDevice(driver, vm,
6873                                         dev->data.rng);
6874         if (!ret) {
6875             alias = dev->data.rng->info.alias;
6876             dev->data.rng = NULL;
6877         }
6878         break;
6879 
6880     case VIR_DOMAIN_DEVICE_MEMORY:
6881         /* note that qemuDomainAttachMemory always consumes dev->data.memory
6882          * and dispatches DeviceAdded event on success */
6883         ret = qemuDomainAttachMemory(driver, vm,
6884                                      dev->data.memory);
6885         dev->data.memory = NULL;
6886         break;
6887 
6888     case VIR_DOMAIN_DEVICE_SHMEM:
6889         ret = qemuDomainAttachShmemDevice(driver, vm,
6890                                           dev->data.shmem);
6891         if (!ret) {
6892             alias = dev->data.shmem->info.alias;
6893             dev->data.shmem = NULL;
6894         }
6895         break;
6896 
6897     case VIR_DOMAIN_DEVICE_WATCHDOG:
6898         ret = qemuDomainAttachWatchdog(driver, vm,
6899                                        dev->data.watchdog);
6900         if (!ret) {
6901             alias = dev->data.watchdog->info.alias;
6902             dev->data.watchdog = NULL;
6903         }
6904         break;
6905 
6906     case VIR_DOMAIN_DEVICE_INPUT:
6907         ret = qemuDomainAttachInputDevice(driver, vm, dev->data.input);
6908         if (ret == 0) {
6909             alias = dev->data.input->info.alias;
6910             dev->data.input = NULL;
6911         }
6912         break;
6913 
6914     case VIR_DOMAIN_DEVICE_VSOCK:
6915         ret = qemuDomainAttachVsockDevice(driver, vm, dev->data.vsock);
6916         if (ret == 0) {
6917             alias = dev->data.vsock->info.alias;
6918             dev->data.vsock = NULL;
6919         }
6920         break;
6921 
6922     case VIR_DOMAIN_DEVICE_FS:
6923         ret = qemuDomainAttachFSDevice(driver, vm, dev->data.fs);
6924         if (ret == 0) {
6925             alias = dev->data.fs->info.alias;
6926             dev->data.fs = NULL;
6927         }
6928         break;
6929 
6930     case VIR_DOMAIN_DEVICE_NONE:
6931     case VIR_DOMAIN_DEVICE_SOUND:
6932     case VIR_DOMAIN_DEVICE_VIDEO:
6933     case VIR_DOMAIN_DEVICE_GRAPHICS:
6934     case VIR_DOMAIN_DEVICE_HUB:
6935     case VIR_DOMAIN_DEVICE_SMARTCARD:
6936     case VIR_DOMAIN_DEVICE_MEMBALLOON:
6937     case VIR_DOMAIN_DEVICE_NVRAM:
6938     case VIR_DOMAIN_DEVICE_TPM:
6939     case VIR_DOMAIN_DEVICE_PANIC:
6940     case VIR_DOMAIN_DEVICE_IOMMU:
6941     case VIR_DOMAIN_DEVICE_AUDIO:
6942     case VIR_DOMAIN_DEVICE_LAST:
6943         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
6944                        _("live attach of device '%s' is not supported"),
6945                        virDomainDeviceTypeToString(dev->type));
6946         break;
6947     }
6948 
6949     if (alias) {
6950         /* queue the event before the alias has a chance to get freed
6951          * if the domain disappears while qemuDomainUpdateDeviceList
6952          * is in monitor */
6953         virObjectEvent *event;
6954         event = virDomainEventDeviceAddedNewFromObj(vm, alias);
6955         virObjectEventStateQueue(driver->domainEventState, event);
6956     }
6957 
6958     if (ret == 0)
6959         ret = qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE);
6960 
6961     return ret;
6962 }
6963 
6964 
6965 static int
qemuDomainChangeDiskLive(virDomainObj * vm,virDomainDeviceDef * dev,virQEMUDriver * driver,bool force)6966 qemuDomainChangeDiskLive(virDomainObj *vm,
6967                          virDomainDeviceDef *dev,
6968                          virQEMUDriver *driver,
6969                          bool force)
6970 {
6971     virDomainDiskDef *disk = dev->data.disk;
6972     virDomainDiskDef *orig_disk = NULL;
6973     virDomainStartupPolicy origStartupPolicy;
6974     virDomainDeviceDef oldDev = { .type = dev->type };
6975 
6976     if (!(orig_disk = virDomainDiskByTarget(vm->def, disk->dst))) {
6977         virReportError(VIR_ERR_INTERNAL_ERROR,
6978                        _("disk '%s' not found"), disk->dst);
6979         return -1;
6980     }
6981 
6982     oldDev.data.disk = orig_disk;
6983     origStartupPolicy = orig_disk->startupPolicy;
6984     if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
6985                                      VIR_DOMAIN_DEVICE_ACTION_UPDATE,
6986                                      true) < 0)
6987         return -1;
6988 
6989     if (!qemuDomainDiskChangeSupported(disk, orig_disk))
6990         return -1;
6991 
6992     if (!virStorageSourceIsSameLocation(disk->src, orig_disk->src)) {
6993         /* Disk source can be changed only for removable devices */
6994         if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
6995             disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
6996             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6997                            _("disk source can be changed only in removable "
6998                              "drives"));
6999             return -1;
7000         }
7001 
7002         /* update startup policy first before updating disk image */
7003         orig_disk->startupPolicy = dev->data.disk->startupPolicy;
7004 
7005         if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
7006                                            dev->data.disk->src, force) < 0) {
7007             /* revert startup policy before failing */
7008             orig_disk->startupPolicy = origStartupPolicy;
7009             return -1;
7010         }
7011 
7012         dev->data.disk->src = NULL;
7013     }
7014 
7015     /* in case when we aren't updating disk source we update startup policy here */
7016     orig_disk->startupPolicy = dev->data.disk->startupPolicy;
7017     orig_disk->snapshot = dev->data.disk->snapshot;
7018 
7019     return 0;
7020 }
7021 
7022 
7023 static bool
qemuDomainChangeMemoryLiveValidateChange(const virDomainMemoryDef * oldDef,const virDomainMemoryDef * newDef)7024 qemuDomainChangeMemoryLiveValidateChange(const virDomainMemoryDef *oldDef,
7025                                          const virDomainMemoryDef *newDef)
7026 {
7027     /* The only thing that is allowed to change is 'requestedsize' for
7028      * virtio-mem model. Check if user isn't trying to sneak in change for
7029      * something else. */
7030 
7031     switch (oldDef->model) {
7032     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
7033         break;
7034 
7035     case VIR_DOMAIN_MEMORY_MODEL_NONE:
7036     case VIR_DOMAIN_MEMORY_MODEL_DIMM:
7037     case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
7038     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
7039     case VIR_DOMAIN_MEMORY_MODEL_LAST:
7040         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7041                        _("cannot modify memory of model '%s'"),
7042                        virDomainMemoryModelTypeToString(oldDef->model));
7043         return false;
7044         break;
7045     }
7046 
7047     if (oldDef->model != newDef->model) {
7048         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7049                        _("cannot modify memory model from '%s' to '%s'"),
7050                        virDomainMemoryModelTypeToString(oldDef->model),
7051                        virDomainMemoryModelTypeToString(newDef->model));
7052         return false;
7053     }
7054 
7055     if (oldDef->access != newDef->access) {
7056         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7057                        _("cannot modify memory access from '%s' to '%s'"),
7058                        virDomainMemoryAccessTypeToString(oldDef->access),
7059                        virDomainMemoryAccessTypeToString(newDef->access));
7060         return false;
7061     }
7062 
7063     if (oldDef->discard != newDef->discard) {
7064         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7065                        _("cannot modify memory discard from '%s' to '%s'"),
7066                        virTristateBoolTypeToString(oldDef->discard),
7067                        virTristateBoolTypeToString(newDef->discard));
7068         return false;
7069     }
7070 
7071     if (!virBitmapEqual(oldDef->sourceNodes,
7072                         newDef->sourceNodes)) {
7073         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7074                        _("cannot modify memory source nodes"));
7075         return false;
7076     }
7077 
7078     if (oldDef->pagesize != newDef->pagesize) {
7079         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7080                        _("cannot modify memory pagesize from '%llu' to '%llu'"),
7081                        oldDef->pagesize,
7082                        newDef->pagesize);
7083         return false;
7084     }
7085 
7086     if (STRNEQ_NULLABLE(oldDef->nvdimmPath, newDef->nvdimmPath)) {
7087         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7088                        _("cannot modify memory path from '%s' to '%s'"),
7089                        NULLSTR(oldDef->nvdimmPath),
7090                        NULLSTR(newDef->nvdimmPath));
7091         return false;
7092     }
7093 
7094     if (oldDef->alignsize != newDef->alignsize) {
7095         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7096                        _("cannot modify memory align size from '%llu' to '%llu'"),
7097                        oldDef->alignsize, newDef->alignsize);
7098         return false;
7099     }
7100 
7101     if (oldDef->nvdimmPmem != newDef->nvdimmPmem) {
7102         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7103                        _("cannot modify memory pmem from '%d' to '%d'"),
7104                        oldDef->nvdimmPmem, newDef->nvdimmPmem);
7105         return false;
7106     }
7107 
7108     if (oldDef->targetNode != newDef->targetNode) {
7109         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7110                        _("cannot modify memory targetNode from '%d' to '%d'"),
7111                        oldDef->targetNode, newDef->targetNode);
7112         return false;
7113     }
7114 
7115     if (oldDef->size != newDef->size) {
7116         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7117                        _("cannot modify memory size from '%llu' to '%llu'"),
7118                        oldDef->size, newDef->size);
7119         return false;
7120     }
7121 
7122     if (oldDef->labelsize != newDef->labelsize) {
7123         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7124                        _("cannot modify memory label size from '%llu' to '%llu'"),
7125                        oldDef->labelsize, newDef->labelsize);
7126         return false;
7127     }
7128     if (oldDef->blocksize != newDef->blocksize) {
7129         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7130                        _("cannot modify memory block size from '%llu' to '%llu'"),
7131                        oldDef->blocksize, newDef->blocksize);
7132         return false;
7133     }
7134 
7135     /* requestedsize can change */
7136 
7137     if (oldDef->readonly != newDef->readonly) {
7138         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7139                        _("cannot modify memory pmem flag"));
7140         return false;
7141     }
7142 
7143     if ((oldDef->uuid || newDef->uuid) &&
7144         !(oldDef->uuid && newDef->uuid &&
7145           memcmp(oldDef->uuid, newDef->uuid, VIR_UUID_BUFLEN) == 0)) {
7146         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7147                        _("cannot modify memory UUID"));
7148         return false;
7149     }
7150 
7151     return true;
7152 }
7153 
7154 
7155 static int
qemuDomainChangeMemoryLive(virQEMUDriver * driver G_GNUC_UNUSED,virDomainObj * vm,virDomainDeviceDef * dev)7156 qemuDomainChangeMemoryLive(virQEMUDriver *driver G_GNUC_UNUSED,
7157                            virDomainObj *vm,
7158                            virDomainDeviceDef *dev)
7159 {
7160     virDomainDeviceDef oldDev = { .type = VIR_DOMAIN_DEVICE_MEMORY };
7161     virDomainMemoryDef *newDef = dev->data.memory;
7162     virDomainMemoryDef *oldDef = NULL;
7163 
7164     oldDef = virDomainMemoryFindByDeviceInfo(vm->def, &dev->data.memory->info, NULL);
7165     if (!oldDef) {
7166         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7167                        _("memory '%s' not found"), dev->data.memory->info.alias);
7168         return -1;
7169     }
7170 
7171     oldDev.data.memory = oldDef;
7172 
7173     if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
7174                                      VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7175                                      true) < 0)
7176         return -1;
7177 
7178     if (!qemuDomainChangeMemoryLiveValidateChange(oldDef, newDef))
7179         return -1;
7180 
7181     if (qemuDomainChangeMemoryRequestedSize(driver, vm,
7182                                             newDef->info.alias,
7183                                             newDef->requestedsize) < 0)
7184         return -1;
7185 
7186     oldDef->requestedsize = newDef->requestedsize;
7187     return 0;
7188 }
7189 
7190 
7191 static int
qemuDomainUpdateDeviceLive(virDomainObj * vm,virDomainDeviceDef * dev,virDomainPtr dom,bool force)7192 qemuDomainUpdateDeviceLive(virDomainObj *vm,
7193                            virDomainDeviceDef *dev,
7194                            virDomainPtr dom,
7195                            bool force)
7196 {
7197     virQEMUDriver *driver = dom->conn->privateData;
7198     virDomainDeviceDef oldDev = { .type = dev->type };
7199     int idx;
7200 
7201     switch ((virDomainDeviceType)dev->type) {
7202     case VIR_DOMAIN_DEVICE_DISK:
7203         qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
7204         return qemuDomainChangeDiskLive(vm, dev, driver, force);
7205 
7206     case VIR_DOMAIN_DEVICE_GRAPHICS:
7207         if ((idx = qemuDomainFindGraphicsIndex(vm->def, dev->data.graphics)) >= 0) {
7208             oldDev.data.graphics = vm->def->graphics[idx];
7209             if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
7210                                              VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7211                                              true) < 0)
7212                 return -1;
7213         }
7214 
7215         return qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
7216 
7217     case VIR_DOMAIN_DEVICE_NET:
7218         if ((idx = virDomainNetFindIdx(vm->def, dev->data.net)) >= 0) {
7219             oldDev.data.net = vm->def->nets[idx];
7220             if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
7221                                              VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7222                                              true) < 0)
7223                 return -1;
7224         }
7225 
7226         return qemuDomainChangeNet(driver, vm, dev);
7227 
7228     case VIR_DOMAIN_DEVICE_MEMORY:
7229         return qemuDomainChangeMemoryLive(driver, vm, dev);
7230 
7231     case VIR_DOMAIN_DEVICE_FS:
7232     case VIR_DOMAIN_DEVICE_INPUT:
7233     case VIR_DOMAIN_DEVICE_SOUND:
7234     case VIR_DOMAIN_DEVICE_VIDEO:
7235     case VIR_DOMAIN_DEVICE_WATCHDOG:
7236     case VIR_DOMAIN_DEVICE_HUB:
7237     case VIR_DOMAIN_DEVICE_SMARTCARD:
7238     case VIR_DOMAIN_DEVICE_MEMBALLOON:
7239     case VIR_DOMAIN_DEVICE_NVRAM:
7240     case VIR_DOMAIN_DEVICE_RNG:
7241     case VIR_DOMAIN_DEVICE_SHMEM:
7242     case VIR_DOMAIN_DEVICE_LEASE:
7243     case VIR_DOMAIN_DEVICE_HOSTDEV:
7244     case VIR_DOMAIN_DEVICE_CONTROLLER:
7245     case VIR_DOMAIN_DEVICE_REDIRDEV:
7246     case VIR_DOMAIN_DEVICE_CHR:
7247     case VIR_DOMAIN_DEVICE_NONE:
7248     case VIR_DOMAIN_DEVICE_TPM:
7249     case VIR_DOMAIN_DEVICE_PANIC:
7250     case VIR_DOMAIN_DEVICE_IOMMU:
7251     case VIR_DOMAIN_DEVICE_VSOCK:
7252     case VIR_DOMAIN_DEVICE_AUDIO:
7253     case VIR_DOMAIN_DEVICE_LAST:
7254         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7255                        _("live update of device '%s' is not supported"),
7256                        virDomainDeviceTypeToString(dev->type));
7257         return -1;
7258     }
7259 
7260     return -1;
7261 }
7262 
7263 
7264 static int
qemuCheckDiskConfigAgainstDomain(const virDomainDef * def,const virDomainDiskDef * disk)7265 qemuCheckDiskConfigAgainstDomain(const virDomainDef *def,
7266                                  const virDomainDiskDef *disk)
7267 {
7268     if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
7269         virDomainSCSIDriveAddressIsUsed(def, &disk->info.addr.drive)) {
7270         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7271                        _("Domain already contains a disk with that address"));
7272         return -1;
7273     }
7274 
7275     return 0;
7276 }
7277 
7278 
7279 static int
qemuDomainAttachDeviceConfig(virDomainDef * vmdef,virDomainDeviceDef * dev,virQEMUCaps * qemuCaps,unsigned int parse_flags,virDomainXMLOption * xmlopt)7280 qemuDomainAttachDeviceConfig(virDomainDef *vmdef,
7281                              virDomainDeviceDef *dev,
7282                              virQEMUCaps *qemuCaps,
7283                              unsigned int parse_flags,
7284                              virDomainXMLOption *xmlopt)
7285 {
7286     virDomainDiskDef *disk;
7287     virDomainNetDef *net;
7288     virDomainSoundDef *sound;
7289     virDomainHostdevDef *hostdev;
7290     virDomainLeaseDef *lease;
7291     virDomainControllerDef *controller;
7292     virDomainFSDef *fs;
7293     virDomainRedirdevDef *redirdev;
7294     virDomainShmemDef *shmem;
7295 
7296     switch ((virDomainDeviceType)dev->type) {
7297     case VIR_DOMAIN_DEVICE_DISK:
7298         disk = dev->data.disk;
7299         if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
7300             virReportError(VIR_ERR_OPERATION_INVALID,
7301                            _("target %s already exists"), disk->dst);
7302             return -1;
7303         }
7304         if (virDomainDiskTranslateSourcePool(disk) < 0)
7305             return -1;
7306         if (qemuCheckDiskConfigAgainstDomain(vmdef, disk) < 0)
7307             return -1;
7308         virDomainDiskInsert(vmdef, disk);
7309         /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
7310         dev->data.disk = NULL;
7311         break;
7312 
7313     case VIR_DOMAIN_DEVICE_NET:
7314         net = dev->data.net;
7315         if (virDomainNetInsert(vmdef, net))
7316             return -1;
7317         dev->data.net = NULL;
7318         break;
7319 
7320     case VIR_DOMAIN_DEVICE_SOUND:
7321         sound = dev->data.sound;
7322         VIR_APPEND_ELEMENT(vmdef->sounds, vmdef->nsounds, sound);
7323         dev->data.sound = NULL;
7324         break;
7325 
7326     case VIR_DOMAIN_DEVICE_HOSTDEV:
7327         hostdev = dev->data.hostdev;
7328         if (virDomainHostdevFind(vmdef, hostdev, NULL) >= 0) {
7329             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7330                            _("device is already in the domain configuration"));
7331             return -1;
7332         }
7333         if (virDomainHostdevInsert(vmdef, hostdev))
7334             return -1;
7335         dev->data.hostdev = NULL;
7336         break;
7337 
7338     case VIR_DOMAIN_DEVICE_LEASE:
7339         lease = dev->data.lease;
7340         if (virDomainLeaseIndex(vmdef, lease) >= 0) {
7341             virReportError(VIR_ERR_OPERATION_INVALID,
7342                            _("Lease %s in lockspace %s already exists"),
7343                            lease->key, NULLSTR(lease->lockspace));
7344             return -1;
7345         }
7346         virDomainLeaseInsert(vmdef, lease);
7347 
7348         /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
7349         dev->data.lease = NULL;
7350         break;
7351 
7352     case VIR_DOMAIN_DEVICE_CONTROLLER:
7353         controller = dev->data.controller;
7354         if (controller->idx != -1 &&
7355             virDomainControllerFind(vmdef, controller->type,
7356                                     controller->idx) >= 0) {
7357             virReportError(VIR_ERR_OPERATION_INVALID,
7358                            _("controller index='%d' already exists"),
7359                            controller->idx);
7360             return -1;
7361         }
7362 
7363         virDomainControllerInsert(vmdef, controller);
7364         dev->data.controller = NULL;
7365 
7366         break;
7367 
7368     case VIR_DOMAIN_DEVICE_CHR:
7369         if (qemuDomainChrInsert(vmdef, dev->data.chr) < 0)
7370             return -1;
7371         dev->data.chr = NULL;
7372         break;
7373 
7374     case VIR_DOMAIN_DEVICE_FS:
7375         fs = dev->data.fs;
7376         if (virDomainFSIndexByName(vmdef, fs->dst) >= 0) {
7377             virReportError(VIR_ERR_OPERATION_INVALID,
7378                          "%s", _("Target already exists"));
7379             return -1;
7380         }
7381 
7382         if (virDomainFSInsert(vmdef, fs) < 0)
7383             return -1;
7384         dev->data.fs = NULL;
7385         break;
7386 
7387     case VIR_DOMAIN_DEVICE_RNG:
7388         if (dev->data.rng->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
7389             virDomainDefHasDeviceAddress(vmdef, &dev->data.rng->info)) {
7390             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7391                            _("a device with the same address already exists "));
7392             return -1;
7393         }
7394 
7395         VIR_APPEND_ELEMENT(vmdef->rngs, vmdef->nrngs, dev->data.rng);
7396         break;
7397 
7398     case VIR_DOMAIN_DEVICE_MEMORY:
7399         if (vmdef->nmems == vmdef->mem.memory_slots) {
7400             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7401                            _("no free memory device slot available"));
7402             return -1;
7403         }
7404 
7405         vmdef->mem.cur_balloon += dev->data.memory->size;
7406 
7407         if (virDomainMemoryInsert(vmdef, dev->data.memory) < 0)
7408             return -1;
7409         dev->data.memory = NULL;
7410         break;
7411 
7412     case VIR_DOMAIN_DEVICE_REDIRDEV:
7413         redirdev = dev->data.redirdev;
7414 
7415         VIR_APPEND_ELEMENT(vmdef->redirdevs, vmdef->nredirdevs, redirdev);
7416         dev->data.redirdev = NULL;
7417         break;
7418 
7419     case VIR_DOMAIN_DEVICE_SHMEM:
7420         shmem = dev->data.shmem;
7421         if (virDomainShmemDefFind(vmdef, shmem) >= 0) {
7422             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7423                            _("device is already in the domain configuration"));
7424             return -1;
7425         }
7426         if (virDomainShmemDefInsert(vmdef, shmem) < 0)
7427             return -1;
7428         dev->data.shmem = NULL;
7429         break;
7430 
7431     case VIR_DOMAIN_DEVICE_WATCHDOG:
7432         if (vmdef->watchdog) {
7433             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7434                            _("domain already has a watchdog"));
7435             return -1;
7436         }
7437         vmdef->watchdog = g_steal_pointer(&dev->data.watchdog);
7438         break;
7439 
7440     case VIR_DOMAIN_DEVICE_INPUT:
7441         VIR_APPEND_ELEMENT(vmdef->inputs, vmdef->ninputs, dev->data.input);
7442         break;
7443 
7444     case VIR_DOMAIN_DEVICE_VSOCK:
7445         if (vmdef->vsock) {
7446             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7447                            _("domain already has a vsock device"));
7448             return -1;
7449         }
7450         vmdef->vsock = g_steal_pointer(&dev->data.vsock);
7451         break;
7452 
7453     case VIR_DOMAIN_DEVICE_VIDEO:
7454     case VIR_DOMAIN_DEVICE_GRAPHICS:
7455     case VIR_DOMAIN_DEVICE_HUB:
7456     case VIR_DOMAIN_DEVICE_SMARTCARD:
7457     case VIR_DOMAIN_DEVICE_MEMBALLOON:
7458     case VIR_DOMAIN_DEVICE_NVRAM:
7459     case VIR_DOMAIN_DEVICE_NONE:
7460     case VIR_DOMAIN_DEVICE_TPM:
7461     case VIR_DOMAIN_DEVICE_PANIC:
7462     case VIR_DOMAIN_DEVICE_IOMMU:
7463     case VIR_DOMAIN_DEVICE_AUDIO:
7464     case VIR_DOMAIN_DEVICE_LAST:
7465          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
7466                         _("persistent attach of device '%s' is not supported"),
7467                         virDomainDeviceTypeToString(dev->type));
7468          return -1;
7469     }
7470 
7471     if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, qemuCaps) < 0)
7472         return -1;
7473 
7474     return 0;
7475 }
7476 
7477 
7478 static int
qemuDomainDetachDeviceConfig(virDomainDef * vmdef,virDomainDeviceDef * dev,virQEMUCaps * qemuCaps,unsigned int parse_flags,virDomainXMLOption * xmlopt)7479 qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
7480                              virDomainDeviceDef *dev,
7481                              virQEMUCaps *qemuCaps,
7482                              unsigned int parse_flags,
7483                              virDomainXMLOption *xmlopt)
7484 {
7485     virDomainDiskDef *disk;
7486     virDomainDiskDef *det_disk;
7487     virDomainNetDef *net;
7488     virDomainSoundDef *sound;
7489     virDomainHostdevDef *hostdev;
7490     virDomainHostdevDef *det_hostdev;
7491     virDomainLeaseDef *lease;
7492     virDomainLeaseDef *det_lease;
7493     virDomainControllerDef *cont;
7494     virDomainControllerDef *det_cont;
7495     virDomainChrDef *chr;
7496     virDomainFSDef *fs;
7497     virDomainMemoryDef *mem;
7498     int idx;
7499 
7500     switch ((virDomainDeviceType)dev->type) {
7501     case VIR_DOMAIN_DEVICE_DISK:
7502         disk = dev->data.disk;
7503         if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
7504             virReportError(VIR_ERR_DEVICE_MISSING,
7505                            _("no target device %s"), disk->dst);
7506             return -1;
7507         }
7508         virDomainDiskDefFree(det_disk);
7509         break;
7510 
7511     case VIR_DOMAIN_DEVICE_NET:
7512         net = dev->data.net;
7513         if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
7514             return -1;
7515 
7516         /* this is guaranteed to succeed */
7517         virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
7518         break;
7519 
7520     case VIR_DOMAIN_DEVICE_SOUND:
7521         sound = dev->data.sound;
7522         if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
7523             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7524                            _("device not present in domain configuration"));
7525             return -1;
7526         }
7527         virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
7528         break;
7529 
7530     case VIR_DOMAIN_DEVICE_HOSTDEV: {
7531         hostdev = dev->data.hostdev;
7532         if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
7533             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7534                            _("device not present in domain configuration"));
7535             return -1;
7536         }
7537         virDomainHostdevRemove(vmdef, idx);
7538         virDomainHostdevDefFree(det_hostdev);
7539         break;
7540     }
7541 
7542     case VIR_DOMAIN_DEVICE_LEASE:
7543         lease = dev->data.lease;
7544         if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
7545             virReportError(VIR_ERR_DEVICE_MISSING,
7546                            _("Lease %s in lockspace %s does not exist"),
7547                            lease->key, NULLSTR(lease->lockspace));
7548             return -1;
7549         }
7550         virDomainLeaseDefFree(det_lease);
7551         break;
7552 
7553     case VIR_DOMAIN_DEVICE_CONTROLLER:
7554         cont = dev->data.controller;
7555         if ((idx = virDomainControllerFind(vmdef, cont->type,
7556                                            cont->idx)) < 0) {
7557             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7558                            _("device not present in domain configuration"));
7559             return -1;
7560         }
7561         det_cont = virDomainControllerRemove(vmdef, idx);
7562         virDomainControllerDefFree(det_cont);
7563 
7564         break;
7565 
7566     case VIR_DOMAIN_DEVICE_CHR:
7567         if (!(chr = qemuDomainChrRemove(vmdef, dev->data.chr)))
7568             return -1;
7569 
7570         virDomainChrDefFree(chr);
7571         break;
7572 
7573     case VIR_DOMAIN_DEVICE_FS:
7574         fs = dev->data.fs;
7575         idx = virDomainFSIndexByName(vmdef, fs->dst);
7576         if (idx < 0) {
7577             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7578                            _("no matching filesystem device was found"));
7579             return -1;
7580         }
7581 
7582         fs = virDomainFSRemove(vmdef, idx);
7583         virDomainFSDefFree(fs);
7584         break;
7585 
7586     case VIR_DOMAIN_DEVICE_RNG:
7587         if ((idx = virDomainRNGFind(vmdef, dev->data.rng)) < 0) {
7588             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7589                            _("no matching RNG device was found"));
7590             return -1;
7591         }
7592 
7593         virDomainRNGDefFree(virDomainRNGRemove(vmdef, idx));
7594         break;
7595 
7596     case VIR_DOMAIN_DEVICE_MEMORY:
7597         if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
7598                                                     dev->data.memory)) < 0) {
7599             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7600                            _("matching memory device was not found"));
7601             return -1;
7602         }
7603         mem = virDomainMemoryRemove(vmdef, idx);
7604         vmdef->mem.cur_balloon -= mem->size;
7605         virDomainMemoryDefFree(mem);
7606         break;
7607 
7608     case VIR_DOMAIN_DEVICE_REDIRDEV:
7609         if ((idx = virDomainRedirdevDefFind(vmdef,
7610                                             dev->data.redirdev)) < 0) {
7611             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7612                            _("no matching redirdev was not found"));
7613             return -1;
7614         }
7615 
7616         virDomainRedirdevDefFree(virDomainRedirdevDefRemove(vmdef, idx));
7617         break;
7618 
7619     case VIR_DOMAIN_DEVICE_SHMEM:
7620         if ((idx = virDomainShmemDefFind(vmdef, dev->data.shmem)) < 0) {
7621             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7622                            _("matching shmem device was not found"));
7623             return -1;
7624         }
7625 
7626         virDomainShmemDefFree(virDomainShmemDefRemove(vmdef, idx));
7627         break;
7628 
7629 
7630     case VIR_DOMAIN_DEVICE_WATCHDOG:
7631         if (!vmdef->watchdog) {
7632             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7633                            _("domain has no watchdog"));
7634             return -1;
7635         }
7636         virDomainWatchdogDefFree(vmdef->watchdog);
7637         vmdef->watchdog = NULL;
7638         break;
7639 
7640     case VIR_DOMAIN_DEVICE_INPUT:
7641         if ((idx = virDomainInputDefFind(vmdef, dev->data.input)) < 0) {
7642             virReportError(VIR_ERR_DEVICE_MISSING, "%s",
7643                            _("matching input device not found"));
7644             return -1;
7645         }
7646         VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
7647         break;
7648 
7649     case VIR_DOMAIN_DEVICE_VSOCK:
7650         if (!vmdef->vsock ||
7651             !virDomainVsockDefEquals(dev->data.vsock, vmdef->vsock)) {
7652             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
7653                            _("matching vsock device not found"));
7654             return -1;
7655         }
7656         virDomainVsockDefFree(vmdef->vsock);
7657         vmdef->vsock = NULL;
7658         break;
7659 
7660     case VIR_DOMAIN_DEVICE_VIDEO:
7661     case VIR_DOMAIN_DEVICE_GRAPHICS:
7662     case VIR_DOMAIN_DEVICE_HUB:
7663     case VIR_DOMAIN_DEVICE_SMARTCARD:
7664     case VIR_DOMAIN_DEVICE_MEMBALLOON:
7665     case VIR_DOMAIN_DEVICE_NVRAM:
7666     case VIR_DOMAIN_DEVICE_NONE:
7667     case VIR_DOMAIN_DEVICE_TPM:
7668     case VIR_DOMAIN_DEVICE_PANIC:
7669     case VIR_DOMAIN_DEVICE_IOMMU:
7670     case VIR_DOMAIN_DEVICE_AUDIO:
7671     case VIR_DOMAIN_DEVICE_LAST:
7672         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
7673                        _("persistent detach of device '%s' is not supported"),
7674                        virDomainDeviceTypeToString(dev->type));
7675         return -1;
7676     }
7677 
7678     if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, qemuCaps) < 0)
7679         return -1;
7680 
7681     return 0;
7682 }
7683 
7684 static int
qemuDomainUpdateDeviceConfig(virDomainDef * vmdef,virDomainDeviceDef * dev,virQEMUCaps * qemuCaps,unsigned int parse_flags,virDomainXMLOption * xmlopt)7685 qemuDomainUpdateDeviceConfig(virDomainDef *vmdef,
7686                              virDomainDeviceDef *dev,
7687                              virQEMUCaps *qemuCaps,
7688                              unsigned int parse_flags,
7689                              virDomainXMLOption *xmlopt)
7690 {
7691     virDomainDiskDef *newDisk;
7692     virDomainGraphicsDef *newGraphics;
7693     virDomainNetDef *net;
7694     virDomainMemoryDef *mem;
7695     virDomainDeviceDef oldDev = { .type = dev->type };
7696     int pos;
7697 
7698     switch ((virDomainDeviceType)dev->type) {
7699     case VIR_DOMAIN_DEVICE_DISK:
7700         newDisk = dev->data.disk;
7701         if ((pos = virDomainDiskIndexByName(vmdef, newDisk->dst, false)) < 0) {
7702             virReportError(VIR_ERR_INVALID_ARG,
7703                            _("target %s doesn't exist."), newDisk->dst);
7704             return -1;
7705         }
7706 
7707         oldDev.data.disk = vmdef->disks[pos];
7708         if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
7709                                          VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7710                                          false) < 0)
7711             return -1;
7712 
7713         virDomainDiskDefFree(vmdef->disks[pos]);
7714         vmdef->disks[pos] = newDisk;
7715         dev->data.disk = NULL;
7716         break;
7717 
7718     case VIR_DOMAIN_DEVICE_GRAPHICS:
7719         newGraphics = dev->data.graphics;
7720         pos = qemuDomainFindGraphicsIndex(vmdef, newGraphics);
7721         if (pos < 0) {
7722             virReportError(VIR_ERR_INVALID_ARG,
7723                            _("cannot find existing graphics type '%s' device to modify"),
7724                            virDomainGraphicsTypeToString(newGraphics->type));
7725             return -1;
7726         }
7727 
7728         oldDev.data.graphics = vmdef->graphics[pos];
7729         if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
7730                                          VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7731                                          false) < 0)
7732             return -1;
7733 
7734         virDomainGraphicsDefFree(vmdef->graphics[pos]);
7735         vmdef->graphics[pos] = newGraphics;
7736         dev->data.graphics = NULL;
7737         break;
7738 
7739     case VIR_DOMAIN_DEVICE_NET:
7740         net = dev->data.net;
7741         if ((pos = virDomainNetFindIdx(vmdef, net)) < 0)
7742             return -1;
7743 
7744         oldDev.data.net = vmdef->nets[pos];
7745         if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
7746                                          VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7747                                          false) < 0)
7748             return -1;
7749 
7750         if (virDomainNetUpdate(vmdef, pos, net))
7751             return -1;
7752 
7753         virDomainNetDefFree(oldDev.data.net);
7754         dev->data.net = NULL;
7755         break;
7756 
7757     case VIR_DOMAIN_DEVICE_MEMORY:
7758         mem = virDomainMemoryFindByDeviceInfo(vmdef, &dev->data.memory->info, &pos);
7759         if (!mem) {
7760             virReportError(VIR_ERR_INVALID_ARG, "%s", _("memory not found"));
7761             return -1;
7762         }
7763 
7764         oldDev.data.memory = mem;
7765         if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
7766                                          VIR_DOMAIN_DEVICE_ACTION_UPDATE,
7767                                          false) < 0)
7768             return -1;
7769 
7770         virDomainMemoryDefFree(vmdef->mems[pos]);
7771         vmdef->mems[pos] = g_steal_pointer(&dev->data.memory);
7772         break;
7773 
7774     case VIR_DOMAIN_DEVICE_FS:
7775     case VIR_DOMAIN_DEVICE_INPUT:
7776     case VIR_DOMAIN_DEVICE_SOUND:
7777     case VIR_DOMAIN_DEVICE_VIDEO:
7778     case VIR_DOMAIN_DEVICE_WATCHDOG:
7779     case VIR_DOMAIN_DEVICE_HUB:
7780     case VIR_DOMAIN_DEVICE_SMARTCARD:
7781     case VIR_DOMAIN_DEVICE_MEMBALLOON:
7782     case VIR_DOMAIN_DEVICE_NVRAM:
7783     case VIR_DOMAIN_DEVICE_RNG:
7784     case VIR_DOMAIN_DEVICE_SHMEM:
7785     case VIR_DOMAIN_DEVICE_LEASE:
7786     case VIR_DOMAIN_DEVICE_HOSTDEV:
7787     case VIR_DOMAIN_DEVICE_CONTROLLER:
7788     case VIR_DOMAIN_DEVICE_REDIRDEV:
7789     case VIR_DOMAIN_DEVICE_CHR:
7790     case VIR_DOMAIN_DEVICE_NONE:
7791     case VIR_DOMAIN_DEVICE_TPM:
7792     case VIR_DOMAIN_DEVICE_PANIC:
7793     case VIR_DOMAIN_DEVICE_IOMMU:
7794     case VIR_DOMAIN_DEVICE_VSOCK:
7795     case VIR_DOMAIN_DEVICE_AUDIO:
7796     case VIR_DOMAIN_DEVICE_LAST:
7797         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
7798                        _("persistent update of device '%s' is not supported"),
7799                        virDomainDeviceTypeToString(dev->type));
7800         return -1;
7801     }
7802 
7803     if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, qemuCaps) < 0)
7804         return -1;
7805 
7806     return 0;
7807 }
7808 
7809 
7810 static void
qemuDomainAttachDeviceLiveAndConfigHomogenize(const virDomainDeviceDef * devConf,virDomainDeviceDef * devLive)7811 qemuDomainAttachDeviceLiveAndConfigHomogenize(const virDomainDeviceDef *devConf,
7812                                               virDomainDeviceDef *devLive)
7813 {
7814     /*
7815      * Fixup anything that needs to be identical in the live and
7816      * config versions of DeviceDef, but might not be. Do this by
7817      * changing the contents of devLive. This is done after all
7818      * post-parse tweaks and validation, so be very careful about what
7819      * changes are made. (For example, it would be a very bad idea to
7820      * change assigned PCI, scsi, or sata addresses, as it could lead
7821      * to a conflict and there would be nothing to catch it except
7822      * qemu itself!)
7823      */
7824 
7825     /* MAC address should be identical in both DeviceDefs, but if it
7826      * wasn't specified in the XML, and was instead autogenerated, it
7827      * will be different for the two since they are each the result of
7828      * a separate parser call. If it *was* specified, it will already
7829      * be the same, so copying does no harm.
7830      */
7831 
7832     if (devConf->type == VIR_DOMAIN_DEVICE_NET)
7833         virMacAddrSet(&devLive->data.net->mac, &devConf->data.net->mac);
7834 
7835 }
7836 
7837 
7838 static int
qemuDomainAttachDeviceLiveAndConfig(virDomainObj * vm,virQEMUDriver * driver,const char * xml,unsigned int flags)7839 qemuDomainAttachDeviceLiveAndConfig(virDomainObj *vm,
7840                                     virQEMUDriver *driver,
7841                                     const char *xml,
7842                                     unsigned int flags)
7843 {
7844     qemuDomainObjPrivate *priv = vm->privateData;
7845     g_autoptr(virDomainDef) vmdef = NULL;
7846     g_autoptr(virQEMUDriverConfig) cfg = NULL;
7847     g_autoptr(virDomainDeviceDef) devConf = NULL;
7848     virDomainDeviceDef devConfSave = { 0 };
7849     g_autoptr(virDomainDeviceDef) devLive = NULL;
7850     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
7851                                VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
7852 
7853     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
7854                   VIR_DOMAIN_AFFECT_CONFIG, -1);
7855 
7856     cfg = virQEMUDriverGetConfig(driver);
7857 
7858     /* The config and live post processing address auto-generation algorithms
7859      * rely on the correct vm->def or vm->newDef being passed, so call the
7860      * device parse based on which definition is in use */
7861     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7862         vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt,
7863                                               priv->qemuCaps);
7864         if (!vmdef)
7865             return -1;
7866 
7867         if (!(devConf = virDomainDeviceDefParse(xml, vmdef,
7868                                                 driver->xmlopt, priv->qemuCaps,
7869                                                 parse_flags)))
7870             return -1;
7871 
7872         /*
7873          * devConf will be NULLed out by
7874          * qemuDomainAttachDeviceConfig(), so save it for later use by
7875          * qemuDomainAttachDeviceLiveAndConfigHomogenize()
7876          */
7877         devConfSave = *devConf;
7878 
7879         if (virDomainDeviceValidateAliasForHotplug(vm, devConf,
7880                                                    VIR_DOMAIN_AFFECT_CONFIG) < 0)
7881             return -1;
7882 
7883         if (virDomainDefCompatibleDevice(vmdef, devConf, NULL,
7884                                          VIR_DOMAIN_DEVICE_ACTION_ATTACH,
7885                                          false) < 0)
7886             return -1;
7887 
7888         if (qemuDomainAttachDeviceConfig(vmdef, devConf, priv->qemuCaps,
7889                                          parse_flags,
7890                                          driver->xmlopt) < 0)
7891             return -1;
7892     }
7893 
7894     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7895         if (!(devLive = virDomainDeviceDefParse(xml, vm->def,
7896                                                 driver->xmlopt, priv->qemuCaps,
7897                                                 parse_flags)))
7898             return -1;
7899 
7900         if (flags & VIR_DOMAIN_AFFECT_CONFIG)
7901             qemuDomainAttachDeviceLiveAndConfigHomogenize(&devConfSave, devLive);
7902 
7903         if (virDomainDeviceValidateAliasForHotplug(vm, devLive,
7904                                                    VIR_DOMAIN_AFFECT_LIVE) < 0)
7905             return -1;
7906 
7907         if (virDomainDefCompatibleDevice(vm->def, devLive, NULL,
7908                                          VIR_DOMAIN_DEVICE_ACTION_ATTACH,
7909                                          true) < 0)
7910             return -1;
7911 
7912         if (qemuDomainAttachDeviceLive(vm, devLive, driver) < 0)
7913             return -1;
7914         /*
7915          * update domain status forcibly because the domain status may be
7916          * changed even if we failed to attach the device. For example,
7917          * a new controller may be created.
7918          */
7919         qemuDomainSaveStatus(vm);
7920     }
7921 
7922     /* Finally, if no error until here, we can save config. */
7923     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7924         if (virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir) < 0)
7925             return -1;
7926 
7927         virDomainObjAssignDef(vm, &vmdef, false, NULL);
7928     }
7929 
7930     return 0;
7931 }
7932 
7933 static int
qemuDomainAttachDeviceFlags(virDomainPtr dom,const char * xml,unsigned int flags)7934 qemuDomainAttachDeviceFlags(virDomainPtr dom,
7935                             const char *xml,
7936                             unsigned int flags)
7937 {
7938     virQEMUDriver *driver = dom->conn->privateData;
7939     virDomainObj *vm = NULL;
7940     int ret = -1;
7941 
7942     virNWFilterReadLockFilterUpdates();
7943 
7944     if (!(vm = qemuDomainObjFromDomain(dom)))
7945         goto cleanup;
7946 
7947     if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
7948         goto cleanup;
7949 
7950     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
7951         goto cleanup;
7952 
7953     if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
7954         goto endjob;
7955 
7956     if (qemuDomainAttachDeviceLiveAndConfig(vm, driver, xml, flags) < 0)
7957         goto endjob;
7958 
7959     ret = 0;
7960 
7961  endjob:
7962     qemuDomainObjEndJob(driver, vm);
7963 
7964  cleanup:
7965     virDomainObjEndAPI(&vm);
7966     virNWFilterUnlockFilterUpdates();
7967     return ret;
7968 }
7969 
qemuDomainAttachDevice(virDomainPtr dom,const char * xml)7970 static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml)
7971 {
7972     return qemuDomainAttachDeviceFlags(dom, xml,
7973                                        VIR_DOMAIN_AFFECT_LIVE);
7974 }
7975 
7976 
qemuDomainUpdateDeviceFlags(virDomainPtr dom,const char * xml,unsigned int flags)7977 static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
7978                                        const char *xml,
7979                                        unsigned int flags)
7980 {
7981     virQEMUDriver *driver = dom->conn->privateData;
7982     virDomainObj *vm = NULL;
7983     qemuDomainObjPrivate *priv;
7984     g_autoptr(virDomainDef) vmdef = NULL;
7985     g_autoptr(virDomainDeviceDef) dev = NULL;
7986     virDomainDeviceDef *dev_copy = NULL;
7987     bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
7988     int ret = -1;
7989     g_autoptr(virQEMUDriverConfig) cfg = NULL;
7990     unsigned int parse_flags = 0;
7991 
7992     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
7993                   VIR_DOMAIN_AFFECT_CONFIG |
7994                   VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1);
7995 
7996     virNWFilterReadLockFilterUpdates();
7997 
7998     cfg = virQEMUDriverGetConfig(driver);
7999 
8000     if (!(vm = qemuDomainObjFromDomain(dom)))
8001         goto cleanup;
8002 
8003     priv = vm->privateData;
8004 
8005     if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
8006         goto cleanup;
8007 
8008     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8009         goto cleanup;
8010 
8011     if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
8012         goto endjob;
8013 
8014     if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
8015         !(flags & VIR_DOMAIN_AFFECT_LIVE))
8016         parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
8017 
8018     dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
8019                                              driver->xmlopt, priv->qemuCaps,
8020                                              parse_flags);
8021     if (dev == NULL)
8022         goto endjob;
8023 
8024     if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
8025         flags & VIR_DOMAIN_AFFECT_LIVE) {
8026         /* If we are affecting both CONFIG and LIVE
8027          * create a deep copy of device as adding
8028          * to CONFIG takes one instance.
8029          */
8030         dev_copy = virDomainDeviceDefCopy(dev, vm->def,
8031                                           driver->xmlopt, priv->qemuCaps);
8032         if (!dev_copy)
8033             goto endjob;
8034     }
8035 
8036     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8037         /* Make a copy for updated domain. */
8038         vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt,
8039                                               priv->qemuCaps);
8040         if (!vmdef)
8041             goto endjob;
8042 
8043         /* virDomainDefCompatibleDevice call is delayed until we know the
8044          * device we're going to update. */
8045         if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, priv->qemuCaps,
8046                                                 parse_flags,
8047                                                 driver->xmlopt)) < 0)
8048             goto endjob;
8049     }
8050 
8051     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
8052         /* virDomainDefCompatibleDevice call is delayed until we know the
8053          * device we're going to update. */
8054         if ((ret = qemuDomainUpdateDeviceLive(vm, dev_copy, dom, force)) < 0)
8055             goto endjob;
8056 
8057         qemuDomainSaveStatus(vm);
8058     }
8059 
8060     /* Finally, if no error until here, we can save config. */
8061     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8062         ret = virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir);
8063         if (!ret)
8064             virDomainObjAssignDef(vm, &vmdef, false, NULL);
8065     }
8066 
8067  endjob:
8068     qemuDomainObjEndJob(driver, vm);
8069 
8070  cleanup:
8071     if (dev != dev_copy)
8072         virDomainDeviceDefFree(dev_copy);
8073     virDomainObjEndAPI(&vm);
8074     virNWFilterUnlockFilterUpdates();
8075     return ret;
8076 }
8077 
8078 static int
qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver * driver,virDomainObj * vm,const char * xml,unsigned int flags)8079 qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
8080                                     virDomainObj *vm,
8081                                     const char *xml,
8082                                     unsigned int flags)
8083 {
8084     qemuDomainObjPrivate *priv = vm->privateData;
8085     g_autoptr(virQEMUDriverConfig) cfg = NULL;
8086     g_autoptr(virDomainDeviceDef) dev = NULL;
8087     virDomainDeviceDef *dev_copy = NULL;
8088     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
8089     g_autoptr(virDomainDef) vmdef = NULL;
8090     int ret = -1;
8091 
8092     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8093                   VIR_DOMAIN_AFFECT_CONFIG, -1);
8094 
8095     cfg = virQEMUDriverGetConfig(driver);
8096 
8097     if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
8098         !(flags & VIR_DOMAIN_AFFECT_LIVE))
8099         parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
8100 
8101     dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
8102                                              driver->xmlopt, priv->qemuCaps,
8103                                              parse_flags);
8104     if (dev == NULL)
8105         goto cleanup;
8106 
8107     if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
8108         flags & VIR_DOMAIN_AFFECT_LIVE) {
8109         /* If we are affecting both CONFIG and LIVE
8110          * create a deep copy of device as adding
8111          * to CONFIG takes one instance.
8112          */
8113         dev_copy = virDomainDeviceDefCopy(dev, vm->def,
8114                                           driver->xmlopt, priv->qemuCaps);
8115         if (!dev_copy)
8116             goto cleanup;
8117     }
8118 
8119     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8120         /* Make a copy for updated domain. */
8121         vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt, priv->qemuCaps);
8122         if (!vmdef)
8123             goto cleanup;
8124 
8125         if (qemuDomainDetachDeviceConfig(vmdef, dev, priv->qemuCaps,
8126                                          parse_flags,
8127                                          driver->xmlopt) < 0)
8128             goto cleanup;
8129     }
8130 
8131     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
8132         int rc;
8133 
8134         if ((rc = qemuDomainDetachDeviceLive(vm, dev_copy, driver, false)) < 0)
8135             goto cleanup;
8136 
8137         if (rc == 0 && qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
8138             goto cleanup;
8139 
8140         qemuDomainSaveStatus(vm);
8141     }
8142 
8143     /* Finally, if no error until here, we can save config. */
8144     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8145         if (virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir) < 0)
8146             goto cleanup;
8147 
8148         virDomainObjAssignDef(vm, &vmdef, false, NULL);
8149     }
8150 
8151     ret = 0;
8152 
8153  cleanup:
8154     if (dev != dev_copy)
8155         virDomainDeviceDefFree(dev_copy);
8156     return ret;
8157 }
8158 
8159 
8160 static int
qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriver * driver,virDomainObj * vm,const char * alias,unsigned int flags)8161 qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriver *driver,
8162                                          virDomainObj *vm,
8163                                          const char *alias,
8164                                          unsigned int flags)
8165 {
8166     qemuDomainObjPrivate *priv = vm->privateData;
8167     g_autoptr(virQEMUDriverConfig) cfg = NULL;
8168     virDomainDef *def = NULL;
8169     virDomainDef *persistentDef = NULL;
8170     g_autoptr(virDomainDef) vmdef = NULL;
8171     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
8172 
8173     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8174                   VIR_DOMAIN_AFFECT_CONFIG, -1);
8175 
8176     cfg = virQEMUDriverGetConfig(driver);
8177 
8178     if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
8179         !(flags & VIR_DOMAIN_AFFECT_LIVE))
8180         parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
8181 
8182     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
8183         return -1;
8184 
8185     if (persistentDef) {
8186         virDomainDeviceDef dev;
8187 
8188         if (!(vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt,
8189                                                     priv->qemuCaps)))
8190             return -1;
8191 
8192         if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0)
8193             return -1;
8194 
8195         if (qemuDomainDetachDeviceConfig(vmdef, &dev, priv->qemuCaps,
8196                                          parse_flags, driver->xmlopt) < 0)
8197             return -1;
8198     }
8199 
8200     if (def) {
8201         virDomainDeviceDef dev;
8202         int rc;
8203 
8204         if (virDomainDefFindDevice(def, alias, &dev, true) < 0)
8205             return -1;
8206 
8207         if ((rc = qemuDomainDetachDeviceLive(vm, &dev, driver, true)) < 0)
8208             return -1;
8209 
8210         if (rc == 0 && qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
8211             return -1;
8212     }
8213 
8214     if (vmdef) {
8215         if (virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir) < 0)
8216             return -1;
8217         virDomainObjAssignDef(vm, &vmdef, false, NULL);
8218     }
8219 
8220     return 0;
8221 }
8222 
8223 
8224 static int
qemuDomainDetachDeviceFlags(virDomainPtr dom,const char * xml,unsigned int flags)8225 qemuDomainDetachDeviceFlags(virDomainPtr dom,
8226                             const char *xml,
8227                             unsigned int flags)
8228 {
8229     virQEMUDriver *driver = dom->conn->privateData;
8230     virDomainObj *vm = NULL;
8231     int ret = -1;
8232 
8233     if (!(vm = qemuDomainObjFromDomain(dom)))
8234         goto cleanup;
8235 
8236     if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
8237         goto cleanup;
8238 
8239     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8240         goto cleanup;
8241 
8242     if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
8243         goto endjob;
8244 
8245     if (qemuDomainDetachDeviceLiveAndConfig(driver, vm, xml, flags) < 0)
8246         goto endjob;
8247 
8248     ret = 0;
8249 
8250  endjob:
8251     qemuDomainObjEndJob(driver, vm);
8252 
8253  cleanup:
8254     virDomainObjEndAPI(&vm);
8255     return ret;
8256 }
8257 
8258 
8259 static int
qemuDomainDetachDeviceAlias(virDomainPtr dom,const char * alias,unsigned int flags)8260 qemuDomainDetachDeviceAlias(virDomainPtr dom,
8261                             const char *alias,
8262                             unsigned int flags)
8263 {
8264     virQEMUDriver *driver = dom->conn->privateData;
8265     virDomainObj *vm = NULL;
8266     int ret = -1;
8267 
8268     if (!(vm = qemuDomainObjFromDomain(dom)))
8269         goto cleanup;
8270 
8271     if (virDomainDetachDeviceAliasEnsureACL(dom->conn, vm->def, flags) < 0)
8272         goto cleanup;
8273 
8274     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8275         goto cleanup;
8276 
8277     if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
8278         goto endjob;
8279 
8280     if (qemuDomainDetachDeviceAliasLiveAndConfig(driver, vm, alias, flags) < 0)
8281         goto endjob;
8282 
8283     ret = 0;
8284 
8285  endjob:
8286     qemuDomainObjEndJob(driver, vm);
8287 
8288  cleanup:
8289     virDomainObjEndAPI(&vm);
8290     return ret;
8291 }
8292 
8293 
qemuDomainDetachDevice(virDomainPtr dom,const char * xml)8294 static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml)
8295 {
8296     return qemuDomainDetachDeviceFlags(dom, xml,
8297                                        VIR_DOMAIN_AFFECT_LIVE);
8298 }
8299 
qemuDomainGetAutostart(virDomainPtr dom,int * autostart)8300 static int qemuDomainGetAutostart(virDomainPtr dom,
8301                                   int *autostart)
8302 {
8303     virDomainObj *vm;
8304     int ret = -1;
8305 
8306     if (!(vm = qemuDomainObjFromDomain(dom)))
8307         goto cleanup;
8308 
8309     if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
8310         goto cleanup;
8311 
8312     *autostart = vm->autostart;
8313     ret = 0;
8314 
8315  cleanup:
8316     virDomainObjEndAPI(&vm);
8317     return ret;
8318 }
8319 
qemuDomainSetAutostart(virDomainPtr dom,int autostart)8320 static int qemuDomainSetAutostart(virDomainPtr dom,
8321                                   int autostart)
8322 {
8323     virQEMUDriver *driver = dom->conn->privateData;
8324     virDomainObj *vm;
8325     g_autofree char *configFile = NULL;
8326     g_autofree char *autostartLink = NULL;
8327     int ret = -1;
8328     g_autoptr(virQEMUDriverConfig) cfg = NULL;
8329 
8330     if (!(vm = qemuDomainObjFromDomain(dom)))
8331         return -1;
8332 
8333     cfg = virQEMUDriverGetConfig(driver);
8334 
8335     if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
8336         goto cleanup;
8337 
8338     if (!vm->persistent) {
8339         virReportError(VIR_ERR_OPERATION_INVALID,
8340                        "%s", _("cannot set autostart for transient domain"));
8341         goto cleanup;
8342     }
8343 
8344     autostart = (autostart != 0);
8345 
8346     if (vm->autostart != autostart) {
8347         if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8348             goto cleanup;
8349 
8350         if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
8351             goto endjob;
8352 
8353         if (!(autostartLink = virDomainConfigFile(cfg->autostartDir,
8354                                                   vm->def->name)))
8355             goto endjob;
8356 
8357         if (autostart) {
8358             if (g_mkdir_with_parents(cfg->autostartDir, 0777) < 0) {
8359                 virReportSystemError(errno,
8360                                      _("cannot create autostart directory %s"),
8361                                      cfg->autostartDir);
8362                 goto endjob;
8363             }
8364 
8365             if (symlink(configFile, autostartLink) < 0) {
8366                 virReportSystemError(errno,
8367                                      _("Failed to create symlink '%s to '%s'"),
8368                                      autostartLink, configFile);
8369                 goto endjob;
8370             }
8371         } else {
8372             if (unlink(autostartLink) < 0 &&
8373                 errno != ENOENT &&
8374                 errno != ENOTDIR) {
8375                 virReportSystemError(errno,
8376                                      _("Failed to delete symlink '%s'"),
8377                                      autostartLink);
8378                 goto endjob;
8379             }
8380         }
8381 
8382         vm->autostart = autostart;
8383 
8384  endjob:
8385         qemuDomainObjEndJob(driver, vm);
8386     }
8387     ret = 0;
8388 
8389  cleanup:
8390     virDomainObjEndAPI(&vm);
8391     return ret;
8392 }
8393 
8394 
qemuDomainGetSchedulerType(virDomainPtr dom,int * nparams)8395 static char *qemuDomainGetSchedulerType(virDomainPtr dom,
8396                                         int *nparams)
8397 {
8398     char *ret = NULL;
8399     virDomainObj *vm = NULL;
8400     qemuDomainObjPrivate *priv;
8401     virQEMUDriver *driver = dom->conn->privateData;
8402 
8403     if (!(vm = qemuDomainObjFromDomain(dom)))
8404         goto cleanup;
8405 
8406     priv = vm->privateData;
8407 
8408     if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
8409         goto cleanup;
8410 
8411     if (!driver->privileged) {
8412         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
8413                        _("CPU tuning is not available in session mode"));
8414         goto cleanup;
8415     }
8416 
8417     /* Domain not running, thus no cgroups - return defaults */
8418     if (!virDomainObjIsActive(vm)) {
8419         if (nparams)
8420             *nparams = 9;
8421         ret = g_strdup("posix");
8422         goto cleanup;
8423     }
8424 
8425     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
8426         virReportError(VIR_ERR_OPERATION_INVALID,
8427                        "%s", _("cgroup CPU controller is not mounted"));
8428         goto cleanup;
8429     }
8430 
8431     if (nparams) {
8432         if (virCgroupSupportsCpuBW(priv->cgroup))
8433             *nparams = 9;
8434         else
8435             *nparams = 1;
8436     }
8437 
8438     ret = g_strdup("posix");
8439 
8440  cleanup:
8441     virDomainObjEndAPI(&vm);
8442     return ret;
8443 }
8444 
8445 
8446 static int
qemuDomainSetBlkioParameters(virDomainPtr dom,virTypedParameterPtr params,int nparams,unsigned int flags)8447 qemuDomainSetBlkioParameters(virDomainPtr dom,
8448                              virTypedParameterPtr params,
8449                              int nparams,
8450                              unsigned int flags)
8451 {
8452     virQEMUDriver *driver = dom->conn->privateData;
8453     virDomainObj *vm = NULL;
8454     virDomainDef *def;
8455     virDomainDef *persistentDef;
8456     int ret = -1;
8457     g_autoptr(virQEMUDriverConfig) cfg = NULL;
8458     qemuDomainObjPrivate *priv;
8459 
8460     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8461                   VIR_DOMAIN_AFFECT_CONFIG, -1);
8462     if (virTypedParamsValidate(params, nparams,
8463                                VIR_DOMAIN_BLKIO_WEIGHT,
8464                                VIR_TYPED_PARAM_UINT,
8465                                VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
8466                                VIR_TYPED_PARAM_STRING,
8467                                VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS,
8468                                VIR_TYPED_PARAM_STRING,
8469                                VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS,
8470                                VIR_TYPED_PARAM_STRING,
8471                                VIR_DOMAIN_BLKIO_DEVICE_READ_BPS,
8472                                VIR_TYPED_PARAM_STRING,
8473                                VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS,
8474                                VIR_TYPED_PARAM_STRING,
8475                                NULL) < 0)
8476         return -1;
8477 
8478     if (!(vm = qemuDomainObjFromDomain(dom)))
8479         return -1;
8480 
8481     priv = vm->privateData;
8482     cfg = virQEMUDriverGetConfig(driver);
8483 
8484     if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0)
8485         goto cleanup;
8486 
8487     if (!driver->privileged) {
8488         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8489                        _("Block I/O tuning is not available in session mode"));
8490         goto cleanup;
8491     }
8492 
8493     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8494         goto cleanup;
8495 
8496     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
8497         goto endjob;
8498 
8499     if (def) {
8500         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
8501             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8502                            _("blkio cgroup isn't mounted"));
8503             goto endjob;
8504         }
8505     }
8506 
8507     ret = 0;
8508     if (def) {
8509         ret = virDomainCgroupSetupDomainBlkioParameters(priv->cgroup, def,
8510                                                         params, nparams);
8511         qemuDomainSaveStatus(vm);
8512     }
8513     if (ret < 0)
8514         goto endjob;
8515     if (persistentDef) {
8516         ret = virDomainDriverSetupPersistentDefBlkioParams(persistentDef,
8517                                                            params,
8518                                                            nparams);
8519 
8520         if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
8521             ret = -1;
8522     }
8523 
8524  endjob:
8525     qemuDomainObjEndJob(driver, vm);
8526 
8527  cleanup:
8528     virDomainObjEndAPI(&vm);
8529     return ret;
8530 }
8531 
8532 
8533 static int
qemuDomainGetBlkioParameters(virDomainPtr dom,virTypedParameterPtr params,int * nparams,unsigned int flags)8534 qemuDomainGetBlkioParameters(virDomainPtr dom,
8535                              virTypedParameterPtr params,
8536                              int *nparams,
8537                              unsigned int flags)
8538 {
8539     virQEMUDriver *driver = dom->conn->privateData;
8540     virDomainObj *vm = NULL;
8541     virDomainDef *def = NULL;
8542     virDomainDef *persistentDef = NULL;
8543     int maxparams = QEMU_NB_BLKIO_PARAM;
8544     unsigned int val;
8545     int ret = -1;
8546     qemuDomainObjPrivate *priv;
8547 
8548     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8549                   VIR_DOMAIN_AFFECT_CONFIG |
8550                   VIR_TYPED_PARAM_STRING_OKAY, -1);
8551 
8552     /* We blindly return a string, and let libvirt.c and
8553      * remote_driver.c do the filtering on behalf of older clients
8554      * that can't parse it.  */
8555     flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
8556 
8557     if (!(vm = qemuDomainObjFromDomain(dom)))
8558         return -1;
8559 
8560     priv = vm->privateData;
8561 
8562     if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0)
8563         goto cleanup;
8564 
8565     if (!driver->privileged) {
8566         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8567                        _("Block I/O tuning is not available in session mode"));
8568         goto cleanup;
8569     }
8570 
8571     if ((*nparams) == 0) {
8572         /* Current number of blkio parameters supported by cgroups */
8573         *nparams = QEMU_NB_BLKIO_PARAM;
8574         ret = 0;
8575         goto cleanup;
8576     } else if (*nparams < maxparams) {
8577         maxparams = *nparams;
8578     }
8579 
8580     *nparams = 0;
8581 
8582     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
8583         goto cleanup;
8584 
8585     if (def) {
8586         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
8587             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8588                            _("blkio cgroup isn't mounted"));
8589             goto cleanup;
8590         }
8591 
8592         /* fill blkio weight here */
8593         if (virCgroupGetBlkioWeight(priv->cgroup, &val) < 0)
8594             goto cleanup;
8595         if (virTypedParameterAssign(&(params[(*nparams)++]),
8596                                     VIR_DOMAIN_BLKIO_WEIGHT,
8597                                     VIR_TYPED_PARAM_UINT, val) < 0)
8598             goto cleanup;
8599 
8600         if (virDomainGetBlkioParametersAssignFromDef(def, params, nparams,
8601                                                      maxparams) < 0)
8602             goto cleanup;
8603 
8604     } else if (persistentDef) {
8605         /* fill blkio weight here */
8606         if (virTypedParameterAssign(&(params[(*nparams)++]),
8607                                     VIR_DOMAIN_BLKIO_WEIGHT,
8608                                     VIR_TYPED_PARAM_UINT,
8609                                     persistentDef->blkio.weight) < 0)
8610             goto cleanup;
8611 
8612         if (virDomainGetBlkioParametersAssignFromDef(persistentDef, params,
8613                                                      nparams, maxparams) < 0)
8614             goto cleanup;
8615     }
8616 
8617     ret = 0;
8618 
8619  cleanup:
8620     virDomainObjEndAPI(&vm);
8621     return ret;
8622 }
8623 
8624 static int
qemuDomainSetMemoryParameters(virDomainPtr dom,virTypedParameterPtr params,int nparams,unsigned int flags)8625 qemuDomainSetMemoryParameters(virDomainPtr dom,
8626                               virTypedParameterPtr params,
8627                               int nparams,
8628                               unsigned int flags)
8629 {
8630     virQEMUDriver *driver = dom->conn->privateData;
8631     virDomainDef *def = NULL;
8632     virDomainDef *persistentDef = NULL;
8633     virDomainObj *vm = NULL;
8634     g_autoptr(virQEMUDriverConfig) cfg = NULL;
8635     int ret = -1;
8636     qemuDomainObjPrivate *priv;
8637 
8638     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8639                   VIR_DOMAIN_AFFECT_CONFIG, -1);
8640 
8641     if (virTypedParamsValidate(params, nparams,
8642                                VIR_DOMAIN_MEMORY_HARD_LIMIT,
8643                                VIR_TYPED_PARAM_ULLONG,
8644                                VIR_DOMAIN_MEMORY_SOFT_LIMIT,
8645                                VIR_TYPED_PARAM_ULLONG,
8646                                VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
8647                                VIR_TYPED_PARAM_ULLONG,
8648                                NULL) < 0)
8649         return -1;
8650 
8651 
8652     if (!(vm = qemuDomainObjFromDomain(dom)))
8653         return -1;
8654 
8655     priv = vm->privateData;
8656     cfg = virQEMUDriverGetConfig(driver);
8657 
8658     if (virDomainSetMemoryParametersEnsureACL(dom->conn, vm->def, flags) < 0)
8659         goto cleanup;
8660 
8661     if (!driver->privileged) {
8662         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
8663                        _("Memory tuning is not available in session mode"));
8664         goto cleanup;
8665     }
8666 
8667     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8668         goto cleanup;
8669 
8670     /* QEMU and LXC implementation are identical */
8671     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
8672         goto endjob;
8673 
8674     if (def &&
8675         !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
8676         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8677                        _("cgroup memory controller is not mounted"));
8678         goto endjob;
8679     }
8680 
8681     if (virDomainCgroupSetMemoryLimitParameters(priv->cgroup, vm, def,
8682                                                 persistentDef,
8683                                                 params, nparams) < 0)
8684         goto endjob;
8685 
8686     if (def)
8687         qemuDomainSaveStatus(vm);
8688 
8689     if (persistentDef &&
8690         virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
8691         goto endjob;
8692     /* QEMU and LXC implementations are identical */
8693 
8694     ret = 0;
8695 
8696  endjob:
8697     qemuDomainObjEndJob(driver, vm);
8698 
8699  cleanup:
8700     virDomainObjEndAPI(&vm);
8701     return ret;
8702 }
8703 
8704 
8705 #define QEMU_ASSIGN_MEM_PARAM(index, name, value) \
8706     if (index < *nparams && \
8707         virTypedParameterAssign(&params[index], name, VIR_TYPED_PARAM_ULLONG, \
8708                                 value) < 0) \
8709         goto cleanup
8710 
8711 static int
qemuDomainGetMemoryParameters(virDomainPtr dom,virTypedParameterPtr params,int * nparams,unsigned int flags)8712 qemuDomainGetMemoryParameters(virDomainPtr dom,
8713                               virTypedParameterPtr params,
8714                               int *nparams,
8715                               unsigned int flags)
8716 {
8717     virQEMUDriver *driver = dom->conn->privateData;
8718     virDomainObj *vm = NULL;
8719     virDomainDef *persistentDef = NULL;
8720     int ret = -1;
8721     qemuDomainObjPrivate *priv;
8722     unsigned long long swap_hard_limit, mem_hard_limit, mem_soft_limit;
8723 
8724     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8725                   VIR_DOMAIN_AFFECT_CONFIG |
8726                   VIR_TYPED_PARAM_STRING_OKAY, -1);
8727 
8728     if (!(vm = qemuDomainObjFromDomain(dom)))
8729         return -1;
8730 
8731     priv = vm->privateData;
8732 
8733     if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0)
8734         goto cleanup;
8735 
8736     if (!driver->privileged) {
8737         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
8738                        _("Memory tuning is not available in session mode"));
8739         goto cleanup;
8740     }
8741 
8742     if (virDomainObjGetDefs(vm, flags, NULL, &persistentDef) < 0)
8743         goto cleanup;
8744 
8745     if ((*nparams) == 0) {
8746         /* Current number of memory parameters supported by cgroups */
8747         *nparams = QEMU_NB_MEM_PARAM;
8748         ret = 0;
8749         goto cleanup;
8750     }
8751 
8752     if (persistentDef) {
8753         mem_hard_limit = persistentDef->mem.hard_limit;
8754         mem_soft_limit = persistentDef->mem.soft_limit;
8755         swap_hard_limit = persistentDef->mem.swap_hard_limit;
8756     } else {
8757         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
8758             virReportError(VIR_ERR_OPERATION_INVALID,
8759                            "%s", _("cgroup memory controller is not mounted"));
8760             goto cleanup;
8761         }
8762 
8763         if (virCgroupGetMemoryHardLimit(priv->cgroup, &mem_hard_limit) < 0)
8764             goto cleanup;
8765 
8766         if (virCgroupGetMemorySoftLimit(priv->cgroup, &mem_soft_limit) < 0)
8767             goto cleanup;
8768 
8769         if (virCgroupGetMemSwapHardLimit(priv->cgroup, &swap_hard_limit) < 0) {
8770             if (!virLastErrorIsSystemErrno(ENOENT) &&
8771                 !virLastErrorIsSystemErrno(EOPNOTSUPP))
8772                 goto cleanup;
8773             swap_hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
8774         }
8775     }
8776 
8777     QEMU_ASSIGN_MEM_PARAM(0, VIR_DOMAIN_MEMORY_HARD_LIMIT, mem_hard_limit);
8778     QEMU_ASSIGN_MEM_PARAM(1, VIR_DOMAIN_MEMORY_SOFT_LIMIT, mem_soft_limit);
8779     QEMU_ASSIGN_MEM_PARAM(2, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit);
8780 
8781     if (QEMU_NB_MEM_PARAM < *nparams)
8782         *nparams = QEMU_NB_MEM_PARAM;
8783     ret = 0;
8784 
8785  cleanup:
8786     virDomainObjEndAPI(&vm);
8787     return ret;
8788 }
8789 #undef QEMU_ASSIGN_MEM_PARAM
8790 
8791 static int
qemuDomainSetNumaParamsLive(virDomainObj * vm,virBitmap * nodeset)8792 qemuDomainSetNumaParamsLive(virDomainObj *vm,
8793                             virBitmap *nodeset)
8794 {
8795     g_autoptr(virCgroup) cgroup_thread = NULL;
8796     qemuDomainObjPrivate *priv = vm->privateData;
8797     g_autofree char *nodeset_str = NULL;
8798     virDomainNumatuneMemMode mode;
8799     size_t i = 0;
8800 
8801     if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
8802         mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
8803         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8804                        _("change of nodeset for running domain "
8805                          "requires strict numa mode"));
8806         return -1;
8807     }
8808 
8809     if (!virNumaNodesetIsAvailable(nodeset))
8810         return -1;
8811 
8812     /* Ensure the cpuset string is formatted before passing to cgroup */
8813     if (!(nodeset_str = virBitmapFormat(nodeset)))
8814         return -1;
8815 
8816     if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
8817                            false, &cgroup_thread) < 0 ||
8818         virCgroupSetCpusetMems(cgroup_thread, nodeset_str) < 0)
8819         return -1;
8820 
8821     for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
8822         g_autoptr(virCgroup) cgroup_vcpu = NULL;
8823         virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
8824 
8825         if (!vcpu->online)
8826             continue;
8827 
8828         if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
8829                                false, &cgroup_vcpu) < 0 ||
8830             virCgroupSetCpusetMems(cgroup_vcpu, nodeset_str) < 0)
8831             return -1;
8832     }
8833 
8834     for (i = 0; i < vm->def->niothreadids; i++) {
8835         g_autoptr(virCgroup) cgroup_iothread = NULL;
8836 
8837         if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
8838                                vm->def->iothreadids[i]->iothread_id,
8839                                false, &cgroup_iothread) < 0 ||
8840             virCgroupSetCpusetMems(cgroup_iothread, nodeset_str) < 0)
8841             return -1;
8842     }
8843 
8844     return 0;
8845 }
8846 
8847 static int
qemuDomainSetNumaParameters(virDomainPtr dom,virTypedParameterPtr params,int nparams,unsigned int flags)8848 qemuDomainSetNumaParameters(virDomainPtr dom,
8849                             virTypedParameterPtr params,
8850                             int nparams,
8851                             unsigned int flags)
8852 {
8853     virQEMUDriver *driver = dom->conn->privateData;
8854     size_t i;
8855     virDomainDef *def;
8856     virDomainDef *persistentDef;
8857     virDomainObj *vm = NULL;
8858     int ret = -1;
8859     g_autoptr(virQEMUDriverConfig) cfg = NULL;
8860     qemuDomainObjPrivate *priv;
8861     virBitmap *nodeset = NULL;
8862     virDomainNumatuneMemMode config_mode;
8863     int mode = -1;
8864 
8865     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8866                   VIR_DOMAIN_AFFECT_CONFIG, -1);
8867 
8868     if (virTypedParamsValidate(params, nparams,
8869                                VIR_DOMAIN_NUMA_MODE,
8870                                VIR_TYPED_PARAM_INT,
8871                                VIR_DOMAIN_NUMA_NODESET,
8872                                VIR_TYPED_PARAM_STRING,
8873                                NULL) < 0)
8874         return -1;
8875 
8876     if (!(vm = qemuDomainObjFromDomain(dom)))
8877         return -1;
8878 
8879     priv = vm->privateData;
8880     cfg = virQEMUDriverGetConfig(driver);
8881 
8882     if (virDomainSetNumaParametersEnsureACL(dom->conn, vm->def, flags) < 0)
8883         goto cleanup;
8884 
8885     for (i = 0; i < nparams; i++) {
8886         virTypedParameterPtr param = &params[i];
8887 
8888         if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
8889             mode = param->value.i;
8890 
8891             if (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST) {
8892                 virReportError(VIR_ERR_INVALID_ARG,
8893                                _("unsupported numatune mode: '%d'"), mode);
8894                 goto cleanup;
8895             }
8896 
8897         } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
8898             if (virBitmapParse(param->value.s, &nodeset,
8899                                VIR_DOMAIN_CPUMASK_LEN) < 0)
8900                 goto cleanup;
8901 
8902             if (virBitmapIsAllClear(nodeset)) {
8903                 virReportError(VIR_ERR_OPERATION_INVALID,
8904                                _("Invalid nodeset of 'numatune': %s"),
8905                                param->value.s);
8906                 goto cleanup;
8907             }
8908         }
8909     }
8910 
8911     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8912         goto cleanup;
8913 
8914     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
8915         goto endjob;
8916 
8917     if (def) {
8918         if (!driver->privileged) {
8919             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
8920                            _("NUMA tuning is not available in session mode"));
8921             goto endjob;
8922         }
8923 
8924         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
8925             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8926                            _("cgroup cpuset controller is not mounted"));
8927             goto endjob;
8928         }
8929 
8930         if (mode != -1 &&
8931             virDomainNumatuneGetMode(def->numa, -1, &config_mode) == 0 &&
8932             config_mode != mode) {
8933             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8934                            _("can't change numatune mode for running domain"));
8935             goto endjob;
8936         }
8937 
8938         if (nodeset &&
8939             qemuDomainSetNumaParamsLive(vm, nodeset) < 0)
8940             goto endjob;
8941 
8942         if (virDomainNumatuneSet(def->numa,
8943                                  def->placement_mode ==
8944                                  VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
8945                                  -1, mode, nodeset) < 0)
8946             goto endjob;
8947 
8948         qemuDomainSaveStatus(vm);
8949     }
8950 
8951     if (persistentDef) {
8952         if (virDomainNumatuneSet(persistentDef->numa,
8953                                  persistentDef->placement_mode ==
8954                                  VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
8955                                  -1, mode, nodeset) < 0)
8956             goto endjob;
8957 
8958         if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
8959             goto endjob;
8960     }
8961 
8962     ret = 0;
8963 
8964  endjob:
8965     qemuDomainObjEndJob(driver, vm);
8966 
8967  cleanup:
8968     virBitmapFree(nodeset);
8969     virDomainObjEndAPI(&vm);
8970     return ret;
8971 }
8972 
8973 static int
qemuDomainGetNumaParameters(virDomainPtr dom,virTypedParameterPtr params,int * nparams,unsigned int flags)8974 qemuDomainGetNumaParameters(virDomainPtr dom,
8975                             virTypedParameterPtr params,
8976                             int *nparams,
8977                             unsigned int flags)
8978 {
8979     size_t i;
8980     virDomainObj *vm = NULL;
8981     virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
8982     qemuDomainObjPrivate *priv;
8983     g_autofree char *nodeset = NULL;
8984     int ret = -1;
8985     virDomainDef *def = NULL;
8986     bool live = false;
8987     virBitmap *autoNodeset = NULL;
8988 
8989     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8990                   VIR_DOMAIN_AFFECT_CONFIG |
8991                   VIR_TYPED_PARAM_STRING_OKAY, -1);
8992 
8993     if (!(vm = qemuDomainObjFromDomain(dom)))
8994         return -1;
8995     priv = vm->privateData;
8996 
8997     if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
8998         goto cleanup;
8999 
9000     if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
9001         goto cleanup;
9002 
9003     if (live)
9004         autoNodeset = priv->autoNodeset;
9005 
9006     if ((*nparams) == 0) {
9007         *nparams = QEMU_NB_NUMA_PARAM;
9008         ret = 0;
9009         goto cleanup;
9010     }
9011 
9012     for (i = 0; i < QEMU_NB_NUMA_PARAM && i < *nparams; i++) {
9013         virMemoryParameterPtr param = &params[i];
9014 
9015         switch (i) {
9016         case 0: /* fill numa mode here */
9017             ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
9018 
9019             if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
9020                                         VIR_TYPED_PARAM_INT, tmpmode) < 0)
9021                 goto cleanup;
9022 
9023             break;
9024 
9025         case 1: /* fill numa nodeset here */
9026             nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, -1);
9027             if (!nodeset ||
9028                 virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
9029                                         VIR_TYPED_PARAM_STRING, nodeset) < 0)
9030                 goto cleanup;
9031 
9032             nodeset = NULL;
9033             break;
9034 
9035         default:
9036             break;
9037             /* should not hit here */
9038         }
9039     }
9040 
9041     if (*nparams > QEMU_NB_NUMA_PARAM)
9042         *nparams = QEMU_NB_NUMA_PARAM;
9043     ret = 0;
9044 
9045  cleanup:
9046     virDomainObjEndAPI(&vm);
9047     return ret;
9048 }
9049 
9050 static int
qemuSetGlobalBWLive(virCgroup * cgroup,unsigned long long period,long long quota)9051 qemuSetGlobalBWLive(virCgroup *cgroup, unsigned long long period,
9052                     long long quota)
9053 {
9054     if (period == 0 && quota == 0)
9055         return 0;
9056 
9057     if (qemuSetupCgroupVcpuBW(cgroup, period, quota) < 0)
9058         return -1;
9059 
9060     return 0;
9061 }
9062 
9063 static int
qemuDomainSetPerfEvents(virDomainPtr dom,virTypedParameterPtr params,int nparams,unsigned int flags)9064 qemuDomainSetPerfEvents(virDomainPtr dom,
9065                         virTypedParameterPtr params,
9066                         int nparams,
9067                         unsigned int flags)
9068 {
9069     virQEMUDriver *driver = dom->conn->privateData;
9070     size_t i;
9071     virDomainObj *vm = NULL;
9072     g_autoptr(virQEMUDriverConfig) cfg = NULL;
9073     qemuDomainObjPrivate *priv;
9074     virDomainDef *def;
9075     virDomainDef *persistentDef;
9076     int ret = -1;
9077     virPerfEventType type;
9078     bool enabled;
9079 
9080     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9081                   VIR_DOMAIN_AFFECT_CONFIG, -1);
9082 
9083     if (virTypedParamsValidate(params, nparams,
9084                                VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_BOOLEAN,
9085                                VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_BOOLEAN,
9086                                VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_BOOLEAN,
9087                                VIR_PERF_PARAM_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
9088                                VIR_PERF_PARAM_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
9089                                VIR_PERF_PARAM_CACHE_REFERENCES, VIR_TYPED_PARAM_BOOLEAN,
9090                                VIR_PERF_PARAM_CACHE_MISSES, VIR_TYPED_PARAM_BOOLEAN,
9091                                VIR_PERF_PARAM_BRANCH_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
9092                                VIR_PERF_PARAM_BRANCH_MISSES, VIR_TYPED_PARAM_BOOLEAN,
9093                                VIR_PERF_PARAM_BUS_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
9094                                VIR_PERF_PARAM_STALLED_CYCLES_FRONTEND, VIR_TYPED_PARAM_BOOLEAN,
9095                                VIR_PERF_PARAM_STALLED_CYCLES_BACKEND, VIR_TYPED_PARAM_BOOLEAN,
9096                                VIR_PERF_PARAM_REF_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
9097                                VIR_PERF_PARAM_CPU_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
9098                                VIR_PERF_PARAM_TASK_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
9099                                VIR_PERF_PARAM_PAGE_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
9100                                VIR_PERF_PARAM_CONTEXT_SWITCHES, VIR_TYPED_PARAM_BOOLEAN,
9101                                VIR_PERF_PARAM_CPU_MIGRATIONS, VIR_TYPED_PARAM_BOOLEAN,
9102                                VIR_PERF_PARAM_PAGE_FAULTS_MIN, VIR_TYPED_PARAM_BOOLEAN,
9103                                VIR_PERF_PARAM_PAGE_FAULTS_MAJ, VIR_TYPED_PARAM_BOOLEAN,
9104                                VIR_PERF_PARAM_ALIGNMENT_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
9105                                VIR_PERF_PARAM_EMULATION_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
9106                                NULL) < 0)
9107         return -1;
9108 
9109     if (!(vm = qemuDomainObjFromDomain(dom)))
9110         return -1;
9111 
9112     cfg = virQEMUDriverGetConfig(driver);
9113     priv = vm->privateData;
9114 
9115     if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
9116         goto cleanup;
9117 
9118     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9119         goto cleanup;
9120 
9121     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9122         goto endjob;
9123 
9124     if (def) {
9125         for (i = 0; i < nparams; i++) {
9126             virTypedParameterPtr param = &params[i];
9127             enabled = param->value.b;
9128             type = virPerfEventTypeFromString(param->field);
9129 
9130             if (!enabled && virPerfEventDisable(priv->perf, type) < 0)
9131                 goto endjob;
9132             if (enabled && virPerfEventEnable(priv->perf, type, vm->pid) < 0)
9133                 goto endjob;
9134 
9135             def->perf.events[type] = enabled ?
9136                 VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
9137         }
9138 
9139         qemuDomainSaveStatus(vm);
9140     }
9141 
9142     if (persistentDef) {
9143         for (i = 0; i < nparams; i++) {
9144             virTypedParameterPtr param = &params[i];
9145             enabled = param->value.b;
9146             type = virPerfEventTypeFromString(param->field);
9147 
9148             persistentDef->perf.events[type] = enabled ?
9149                 VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
9150         }
9151 
9152         if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
9153             goto endjob;
9154     }
9155 
9156     ret = 0;
9157 
9158  endjob:
9159     qemuDomainObjEndJob(driver, vm);
9160 
9161  cleanup:
9162     virDomainObjEndAPI(&vm);
9163     return ret;
9164 }
9165 
9166 static int
qemuDomainGetPerfEvents(virDomainPtr dom,virTypedParameterPtr * params,int * nparams,unsigned int flags)9167 qemuDomainGetPerfEvents(virDomainPtr dom,
9168                         virTypedParameterPtr *params,
9169                         int *nparams,
9170                         unsigned int flags)
9171 {
9172     virQEMUDriver *driver = dom->conn->privateData;
9173     virDomainObj *vm = NULL;
9174     qemuDomainObjPrivate *priv;
9175     virDomainDef *def;
9176     virTypedParameterPtr par = NULL;
9177     int maxpar = 0;
9178     int npar = 0;
9179     size_t i;
9180     int ret = -1;
9181     bool live = false;
9182 
9183     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9184                   VIR_DOMAIN_AFFECT_CONFIG |
9185                   VIR_TYPED_PARAM_STRING_OKAY, -1);
9186 
9187     if (!(vm = qemuDomainObjFromDomain(dom)))
9188         goto cleanup;
9189 
9190     if (virDomainGetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
9191         goto cleanup;
9192 
9193     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
9194         goto cleanup;
9195 
9196     if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
9197         goto endjob;
9198 
9199     priv = vm->privateData;
9200 
9201     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
9202         bool perf_enabled;
9203 
9204         if ((flags & VIR_DOMAIN_AFFECT_CONFIG) || !live)
9205             perf_enabled = def->perf.events[i] == VIR_TRISTATE_BOOL_YES;
9206         else
9207             perf_enabled = virPerfEventIsEnabled(priv->perf, i);
9208 
9209         if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
9210                                      virPerfEventTypeToString(i),
9211                                      perf_enabled) < 0)
9212             goto endjob;
9213     }
9214 
9215     *nparams = npar;
9216     *params = g_steal_pointer(&par);
9217     npar = 0;
9218     ret = 0;
9219 
9220  endjob:
9221     qemuDomainObjEndJob(driver, vm);
9222 
9223  cleanup:
9224     virDomainObjEndAPI(&vm);
9225     virTypedParamsFree(par, npar);
9226     return ret;
9227 }
9228 
9229 static int
qemuSetVcpusBWLive(virDomainObj * vm,virCgroup * cgroup,unsigned long long period,long long quota)9230 qemuSetVcpusBWLive(virDomainObj *vm, virCgroup *cgroup,
9231                    unsigned long long period, long long quota)
9232 {
9233     size_t i;
9234 
9235     if (period == 0 && quota == 0)
9236         return 0;
9237 
9238     if (!qemuDomainHasVcpuPids(vm))
9239         return 0;
9240 
9241     for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
9242         g_autoptr(virCgroup) cgroup_vcpu = NULL;
9243         virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
9244 
9245         if (!vcpu->online)
9246             continue;
9247 
9248         if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_VCPU, i,
9249                                false, &cgroup_vcpu) < 0)
9250             return -1;
9251 
9252         if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
9253             return -1;
9254     }
9255 
9256     return 0;
9257 }
9258 
9259 static int
qemuSetEmulatorBandwidthLive(virCgroup * cgroup,unsigned long long period,long long quota)9260 qemuSetEmulatorBandwidthLive(virCgroup *cgroup,
9261                              unsigned long long period,
9262                              long long quota)
9263 {
9264     g_autoptr(virCgroup) cgroup_emulator = NULL;
9265 
9266     if (period == 0 && quota == 0)
9267         return 0;
9268 
9269     if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
9270                            false, &cgroup_emulator) < 0)
9271         return -1;
9272 
9273     if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
9274         return -1;
9275 
9276     return 0;
9277 }
9278 
9279 
9280 static int
qemuSetIOThreadsBWLive(virDomainObj * vm,virCgroup * cgroup,unsigned long long period,long long quota)9281 qemuSetIOThreadsBWLive(virDomainObj *vm, virCgroup *cgroup,
9282                        unsigned long long period, long long quota)
9283 {
9284     size_t i;
9285 
9286     if (period == 0 && quota == 0)
9287         return 0;
9288 
9289     if (!vm->def->niothreadids)
9290         return 0;
9291 
9292     for (i = 0; i < vm->def->niothreadids; i++) {
9293         g_autoptr(virCgroup) cgroup_iothread = NULL;
9294 
9295         if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_IOTHREAD,
9296                                vm->def->iothreadids[i]->iothread_id,
9297                                false, &cgroup_iothread) < 0)
9298             return -1;
9299 
9300         if (qemuSetupCgroupVcpuBW(cgroup_iothread, period, quota) < 0)
9301             return -1;
9302     }
9303 
9304     return 0;
9305 }
9306 
9307 
9308 #define SCHED_RANGE_CHECK(VAR, NAME, MIN, MAX) \
9309     if (((VAR) > 0 && (VAR) < (MIN)) || (VAR) > (MAX)) { \
9310         virReportError(VIR_ERR_INVALID_ARG, \
9311                        _("value of '%s' is out of range [%lld, %lld]"), \
9312                        NAME, MIN, MAX); \
9313         rc = -1; \
9314         goto endjob; \
9315     }
9316 
9317 static int
qemuDomainSetSchedulerParametersFlags(virDomainPtr dom,virTypedParameterPtr params,int nparams,unsigned int flags)9318 qemuDomainSetSchedulerParametersFlags(virDomainPtr dom,
9319                                       virTypedParameterPtr params,
9320                                       int nparams,
9321                                       unsigned int flags)
9322 {
9323     virQEMUDriver *driver = dom->conn->privateData;
9324     size_t i;
9325     virDomainObj *vm = NULL;
9326     virDomainDef *def = NULL;
9327     virDomainDef *persistentDef = NULL;
9328     g_autoptr(virDomainDef) persistentDefCopy = NULL;
9329     unsigned long long value_ul;
9330     long long value_l;
9331     int ret = -1;
9332     int rc;
9333     g_autoptr(virQEMUDriverConfig) cfg = NULL;
9334     qemuDomainObjPrivate *priv;
9335     virObjectEvent *event = NULL;
9336     virTypedParameterPtr eventParams = NULL;
9337     int eventNparams = 0;
9338     int eventMaxNparams = 0;
9339 
9340     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9341                   VIR_DOMAIN_AFFECT_CONFIG, -1);
9342     if (virTypedParamsValidate(params, nparams,
9343                                VIR_DOMAIN_SCHEDULER_CPU_SHARES,
9344                                VIR_TYPED_PARAM_ULLONG,
9345                                VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
9346                                VIR_TYPED_PARAM_ULLONG,
9347                                VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
9348                                VIR_TYPED_PARAM_LLONG,
9349                                VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
9350                                VIR_TYPED_PARAM_ULLONG,
9351                                VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
9352                                VIR_TYPED_PARAM_LLONG,
9353                                VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
9354                                VIR_TYPED_PARAM_ULLONG,
9355                                VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
9356                                VIR_TYPED_PARAM_LLONG,
9357                                VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
9358                                VIR_TYPED_PARAM_ULLONG,
9359                                VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
9360                                VIR_TYPED_PARAM_LLONG,
9361                                NULL) < 0)
9362         return -1;
9363 
9364     if (!(vm = qemuDomainObjFromDomain(dom)))
9365         return -1;
9366 
9367     priv = vm->privateData;
9368     cfg = virQEMUDriverGetConfig(driver);
9369 
9370     if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
9371         goto cleanup;
9372 
9373     if (!driver->privileged) {
9374         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9375                        _("CPU tuning is not available in session mode"));
9376         goto cleanup;
9377     }
9378 
9379     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9380         goto cleanup;
9381 
9382     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9383         goto endjob;
9384 
9385     if (persistentDef) {
9386         /* Make a copy for updated domain. */
9387         if (!(persistentDefCopy = virDomainObjCopyPersistentDef(vm,
9388                                                                 driver->xmlopt,
9389                                                                 priv->qemuCaps)))
9390             goto endjob;
9391     }
9392 
9393     if (def &&
9394         !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
9395         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
9396                        _("cgroup CPU controller is not mounted"));
9397         goto endjob;
9398     }
9399 
9400     for (i = 0; i < nparams; i++) {
9401         virTypedParameterPtr param = &params[i];
9402         value_ul = param->value.ul;
9403         value_l = param->value.l;
9404 
9405         if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
9406             if (def) {
9407                 if (virCgroupSetCpuShares(priv->cgroup, value_ul) < 0)
9408                     goto endjob;
9409 
9410                 def->cputune.shares = value_ul;
9411                 def->cputune.sharesSpecified = true;
9412 
9413                 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
9414                                             &eventMaxNparams,
9415                                             VIR_DOMAIN_TUNABLE_CPU_CPU_SHARES,
9416                                             value_ul) < 0)
9417                     goto endjob;
9418             }
9419 
9420             if (persistentDef) {
9421                 persistentDefCopy->cputune.shares = value_ul;
9422                 persistentDefCopy->cputune.sharesSpecified = true;
9423             }
9424 
9425 
9426         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
9427             SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
9428                               VIR_CGROUP_CPU_PERIOD_MIN, VIR_CGROUP_CPU_PERIOD_MAX);
9429 
9430             if (def && value_ul) {
9431                 if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, value_ul, 0)))
9432                     goto endjob;
9433 
9434                 def->cputune.period = value_ul;
9435 
9436                 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
9437                                             &eventMaxNparams,
9438                                             VIR_DOMAIN_TUNABLE_CPU_VCPU_PERIOD,
9439                                             value_ul) < 0)
9440                     goto endjob;
9441             }
9442 
9443             if (persistentDef)
9444                 persistentDefCopy->cputune.period = value_ul;
9445 
9446         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
9447             SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
9448                               VIR_CGROUP_CPU_QUOTA_MIN, VIR_CGROUP_CPU_QUOTA_MAX);
9449 
9450             if (def && value_l) {
9451                 if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, 0, value_l)))
9452                     goto endjob;
9453 
9454                 def->cputune.quota = value_l;
9455 
9456                 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
9457                                            &eventMaxNparams,
9458                                            VIR_DOMAIN_TUNABLE_CPU_VCPU_QUOTA,
9459                                            value_l) < 0)
9460                     goto endjob;
9461             }
9462 
9463             if (persistentDef)
9464                 persistentDefCopy->cputune.quota = value_l;
9465 
9466         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD)) {
9467             SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
9468                               VIR_CGROUP_CPU_PERIOD_MIN, VIR_CGROUP_CPU_PERIOD_MAX);
9469 
9470             if (def && value_ul) {
9471                 if ((rc = qemuSetGlobalBWLive(priv->cgroup, value_ul, 0)))
9472                     goto endjob;
9473 
9474                 def->cputune.global_period = value_ul;
9475 
9476                 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
9477                                             &eventMaxNparams,
9478                                             VIR_DOMAIN_TUNABLE_CPU_GLOBAL_PERIOD,
9479                                             value_ul) < 0)
9480                     goto endjob;
9481             }
9482 
9483             if (persistentDef)
9484                 persistentDefCopy->cputune.global_period = value_ul;
9485 
9486         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA)) {
9487             SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
9488                               VIR_CGROUP_CPU_QUOTA_MIN, VIR_CGROUP_CPU_QUOTA_MAX);
9489 
9490             if (def && value_l) {
9491                 if ((rc = qemuSetGlobalBWLive(priv->cgroup, 0, value_l)))
9492                     goto endjob;
9493 
9494                 def->cputune.global_quota = value_l;
9495 
9496                 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
9497                                            &eventMaxNparams,
9498                                            VIR_DOMAIN_TUNABLE_CPU_GLOBAL_QUOTA,
9499                                            value_l) < 0)
9500                     goto endjob;
9501             }
9502 
9503             if (persistentDef)
9504                 persistentDefCopy->cputune.global_quota = value_l;
9505 
9506         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD)) {
9507             SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
9508                               VIR_CGROUP_CPU_PERIOD_MIN, VIR_CGROUP_CPU_PERIOD_MAX);
9509 
9510             if (def && value_ul) {
9511                 if ((rc = qemuSetEmulatorBandwidthLive(priv->cgroup,
9512                                                        value_ul, 0)))
9513                     goto endjob;
9514 
9515                 def->cputune.emulator_period = value_ul;
9516 
9517                 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
9518                                             &eventMaxNparams,
9519                                             VIR_DOMAIN_TUNABLE_CPU_EMULATOR_PERIOD,
9520                                             value_ul) < 0)
9521                     goto endjob;
9522             }
9523 
9524             if (persistentDef)
9525                 persistentDefCopy->cputune.emulator_period = value_ul;
9526 
9527         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA)) {
9528             SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
9529                               VIR_CGROUP_CPU_QUOTA_MIN, VIR_CGROUP_CPU_QUOTA_MAX);
9530 
9531             if (def && value_l) {
9532                 if ((rc = qemuSetEmulatorBandwidthLive(priv->cgroup,
9533                                                        0, value_l)))
9534                     goto endjob;
9535 
9536                 def->cputune.emulator_quota = value_l;
9537 
9538                 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
9539                                            &eventMaxNparams,
9540                                            VIR_DOMAIN_TUNABLE_CPU_EMULATOR_QUOTA,
9541                                            value_l) < 0)
9542                     goto endjob;
9543             }
9544 
9545             if (persistentDef)
9546                 persistentDefCopy->cputune.emulator_quota = value_l;
9547 
9548         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD)) {
9549             SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
9550                               VIR_CGROUP_CPU_PERIOD_MIN, VIR_CGROUP_CPU_PERIOD_MAX);
9551 
9552             if (def && value_ul) {
9553                 if ((rc = qemuSetIOThreadsBWLive(vm, priv->cgroup, value_ul, 0)))
9554                     goto endjob;
9555 
9556                 def->cputune.iothread_period = value_ul;
9557 
9558                 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
9559                                             &eventMaxNparams,
9560                                             VIR_DOMAIN_TUNABLE_CPU_IOTHREAD_PERIOD,
9561                                             value_ul) < 0)
9562                     goto endjob;
9563             }
9564 
9565             if (persistentDef)
9566                 persistentDefCopy->cputune.iothread_period = value_ul;
9567 
9568         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA)) {
9569             SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
9570                               VIR_CGROUP_CPU_QUOTA_MIN, VIR_CGROUP_CPU_QUOTA_MAX);
9571 
9572             if (def && value_l) {
9573                 if ((rc = qemuSetIOThreadsBWLive(vm, priv->cgroup, 0, value_l)))
9574                     goto endjob;
9575 
9576                 def->cputune.iothread_quota = value_l;
9577 
9578                 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
9579                                            &eventMaxNparams,
9580                                            VIR_DOMAIN_TUNABLE_CPU_IOTHREAD_QUOTA,
9581                                            value_l) < 0)
9582                     goto endjob;
9583             }
9584 
9585             if (persistentDef)
9586                 persistentDefCopy->cputune.iothread_quota = value_l;
9587         }
9588     }
9589 
9590     qemuDomainSaveStatus(vm);
9591 
9592     if (eventNparams) {
9593         event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
9594         eventNparams = 0;
9595         virObjectEventStateQueue(driver->domainEventState, event);
9596     }
9597 
9598     if (persistentDef) {
9599         rc = virDomainDefSave(persistentDefCopy, driver->xmlopt,
9600                               cfg->configDir);
9601         if (rc < 0)
9602             goto endjob;
9603 
9604         virDomainObjAssignDef(vm, &persistentDefCopy, false, NULL);
9605     }
9606 
9607     ret = 0;
9608 
9609  endjob:
9610     qemuDomainObjEndJob(driver, vm);
9611 
9612  cleanup:
9613     virDomainObjEndAPI(&vm);
9614     if (eventNparams)
9615         virTypedParamsFree(eventParams, eventNparams);
9616     return ret;
9617 }
9618 #undef SCHED_RANGE_CHECK
9619 
9620 static int
qemuDomainSetSchedulerParameters(virDomainPtr dom,virTypedParameterPtr params,int nparams)9621 qemuDomainSetSchedulerParameters(virDomainPtr dom,
9622                                  virTypedParameterPtr params,
9623                                  int nparams)
9624 {
9625     return qemuDomainSetSchedulerParametersFlags(dom,
9626                                                  params,
9627                                                  nparams,
9628                                                  VIR_DOMAIN_AFFECT_CURRENT);
9629 }
9630 
9631 static int
qemuGetVcpuBWLive(virCgroup * cgroup,unsigned long long * period,long long * quota)9632 qemuGetVcpuBWLive(virCgroup *cgroup, unsigned long long *period,
9633                   long long *quota)
9634 {
9635     return virCgroupGetCpuPeriodQuota(cgroup, period, quota);
9636 }
9637 
9638 static int
qemuGetVcpusBWLive(virDomainObj * vm,unsigned long long * period,long long * quota)9639 qemuGetVcpusBWLive(virDomainObj *vm,
9640                    unsigned long long *period, long long *quota)
9641 {
9642     g_autoptr(virCgroup) cgroup_vcpu = NULL;
9643     qemuDomainObjPrivate *priv = NULL;
9644 
9645     priv = vm->privateData;
9646     if (!qemuDomainHasVcpuPids(vm)) {
9647         /* We do not create sub dir for each vcpu */
9648         if (qemuGetVcpuBWLive(priv->cgroup, period, quota) < 0)
9649             return -1;
9650 
9651         if (*quota > 0)
9652             *quota /= virDomainDefGetVcpus(vm->def);
9653         return 0;
9654     }
9655 
9656     /* get period and quota for vcpu0 */
9657     if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, 0,
9658                            false, &cgroup_vcpu) < 0)
9659         return -1;
9660 
9661     if (qemuGetVcpuBWLive(cgroup_vcpu, period, quota) < 0)
9662         return -1;
9663 
9664     return 0;
9665 }
9666 
9667 static int
qemuGetEmulatorBandwidthLive(virCgroup * cgroup,unsigned long long * period,long long * quota)9668 qemuGetEmulatorBandwidthLive(virCgroup *cgroup,
9669                              unsigned long long *period,
9670                              long long *quota)
9671 {
9672     g_autoptr(virCgroup) cgroup_emulator = NULL;
9673 
9674     /* get period and quota for emulator */
9675     if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
9676                            false, &cgroup_emulator) < 0)
9677         return -1;
9678 
9679     if (qemuGetVcpuBWLive(cgroup_emulator, period, quota) < 0)
9680         return -1;
9681 
9682     return 0;
9683 }
9684 
9685 static int
qemuGetIOThreadsBWLive(virDomainObj * vm,unsigned long long * period,long long * quota)9686 qemuGetIOThreadsBWLive(virDomainObj *vm,
9687                        unsigned long long *period, long long *quota)
9688 {
9689     g_autoptr(virCgroup) cgroup_iothread = NULL;
9690     qemuDomainObjPrivate *priv = NULL;
9691 
9692     priv = vm->privateData;
9693     if (!vm->def->niothreadids) {
9694         /* We do not create sub dir for each iothread */
9695         if (qemuGetVcpuBWLive(priv->cgroup, period, quota) < 0)
9696             return -1;
9697 
9698         return 0;
9699     }
9700 
9701     /* get period and quota for the "first" IOThread */
9702     if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
9703                            vm->def->iothreadids[0]->iothread_id,
9704                            false, &cgroup_iothread) < 0)
9705         return -1;
9706 
9707     if (qemuGetVcpuBWLive(cgroup_iothread, period, quota) < 0)
9708         return -1;
9709 
9710     return 0;
9711 }
9712 
9713 
9714 static int
qemuGetGlobalBWLive(virCgroup * cgroup,unsigned long long * period,long long * quota)9715 qemuGetGlobalBWLive(virCgroup *cgroup, unsigned long long *period,
9716                     long long *quota)
9717 {
9718     if (qemuGetVcpuBWLive(cgroup, period, quota) < 0)
9719         return -1;
9720 
9721     return 0;
9722 }
9723 
9724 static int
qemuDomainGetSchedulerParametersFlags(virDomainPtr dom,virTypedParameterPtr params,int * nparams,unsigned int flags)9725 qemuDomainGetSchedulerParametersFlags(virDomainPtr dom,
9726                                       virTypedParameterPtr params,
9727                                       int *nparams,
9728                                       unsigned int flags)
9729 {
9730     virQEMUDriver *driver = dom->conn->privateData;
9731     virDomainObj *vm = NULL;
9732     virDomainCputune data = {0};
9733     int ret = -1;
9734     bool cpu_bw_status = true;
9735     virDomainDef *persistentDef;
9736     virDomainDef *def;
9737     qemuDomainObjPrivate *priv;
9738     int maxparams = *nparams;
9739 
9740     *nparams = 0;
9741 
9742     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9743                   VIR_DOMAIN_AFFECT_CONFIG |
9744                   VIR_TYPED_PARAM_STRING_OKAY, -1);
9745 
9746     if (!(vm = qemuDomainObjFromDomain(dom)))
9747         goto cleanup;
9748 
9749     priv = vm->privateData;
9750 
9751     if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
9752         goto cleanup;
9753 
9754     if (!driver->privileged) {
9755         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9756                        _("CPU tuning is not available in session mode"));
9757         goto cleanup;
9758     }
9759 
9760     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9761         goto cleanup;
9762 
9763     if (persistentDef) {
9764         data = persistentDef->cputune;
9765     } else if (def) {
9766         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
9767             virReportError(VIR_ERR_OPERATION_INVALID,
9768                            "%s", _("cgroup CPU controller is not mounted"));
9769             goto cleanup;
9770         }
9771 
9772         if (virCgroupGetCpuShares(priv->cgroup, &data.shares) < 0)
9773             goto cleanup;
9774 
9775         if (virCgroupSupportsCpuBW(priv->cgroup)) {
9776             if (maxparams > 1 &&
9777                 qemuGetVcpusBWLive(vm, &data.period, &data.quota) < 0)
9778                 goto cleanup;
9779 
9780             if (maxparams > 3 &&
9781                 qemuGetEmulatorBandwidthLive(priv->cgroup, &data.emulator_period,
9782                                              &data.emulator_quota) < 0)
9783                 goto cleanup;
9784 
9785             if (maxparams > 5 &&
9786                 qemuGetGlobalBWLive(priv->cgroup, &data.global_period,
9787                                     &data.global_quota) < 0)
9788                 goto cleanup;
9789 
9790             if (maxparams > 7 &&
9791                 qemuGetIOThreadsBWLive(vm, &data.iothread_period,
9792                                        &data.iothread_quota) < 0)
9793                 goto cleanup;
9794         } else {
9795             cpu_bw_status = false;
9796         }
9797     }
9798 
9799 #define QEMU_SCHED_ASSIGN(param, name, type) \
9800     if (*nparams < maxparams && \
9801         virTypedParameterAssign(&(params[(*nparams)++]), \
9802                                 VIR_DOMAIN_SCHEDULER_ ## name, \
9803                                 VIR_TYPED_PARAM_ ## type, \
9804                                 data.param) < 0) \
9805             goto cleanup
9806 
9807     QEMU_SCHED_ASSIGN(shares, CPU_SHARES, ULLONG);
9808 
9809     if (cpu_bw_status) {
9810         QEMU_SCHED_ASSIGN(period, VCPU_PERIOD, ULLONG);
9811         QEMU_SCHED_ASSIGN(quota, VCPU_QUOTA, LLONG);
9812 
9813         QEMU_SCHED_ASSIGN(emulator_period, EMULATOR_PERIOD, ULLONG);
9814         QEMU_SCHED_ASSIGN(emulator_quota, EMULATOR_QUOTA, LLONG);
9815 
9816         QEMU_SCHED_ASSIGN(global_period, GLOBAL_PERIOD, ULLONG);
9817         QEMU_SCHED_ASSIGN(global_quota, GLOBAL_QUOTA, LLONG);
9818 
9819         QEMU_SCHED_ASSIGN(iothread_period, IOTHREAD_PERIOD, ULLONG);
9820         QEMU_SCHED_ASSIGN(iothread_quota, IOTHREAD_QUOTA, LLONG);
9821     }
9822 
9823 #undef QEMU_SCHED_ASSIGN
9824 
9825     ret = 0;
9826 
9827  cleanup:
9828     virDomainObjEndAPI(&vm);
9829     return ret;
9830 }
9831 
9832 static int
qemuDomainGetSchedulerParameters(virDomainPtr dom,virTypedParameterPtr params,int * nparams)9833 qemuDomainGetSchedulerParameters(virDomainPtr dom,
9834                                  virTypedParameterPtr params,
9835                                  int *nparams)
9836 {
9837     return qemuDomainGetSchedulerParametersFlags(dom, params, nparams,
9838                                                  VIR_DOMAIN_AFFECT_CURRENT);
9839 }
9840 
9841 /**
9842  * Resize a block device while a guest is running. Resize to a lower size
9843  * is supported, but should be used with extreme caution.  Note that it
9844  * only supports to resize image files, it can't resize block devices
9845  * like LVM volumes.
9846  */
9847 static int
qemuDomainBlockResize(virDomainPtr dom,const char * path,unsigned long long size,unsigned int flags)9848 qemuDomainBlockResize(virDomainPtr dom,
9849                       const char *path,
9850                       unsigned long long size,
9851                       unsigned int flags)
9852 {
9853     virQEMUDriver *driver = dom->conn->privateData;
9854     virDomainObj *vm;
9855     qemuDomainObjPrivate *priv;
9856     int ret = -1;
9857     g_autofree char *device = NULL;
9858     const char *nodename = NULL;
9859     virDomainDiskDef *disk = NULL;
9860 
9861     virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
9862 
9863     /* We prefer operating on bytes.  */
9864     if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) {
9865         if (size > ULLONG_MAX / 1024) {
9866             virReportError(VIR_ERR_OVERFLOW,
9867                            _("size must be less than %llu"),
9868                            ULLONG_MAX / 1024);
9869             return -1;
9870         }
9871         size *= 1024;
9872     }
9873 
9874     if (!(vm = qemuDomainObjFromDomain(dom)))
9875         goto cleanup;
9876 
9877     priv = vm->privateData;
9878 
9879     if (virDomainBlockResizeEnsureACL(dom->conn, vm->def) < 0)
9880         goto cleanup;
9881 
9882     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9883         goto cleanup;
9884 
9885     if (virDomainObjCheckActive(vm) < 0)
9886         goto endjob;
9887 
9888     if (!(disk = virDomainDiskByName(vm->def, path, false))) {
9889         virReportError(VIR_ERR_INVALID_ARG,
9890                        _("disk '%s' was not found in the domain config"), path);
9891         goto endjob;
9892     }
9893 
9894     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
9895         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9896                        _("block resize is not supported for vhostuser disk"));
9897         goto endjob;
9898     }
9899 
9900     /* qcow2 and qed must be sized on 512 byte blocks/sectors,
9901      * so adjust size if necessary to round up.
9902      */
9903     if (disk->src->format == VIR_STORAGE_FILE_QCOW2 ||
9904         disk->src->format == VIR_STORAGE_FILE_QED)
9905         size = VIR_ROUND_UP(size, 512);
9906 
9907     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
9908         !qemuDiskBusIsSD(disk->bus)) {
9909         if (virStorageSourceIsEmpty(disk->src) || disk->src->readonly) {
9910             virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
9911                            _("can't resize empty or readonly disk '%s'"),
9912                            disk->dst);
9913             goto endjob;
9914         }
9915 
9916         nodename = disk->src->nodeformat;
9917     } else {
9918         if (!(device = qemuAliasDiskDriveFromDisk(disk)))
9919             goto endjob;
9920     }
9921 
9922     qemuDomainObjEnterMonitor(driver, vm);
9923     if (qemuMonitorBlockResize(priv->mon, device, nodename, size) < 0) {
9924         ignore_value(qemuDomainObjExitMonitor(driver, vm));
9925         goto endjob;
9926     }
9927     if (qemuDomainObjExitMonitor(driver, vm) < 0)
9928         goto endjob;
9929 
9930     ret = 0;
9931 
9932  endjob:
9933     qemuDomainObjEndJob(driver, vm);
9934 
9935  cleanup:
9936     virDomainObjEndAPI(&vm);
9937     return ret;
9938 }
9939 
9940 
9941 static void
qemuDomainBlockStatsGatherTotals(qemuBlockStats * data,qemuBlockStats * total)9942 qemuDomainBlockStatsGatherTotals(qemuBlockStats *data,
9943                                  qemuBlockStats *total)
9944 {
9945     total->wr_bytes += data->wr_bytes;
9946     total->wr_req += data->wr_req;
9947     total->rd_bytes += data->rd_bytes;
9948     total->rd_req += data->rd_req;
9949     total->flush_req += data->flush_req;
9950     total->wr_total_times += data->wr_total_times;
9951     total->rd_total_times += data->rd_total_times;
9952     total->flush_total_times += data->flush_total_times;
9953 }
9954 
9955 
9956 /**
9957  * qemuDomainBlocksStatsGather:
9958  * @driver: driver object
9959  * @vm: domain object
9960  * @path: to gather the statistics for
9961  * @capacity: refresh capacity of the backing image
9962  * @retstats: returns pointer to structure holding the stats
9963  *
9964  * Gathers the block statistics for use in qemuDomainBlockStats* APIs.
9965  *
9966  * Returns -1 on error; number of filled block statistics on success.
9967  */
9968 static int
qemuDomainBlocksStatsGather(virQEMUDriver * driver,virDomainObj * vm,const char * path,bool capacity,qemuBlockStats ** retstats)9969 qemuDomainBlocksStatsGather(virQEMUDriver *driver,
9970                             virDomainObj *vm,
9971                             const char *path,
9972                             bool capacity,
9973                             qemuBlockStats **retstats)
9974 {
9975     qemuDomainObjPrivate *priv = vm->privateData;
9976     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
9977     virDomainDiskDef *disk = NULL;
9978     GHashTable *blockstats = NULL;
9979     qemuBlockStats *stats;
9980     size_t i;
9981     int nstats;
9982     int rc = 0;
9983     const char *entryname = NULL;
9984     int ret = -1;
9985 
9986     if (*path) {
9987         if (!(disk = virDomainDiskByName(vm->def, path, false))) {
9988             virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
9989             goto cleanup;
9990         }
9991 
9992         if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
9993             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9994                            _("block stats are not supported for vhostuser disk"));
9995             goto cleanup;
9996         }
9997 
9998         if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
9999             entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
10000         } else {
10001             if (!disk->info.alias) {
10002                 virReportError(VIR_ERR_INTERNAL_ERROR,
10003                                _("missing disk device alias name for %s"), disk->dst);
10004                 goto cleanup;
10005             }
10006 
10007             entryname = disk->info.alias;
10008         }
10009     }
10010 
10011     qemuDomainObjEnterMonitor(driver, vm);
10012     nstats = qemuMonitorGetAllBlockStatsInfo(priv->mon, &blockstats);
10013 
10014     if (capacity && nstats >= 0) {
10015         if (blockdev)
10016             rc = qemuMonitorBlockStatsUpdateCapacityBlockdev(priv->mon, blockstats);
10017         else
10018             rc = qemuMonitorBlockStatsUpdateCapacity(priv->mon, blockstats);
10019     }
10020 
10021     if (qemuDomainObjExitMonitor(driver, vm) < 0 || nstats < 0 || rc < 0)
10022         goto cleanup;
10023 
10024     *retstats = g_new0(qemuBlockStats, 1);
10025 
10026     if (entryname) {
10027         if (!(stats = virHashLookup(blockstats, entryname))) {
10028             virReportError(VIR_ERR_INTERNAL_ERROR,
10029                            _("cannot find statistics for device '%s'"), entryname);
10030             goto cleanup;
10031         }
10032 
10033         **retstats = *stats;
10034 
10035         if (blockdev) {
10036             /* capacity are reported only per node-name so we need to transfer them */
10037             qemuBlockStats *capstats;
10038 
10039             if (disk && disk->src &&
10040                 (capstats = virHashLookup(blockstats, disk->src->nodeformat))) {
10041                 (*retstats)->capacity = capstats->capacity;
10042                 (*retstats)->physical = capstats->physical;
10043                 (*retstats)->wr_highest_offset = capstats->wr_highest_offset;
10044                 (*retstats)->wr_highest_offset_valid = capstats->wr_highest_offset_valid;
10045                 (*retstats)->write_threshold = capstats->write_threshold;
10046             }
10047         }
10048     } else {
10049         for (i = 0; i < vm->def->ndisks; i++) {
10050             disk = vm->def->disks[i];
10051             entryname = disk->info.alias;
10052 
10053             /* No stats to report for vhost-user disk */
10054             if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER)
10055                 continue;
10056 
10057             if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName)
10058                 entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
10059 
10060             if (!entryname)
10061                 continue;
10062 
10063             if (!(stats = virHashLookup(blockstats, entryname))) {
10064                 virReportError(VIR_ERR_INTERNAL_ERROR,
10065                                _("cannot find statistics for device '%s'"), entryname);
10066                 goto cleanup;
10067             }
10068 
10069             qemuDomainBlockStatsGatherTotals(stats, *retstats);
10070         }
10071     }
10072 
10073     ret = nstats;
10074 
10075  cleanup:
10076     virHashFree(blockstats);
10077     return ret;
10078 }
10079 
10080 
10081 static int
qemuDomainBlockStats(virDomainPtr dom,const char * path,virDomainBlockStatsPtr stats)10082 qemuDomainBlockStats(virDomainPtr dom,
10083                      const char *path,
10084                      virDomainBlockStatsPtr stats)
10085 {
10086     virQEMUDriver *driver = dom->conn->privateData;
10087     qemuBlockStats *blockstats = NULL;
10088     int ret = -1;
10089     virDomainObj *vm;
10090 
10091     if (!(vm = qemuDomainObjFromDomain(dom)))
10092         goto cleanup;
10093 
10094     if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
10095         goto cleanup;
10096 
10097     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
10098         goto cleanup;
10099 
10100     if (virDomainObjCheckActive(vm) < 0)
10101         goto endjob;
10102 
10103     if (qemuDomainBlocksStatsGather(driver, vm, path, false, &blockstats) < 0)
10104         goto endjob;
10105 
10106     if (VIR_ASSIGN_IS_OVERFLOW(stats->rd_req, blockstats->rd_req) ||
10107         VIR_ASSIGN_IS_OVERFLOW(stats->rd_bytes, blockstats->rd_bytes) ||
10108         VIR_ASSIGN_IS_OVERFLOW(stats->wr_req, blockstats->wr_req) ||
10109         VIR_ASSIGN_IS_OVERFLOW(stats->wr_bytes, blockstats->wr_bytes)) {
10110         virReportError(VIR_ERR_OVERFLOW, "%s", _("statistic value too large"));
10111         goto endjob;
10112     }
10113 
10114     /* qemu doesn't report the error count */
10115     stats->errs = -1;
10116 
10117     ret = 0;
10118 
10119  endjob:
10120     qemuDomainObjEndJob(driver, vm);
10121 
10122  cleanup:
10123     virDomainObjEndAPI(&vm);
10124     VIR_FREE(blockstats);
10125     return ret;
10126 }
10127 
10128 
10129 static int
qemuDomainBlockStatsFlags(virDomainPtr dom,const char * path,virTypedParameterPtr params,int * nparams,unsigned int flags)10130 qemuDomainBlockStatsFlags(virDomainPtr dom,
10131                           const char *path,
10132                           virTypedParameterPtr params,
10133                           int *nparams,
10134                           unsigned int flags)
10135 {
10136     virQEMUDriver *driver = dom->conn->privateData;
10137     virDomainObj *vm;
10138     qemuBlockStats *blockstats = NULL;
10139     int nstats;
10140     int ret = -1;
10141 
10142     VIR_DEBUG("params=%p, flags=0x%x", params, flags);
10143 
10144     virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
10145 
10146     /* We don't return strings, and thus trivially support this flag.  */
10147     flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
10148 
10149     if (!(vm = qemuDomainObjFromDomain(dom)))
10150         goto cleanup;
10151 
10152     if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0)
10153         goto cleanup;
10154 
10155     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
10156         goto cleanup;
10157 
10158     if (virDomainObjCheckActive(vm) < 0)
10159         goto endjob;
10160 
10161     if ((nstats = qemuDomainBlocksStatsGather(driver, vm, path, false,
10162                                               &blockstats)) < 0)
10163         goto endjob;
10164 
10165     /* return count of supported stats */
10166     if (*nparams == 0) {
10167         *nparams = nstats;
10168         ret = 0;
10169         goto endjob;
10170     }
10171 
10172     nstats = 0;
10173 
10174 #define QEMU_BLOCK_STATS_ASSIGN_PARAM(VAR, NAME) \
10175     if (nstats < *nparams) { \
10176         long long tmp; \
10177         if (VIR_ASSIGN_IS_OVERFLOW(tmp, (blockstats->VAR))) { \
10178             virReportError(VIR_ERR_OVERFLOW, \
10179                            _("value of '%s' is too large"), NAME); \
10180             goto endjob; \
10181         } \
10182         if (virTypedParameterAssign(params + nstats, NAME, \
10183                                     VIR_TYPED_PARAM_LLONG, tmp) < 0) \
10184             goto endjob; \
10185         nstats++; \
10186     }
10187 
10188     QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES);
10189     QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ);
10190 
10191     QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES);
10192     QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ);
10193 
10194     QEMU_BLOCK_STATS_ASSIGN_PARAM(flush_req, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ);
10195 
10196     QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_total_times,
10197                                   VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES);
10198     QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_total_times,
10199                                   VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES);
10200     QEMU_BLOCK_STATS_ASSIGN_PARAM(flush_total_times,
10201                                   VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES);
10202 #undef QEMU_BLOCK_STATS_ASSIGN_PARAM
10203 
10204     ret = 0;
10205     *nparams = nstats;
10206 
10207  endjob:
10208     qemuDomainObjEndJob(driver, vm);
10209 
10210  cleanup:
10211     VIR_FREE(blockstats);
10212     virDomainObjEndAPI(&vm);
10213     return ret;
10214 }
10215 
10216 static int
qemuDomainInterfaceStats(virDomainPtr dom,const char * device,virDomainInterfaceStatsPtr stats)10217 qemuDomainInterfaceStats(virDomainPtr dom,
10218                          const char *device,
10219                          virDomainInterfaceStatsPtr stats)
10220 {
10221     virDomainObj *vm;
10222     virDomainNetDef *net = NULL;
10223     int ret = -1;
10224 
10225     if (!(vm = qemuDomainObjFromDomain(dom)))
10226         goto cleanup;
10227 
10228     if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0)
10229         goto cleanup;
10230 
10231     if (virDomainObjCheckActive(vm) < 0)
10232         goto cleanup;
10233 
10234     if (!(net = virDomainNetFind(vm->def, device)))
10235         goto cleanup;
10236 
10237     if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
10238         if (virNetDevOpenvswitchInterfaceStats(net->ifname, stats) < 0)
10239             goto cleanup;
10240     } else if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
10241         virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net);
10242         virPCIDeviceAddress *vfAddr;
10243 
10244         if (!hostdev) {
10245             virReportError(VIR_ERR_INTERNAL_ERROR,
10246                            "%s", _("hostdev interface missing hostdev data"));
10247             goto cleanup;
10248         }
10249 
10250         vfAddr = &hostdev->source.subsys.u.pci.addr;
10251         if (virNetDevVFInterfaceStats(vfAddr, stats) < 0)
10252             goto cleanup;
10253 
10254     } else {
10255         if (virNetDevTapInterfaceStats(net->ifname, stats,
10256                                        !virDomainNetTypeSharesHostView(net)) < 0)
10257             goto cleanup;
10258     }
10259 
10260     ret = 0;
10261  cleanup:
10262     virDomainObjEndAPI(&vm);
10263     return ret;
10264 }
10265 
10266 static int
qemuDomainSetInterfaceParameters(virDomainPtr dom,const char * device,virTypedParameterPtr params,int nparams,unsigned int flags)10267 qemuDomainSetInterfaceParameters(virDomainPtr dom,
10268                                  const char *device,
10269                                  virTypedParameterPtr params,
10270                                  int nparams,
10271                                  unsigned int flags)
10272 {
10273     virQEMUDriver *driver = dom->conn->privateData;
10274     size_t i;
10275     virDomainObj *vm = NULL;
10276     virDomainDef *def;
10277     virDomainDef *persistentDef;
10278     int ret = -1;
10279     virDomainNetDef *net = NULL;
10280     virDomainNetDef *persistentNet = NULL;
10281     g_autoptr(virNetDevBandwidth) bandwidth = NULL;
10282     g_autoptr(virNetDevBandwidth) newBandwidth = NULL;
10283     g_autoptr(virQEMUDriverConfig) cfg = NULL;
10284     bool inboundSpecified = false, outboundSpecified = false;
10285     int actualType;
10286     bool qosSupported = true;
10287     bool ovsType = false;
10288 
10289     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10290                   VIR_DOMAIN_AFFECT_CONFIG, -1);
10291     if (virTypedParamsValidate(params, nparams,
10292                                VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
10293                                VIR_TYPED_PARAM_UINT,
10294                                VIR_DOMAIN_BANDWIDTH_IN_PEAK,
10295                                VIR_TYPED_PARAM_UINT,
10296                                VIR_DOMAIN_BANDWIDTH_IN_BURST,
10297                                VIR_TYPED_PARAM_UINT,
10298                                VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
10299                                VIR_TYPED_PARAM_UINT,
10300                                VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
10301                                VIR_TYPED_PARAM_UINT,
10302                                VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
10303                                VIR_TYPED_PARAM_UINT,
10304                                VIR_DOMAIN_BANDWIDTH_OUT_BURST,
10305                                VIR_TYPED_PARAM_UINT,
10306                                NULL) < 0)
10307         return -1;
10308 
10309     if (!(vm = qemuDomainObjFromDomain(dom)))
10310         return -1;
10311 
10312     cfg = virQEMUDriverGetConfig(driver);
10313 
10314     if (virDomainSetInterfaceParametersEnsureACL(dom->conn, vm->def, flags) < 0)
10315         goto cleanup;
10316 
10317     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10318         goto cleanup;
10319 
10320     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10321         goto endjob;
10322 
10323     if (def &&
10324         !(net = virDomainNetFind(vm->def, device)))
10325         goto endjob;
10326 
10327     if (persistentDef &&
10328         !(persistentNet = virDomainNetFind(persistentDef, device)))
10329         goto endjob;
10330 
10331     if (net) {
10332         actualType = virDomainNetGetActualType(net);
10333         qosSupported = virNetDevSupportsBandwidth(actualType);
10334         ovsType = virDomainNetDefIsOvsport(net);
10335     }
10336 
10337     if (qosSupported && persistentNet) {
10338         actualType = virDomainNetGetActualType(persistentNet);
10339         qosSupported = virNetDevSupportsBandwidth(actualType);
10340     }
10341 
10342     if (!qosSupported) {
10343         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10344                        _("setting bandwidth on interfaces of "
10345                          "type '%s' is not implemented yet"),
10346                        virDomainNetTypeToString(actualType));
10347         goto endjob;
10348     }
10349 
10350     bandwidth = g_new0(virNetDevBandwidth, 1);
10351     bandwidth->in = g_new0(virNetDevBandwidthRate, 1);
10352     bandwidth->out = g_new0(virNetDevBandwidthRate, 1);
10353 
10354     for (i = 0; i < nparams; i++) {
10355         virTypedParameterPtr param = &params[i];
10356 
10357         if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE)) {
10358             bandwidth->in->average = param->value.ui;
10359             inboundSpecified = true;
10360         } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_PEAK)) {
10361             bandwidth->in->peak = param->value.ui;
10362         } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_BURST)) {
10363             bandwidth->in->burst = param->value.ui;
10364         } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_FLOOR)) {
10365             bandwidth->in->floor = param->value.ui;
10366             inboundSpecified = true;
10367         } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE)) {
10368             bandwidth->out->average = param->value.ui;
10369             outboundSpecified = true;
10370         } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK)) {
10371             bandwidth->out->peak = param->value.ui;
10372         } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_BURST)) {
10373             bandwidth->out->burst = param->value.ui;
10374         }
10375     }
10376 
10377     /* average or floor are mandatory, peak and burst are optional.
10378      * So if no average or floor is given, we free inbound/outbound
10379      * here which causes inbound/outbound to not be set. */
10380     if (!bandwidth->in->average && !bandwidth->in->floor)
10381         VIR_FREE(bandwidth->in);
10382     if (!bandwidth->out->average)
10383         VIR_FREE(bandwidth->out);
10384 
10385     if (net) {
10386         newBandwidth = g_new0(virNetDevBandwidth, 1);
10387 
10388         /* virNetDevBandwidthSet() will clear any previous value of
10389          * bandwidth parameters, so merge with old bandwidth parameters
10390          * here to prevent them from being lost. */
10391         if (bandwidth->in ||
10392             (!inboundSpecified && net->bandwidth && net->bandwidth->in)) {
10393             newBandwidth->in = g_new0(virNetDevBandwidthRate, 1);
10394 
10395             memcpy(newBandwidth->in,
10396                    bandwidth->in ? bandwidth->in : net->bandwidth->in,
10397                    sizeof(*newBandwidth->in));
10398         }
10399         if (bandwidth->out ||
10400             (!outboundSpecified && net->bandwidth && net->bandwidth->out)) {
10401             newBandwidth->out = g_new0(virNetDevBandwidthRate, 1);
10402 
10403             memcpy(newBandwidth->out,
10404                    bandwidth->out ? bandwidth->out : net->bandwidth->out,
10405                    sizeof(*newBandwidth->out));
10406         }
10407 
10408         if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
10409             if (virDomainNetBandwidthUpdate(net, newBandwidth) < 0)
10410                 goto endjob;
10411         } else {
10412             if (virNetDevBandwidthHasFloor(bandwidth)) {
10413                 char ifmac[VIR_MAC_STRING_BUFLEN];
10414 
10415                 virMacAddrFormat(&net->mac, ifmac);
10416                 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
10417                                _("Invalid use of 'floor' on interface with MAC address %s "
10418                                "- 'floor' is only supported for interface type 'network' with forward type 'nat', 'route', 'open' or none"),
10419                                ifmac);
10420                 goto endjob;
10421             }
10422         }
10423 
10424         if (ovsType) {
10425             if (virNetDevOpenvswitchInterfaceSetQos(net->ifname, newBandwidth,
10426                                                     vm->def->uuid,
10427                                                     !virDomainNetTypeSharesHostView(net)) < 0) {
10428                 virErrorPtr orig_err;
10429 
10430                 virErrorPreserveLast(&orig_err);
10431                 ignore_value(virNetDevOpenvswitchInterfaceSetQos(net->ifname, newBandwidth,
10432                                                                  vm->def->uuid,
10433                                                                  !virDomainNetTypeSharesHostView(net)));
10434                 if (net->bandwidth) {
10435                     ignore_value(virDomainNetBandwidthUpdate(net,
10436                                                              net->bandwidth));
10437                 }
10438                 virErrorRestore(&orig_err);
10439                 goto endjob;
10440             }
10441         } else if (virNetDevBandwidthSet(net->ifname, newBandwidth, false,
10442                                          !virDomainNetTypeSharesHostView(net)) < 0) {
10443             virErrorPtr orig_err;
10444 
10445             virErrorPreserveLast(&orig_err);
10446             ignore_value(virNetDevBandwidthSet(net->ifname,
10447                                                net->bandwidth,
10448                                                false,
10449                                                !virDomainNetTypeSharesHostView(net)));
10450             if (net->bandwidth) {
10451                 ignore_value(virDomainNetBandwidthUpdate(net,
10452                                                          net->bandwidth));
10453             }
10454             virErrorRestore(&orig_err);
10455             goto endjob;
10456         }
10457 
10458         /* If the old bandwidth was cleared out, restore qdisc. */
10459         if (virDomainNetTypeSharesHostView(net)) {
10460             if (!newBandwidth->out || newBandwidth->out->average == 0)
10461                 qemuDomainInterfaceSetDefaultQDisc(driver, net);
10462         } else {
10463             if (!newBandwidth->in || newBandwidth->in->average == 0)
10464                 qemuDomainInterfaceSetDefaultQDisc(driver, net);
10465         }
10466 
10467         virNetDevBandwidthFree(net->bandwidth);
10468         if (newBandwidth->in || newBandwidth->out) {
10469             net->bandwidth = g_steal_pointer(&newBandwidth);
10470         } else {
10471             net->bandwidth = NULL;
10472         }
10473 
10474         if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
10475             virNetDevBandwidthFree(net->data.network.actual->bandwidth);
10476             if (virNetDevBandwidthCopy(&net->data.network.actual->bandwidth,
10477                                        net->bandwidth) < 0)
10478                 goto endjob;
10479         }
10480 
10481         qemuDomainSaveStatus(vm);
10482     }
10483 
10484     if (persistentNet) {
10485         if (!persistentNet->bandwidth) {
10486             persistentNet->bandwidth = g_steal_pointer(&bandwidth);
10487         } else {
10488             if (bandwidth->in) {
10489                 VIR_FREE(persistentNet->bandwidth->in);
10490                 persistentNet->bandwidth->in = bandwidth->in;
10491                 bandwidth->in = NULL;
10492             } else  if (inboundSpecified) {
10493                 VIR_FREE(persistentNet->bandwidth->in);
10494             }
10495             if (bandwidth->out) {
10496                 VIR_FREE(persistentNet->bandwidth->out);
10497                 persistentNet->bandwidth->out = bandwidth->out;
10498                 bandwidth->out = NULL;
10499             } else if (outboundSpecified) {
10500                 VIR_FREE(persistentNet->bandwidth->out);
10501             }
10502         }
10503 
10504         if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
10505             goto endjob;
10506     }
10507 
10508     ret = 0;
10509 
10510  endjob:
10511     qemuDomainObjEndJob(driver, vm);
10512 
10513  cleanup:
10514     virDomainObjEndAPI(&vm);
10515     return ret;
10516 }
10517 
10518 static int
qemuDomainGetInterfaceParameters(virDomainPtr dom,const char * device,virTypedParameterPtr params,int * nparams,unsigned int flags)10519 qemuDomainGetInterfaceParameters(virDomainPtr dom,
10520                                  const char *device,
10521                                  virTypedParameterPtr params,
10522                                  int *nparams,
10523                                  unsigned int flags)
10524 {
10525     size_t i;
10526     virDomainObj *vm = NULL;
10527     virDomainDef *def = NULL;
10528     virDomainNetDef *net = NULL;
10529     int ret = -1;
10530 
10531     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10532                   VIR_DOMAIN_AFFECT_CONFIG |
10533                   VIR_TYPED_PARAM_STRING_OKAY, -1);
10534 
10535     if (!(vm = qemuDomainObjFromDomain(dom)))
10536         return -1;
10537 
10538     if (virDomainGetInterfaceParametersEnsureACL(dom->conn, vm->def) < 0)
10539         goto cleanup;
10540 
10541     if (!(def = virDomainObjGetOneDef(vm, flags)))
10542         goto cleanup;
10543 
10544     if ((*nparams) == 0) {
10545         *nparams = QEMU_NB_BANDWIDTH_PARAM;
10546         ret = 0;
10547         goto cleanup;
10548     }
10549 
10550     if (!(net = virDomainNetFind(def, device)))
10551         goto cleanup;
10552 
10553     for (i = 0; i < *nparams && i < QEMU_NB_BANDWIDTH_PARAM; i++) {
10554         switch (i) {
10555         case 0: /* inbound.average */
10556             if (virTypedParameterAssign(&params[i],
10557                                         VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
10558                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10559                 goto cleanup;
10560             if (net->bandwidth && net->bandwidth->in)
10561                 params[i].value.ui = net->bandwidth->in->average;
10562             break;
10563         case 1: /* inbound.peak */
10564             if (virTypedParameterAssign(&params[i],
10565                                         VIR_DOMAIN_BANDWIDTH_IN_PEAK,
10566                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10567                 goto cleanup;
10568             if (net->bandwidth && net->bandwidth->in)
10569                 params[i].value.ui = net->bandwidth->in->peak;
10570             break;
10571         case 2: /* inbound.burst */
10572             if (virTypedParameterAssign(&params[i],
10573                                         VIR_DOMAIN_BANDWIDTH_IN_BURST,
10574                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10575                 goto cleanup;
10576             if (net->bandwidth && net->bandwidth->in)
10577                 params[i].value.ui = net->bandwidth->in->burst;
10578             break;
10579         case 3: /* inbound.floor */
10580             if (virTypedParameterAssign(&params[i],
10581                                         VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
10582                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10583                 goto cleanup;
10584             if (net->bandwidth && net->bandwidth->in)
10585                 params[i].value.ui = net->bandwidth->in->floor;
10586             break;
10587         case 4: /* outbound.average */
10588             if (virTypedParameterAssign(&params[i],
10589                                         VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
10590                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10591                 goto cleanup;
10592             if (net->bandwidth && net->bandwidth->out)
10593                 params[i].value.ui = net->bandwidth->out->average;
10594             break;
10595         case 5: /* outbound.peak */
10596             if (virTypedParameterAssign(&params[i],
10597                                         VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
10598                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10599                 goto cleanup;
10600             if (net->bandwidth && net->bandwidth->out)
10601                 params[i].value.ui = net->bandwidth->out->peak;
10602             break;
10603         case 6: /* outbound.burst */
10604             if (virTypedParameterAssign(&params[i],
10605                                         VIR_DOMAIN_BANDWIDTH_OUT_BURST,
10606                                         VIR_TYPED_PARAM_UINT, 0) < 0)
10607                 goto cleanup;
10608             if (net->bandwidth && net->bandwidth->out)
10609                 params[i].value.ui = net->bandwidth->out->burst;
10610             break;
10611         default:
10612             break;
10613             /* should not hit here */
10614         }
10615     }
10616 
10617     if (*nparams > QEMU_NB_BANDWIDTH_PARAM)
10618         *nparams = QEMU_NB_BANDWIDTH_PARAM;
10619     ret = 0;
10620 
10621  cleanup:
10622     virDomainObjEndAPI(&vm);
10623     return ret;
10624 }
10625 
10626 /* This functions assumes that job QEMU_JOB_QUERY is started by a caller */
10627 static int
qemuDomainMemoryStatsInternal(virQEMUDriver * driver,virDomainObj * vm,virDomainMemoryStatPtr stats,unsigned int nr_stats)10628 qemuDomainMemoryStatsInternal(virQEMUDriver *driver,
10629                               virDomainObj *vm,
10630                               virDomainMemoryStatPtr stats,
10631                               unsigned int nr_stats)
10632 
10633 {
10634     int ret = -1;
10635     long rss;
10636 
10637     if (virDomainObjCheckActive(vm) < 0)
10638         return -1;
10639 
10640     if (virDomainDefHasMemballoon(vm->def)) {
10641         qemuDomainObjEnterMonitor(driver, vm);
10642         ret = qemuMonitorGetMemoryStats(qemuDomainGetMonitor(vm),
10643                                         vm->def->memballoon, stats, nr_stats);
10644         if (qemuDomainObjExitMonitor(driver, vm) < 0)
10645             ret = -1;
10646 
10647         if (ret < 0 || ret >= nr_stats)
10648             return ret;
10649     } else {
10650         ret = 0;
10651     }
10652 
10653     if (qemuGetProcessInfo(NULL, NULL, &rss, vm->pid, 0) < 0) {
10654         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
10655                        _("cannot get RSS for domain"));
10656     } else {
10657         stats[ret].tag = VIR_DOMAIN_MEMORY_STAT_RSS;
10658         stats[ret].val = rss;
10659         ret++;
10660     }
10661 
10662     return ret;
10663 }
10664 
10665 static int
qemuDomainMemoryStats(virDomainPtr dom,virDomainMemoryStatPtr stats,unsigned int nr_stats,unsigned int flags)10666 qemuDomainMemoryStats(virDomainPtr dom,
10667                       virDomainMemoryStatPtr stats,
10668                       unsigned int nr_stats,
10669                       unsigned int flags)
10670 {
10671     virQEMUDriver *driver = dom->conn->privateData;
10672     virDomainObj *vm;
10673     int ret = -1;
10674 
10675     virCheckFlags(0, -1);
10676 
10677     if (!(vm = qemuDomainObjFromDomain(dom)))
10678         goto cleanup;
10679 
10680     if (virDomainMemoryStatsEnsureACL(dom->conn, vm->def) < 0)
10681         goto cleanup;
10682 
10683     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
10684         goto cleanup;
10685 
10686     ret = qemuDomainMemoryStatsInternal(driver, vm, stats, nr_stats);
10687 
10688     qemuDomainObjEndJob(driver, vm);
10689 
10690  cleanup:
10691     virDomainObjEndAPI(&vm);
10692     return ret;
10693 }
10694 
10695 static int
qemuDomainBlockPeek(virDomainPtr dom,const char * path,unsigned long long offset,size_t size,void * buffer,unsigned int flags)10696 qemuDomainBlockPeek(virDomainPtr dom,
10697                     const char *path,
10698                     unsigned long long offset, size_t size,
10699                     void *buffer,
10700                     unsigned int flags)
10701 {
10702     virQEMUDriver *driver = dom->conn->privateData;
10703     virDomainDiskDef *disk = NULL;
10704     virDomainObj *vm;
10705     g_autofree char *tmpbuf = NULL;
10706     ssize_t nread;
10707     int ret = -1;
10708 
10709     virCheckFlags(0, -1);
10710 
10711     if (!(vm = qemuDomainObjFromDomain(dom)))
10712         goto cleanup;
10713 
10714     if (virDomainBlockPeekEnsureACL(dom->conn, vm->def) < 0)
10715         goto cleanup;
10716 
10717     if (!(disk = qemuDomainDiskByName(vm->def, path)))
10718         goto cleanup;
10719 
10720     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
10721         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
10722                        _("peeking is not supported for vhostuser disk"));
10723         goto cleanup;
10724     }
10725 
10726     if (disk->src->format != VIR_STORAGE_FILE_RAW) {
10727         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
10728                        _("peeking is only supported for disk with 'raw' format not '%s'"),
10729                        virStorageFileFormatTypeToString(disk->src->format));
10730         goto cleanup;
10731     }
10732 
10733     if (qemuDomainStorageFileInit(driver, vm, disk->src, NULL) < 0)
10734         goto cleanup;
10735 
10736     if ((nread = virStorageSourceRead(disk->src, offset, size, &tmpbuf)) < 0) {
10737         if (nread == -2) {
10738             virReportError(VIR_ERR_INTERNAL_ERROR,
10739                            _("storage file reading is not supported for "
10740                              "storage type %s (protocol: %s)"),
10741                            virStorageTypeToString(disk->src->type),
10742                            virStorageNetProtocolTypeToString(disk->src->protocol));
10743         }
10744         goto cleanup;
10745     }
10746 
10747     if (nread < size) {
10748         virReportError(VIR_ERR_INVALID_ARG,
10749                        _("'%s' starting from %llu has only %zd bytes available"),
10750                        path, offset, nread);
10751         goto cleanup;
10752     }
10753 
10754     memcpy(buffer, tmpbuf, size);
10755 
10756     ret = 0;
10757 
10758  cleanup:
10759     if (disk)
10760         virStorageSourceDeinit(disk->src);
10761     virDomainObjEndAPI(&vm);
10762     return ret;
10763 }
10764 
10765 static int
qemuDomainMemoryPeek(virDomainPtr dom,unsigned long long offset,size_t size,void * buffer,unsigned int flags)10766 qemuDomainMemoryPeek(virDomainPtr dom,
10767                      unsigned long long offset, size_t size,
10768                      void *buffer,
10769                      unsigned int flags)
10770 {
10771     virQEMUDriver *driver = dom->conn->privateData;
10772     virDomainObj *vm;
10773     g_autofree char *tmp = NULL;
10774     int fd = -1, ret = -1;
10775     qemuDomainObjPrivate *priv;
10776 
10777     virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);
10778 
10779     if (!(vm = qemuDomainObjFromDomain(dom)))
10780         goto cleanup;
10781 
10782     priv = vm->privateData;
10783 
10784     if (virDomainMemoryPeekEnsureACL(dom->conn, vm->def) < 0)
10785         goto cleanup;
10786 
10787     if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
10788         virReportError(VIR_ERR_INVALID_ARG,
10789                        "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
10790         goto cleanup;
10791     }
10792 
10793     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
10794         goto cleanup;
10795 
10796     if (virDomainObjCheckActive(vm) < 0)
10797         goto endjob;
10798 
10799     tmp = g_strdup_printf("%s/qemu.mem.XXXXXX", priv->libDir);
10800 
10801     /* Create a temporary filename. */
10802     if ((fd = g_mkstemp_full(tmp, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) {
10803         virReportSystemError(errno,
10804                              _("g_mkstemp(\"%s\") failed"), tmp);
10805         goto endjob;
10806     }
10807 
10808     qemuSecurityDomainSetPathLabel(driver, vm, tmp, false);
10809 
10810     qemuDomainObjEnterMonitor(driver, vm);
10811     if (flags == VIR_MEMORY_VIRTUAL) {
10812         if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
10813             ignore_value(qemuDomainObjExitMonitor(driver, vm));
10814             goto endjob;
10815         }
10816     } else {
10817         if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
10818             ignore_value(qemuDomainObjExitMonitor(driver, vm));
10819             goto endjob;
10820         }
10821     }
10822     if (qemuDomainObjExitMonitor(driver, vm) < 0)
10823         goto endjob;
10824 
10825     /* Read the memory file into buffer. */
10826     if (saferead(fd, buffer, size) == (ssize_t)-1) {
10827         virReportSystemError(errno,
10828                              _("failed to read temporary file "
10829                                "created with template %s"), tmp);
10830         goto endjob;
10831     }
10832 
10833     ret = 0;
10834 
10835  endjob:
10836     qemuDomainObjEndJob(driver, vm);
10837 
10838  cleanup:
10839     VIR_FORCE_CLOSE(fd);
10840     if (tmp)
10841         unlink(tmp);
10842     virDomainObjEndAPI(&vm);
10843     return ret;
10844 }
10845 
10846 
10847 /**
10848  * @driver: qemu driver data
10849  * @cfg: driver configuration data
10850  * @vm: domain object
10851  * @src: storage source data
10852  * @ret_fd: pointer to return open'd file descriptor
10853  * @ret_sb: pointer to return stat buffer (local or remote)
10854  * @skipInaccessible: Don't report error if files are not accessible
10855  *
10856  * For local storage, open the file using qemuDomainOpenFile and then use
10857  * fstat() to grab the stat struct data for the caller.
10858  *
10859  * For remote storage, attempt to access the file and grab the stat
10860  * struct data if the remote connection supports it.
10861  *
10862  * Returns 1 if @src was successfully opened (@ret_fd and @ret_sb is populated),
10863  * 0 if @src can't be opened and @skipInaccessible is true (no errors are
10864  * reported) or -1 otherwise (errors are reported).
10865  */
10866 static int
qemuDomainStorageOpenStat(virQEMUDriver * driver G_GNUC_UNUSED,virQEMUDriverConfig * cfg,virDomainObj * vm,virStorageSource * src,int * ret_fd,struct stat * ret_sb,bool skipInaccessible)10867 qemuDomainStorageOpenStat(virQEMUDriver *driver G_GNUC_UNUSED,
10868                           virQEMUDriverConfig *cfg,
10869                           virDomainObj *vm,
10870                           virStorageSource *src,
10871                           int *ret_fd,
10872                           struct stat *ret_sb,
10873                           bool skipInaccessible)
10874 {
10875     if (virStorageSourceIsLocalStorage(src)) {
10876         if (skipInaccessible && !virFileExists(src->path))
10877             return 0;
10878 
10879         if ((*ret_fd = qemuDomainOpenFile(cfg, vm->def, src->path, O_RDONLY,
10880                                           NULL)) < 0)
10881             return -1;
10882 
10883         if (fstat(*ret_fd, ret_sb) < 0) {
10884             virReportSystemError(errno, _("cannot stat file '%s'"), src->path);
10885             VIR_FORCE_CLOSE(*ret_fd);
10886             return -1;
10887         }
10888     } else {
10889         if (skipInaccessible && virStorageSourceSupportsBackingChainTraversal(src) <= 0)
10890             return 0;
10891 
10892         if (virStorageSourceInitAs(src, cfg->user, cfg->group) < 0)
10893             return -1;
10894 
10895         if (virStorageSourceStat(src, ret_sb) < 0) {
10896             virStorageSourceDeinit(src);
10897             virReportSystemError(errno, _("failed to stat remote file '%s'"),
10898                                  NULLSTR(src->path));
10899             return -1;
10900         }
10901     }
10902 
10903     return 1;
10904 }
10905 
10906 
10907 /**
10908  * @src: storage source data
10909  * @fd: file descriptor to close for local
10910  *
10911  * If local, then just close the file descriptor.
10912  * else remote, then tear down the storage driver backend connection.
10913  */
10914 static void
qemuDomainStorageCloseStat(virStorageSource * src,int * fd)10915 qemuDomainStorageCloseStat(virStorageSource *src,
10916                            int *fd)
10917 {
10918     if (virStorageSourceIsLocalStorage(src))
10919         VIR_FORCE_CLOSE(*fd);
10920     else
10921         virStorageSourceDeinit(src);
10922 }
10923 
10924 
10925 /**
10926  * qemuDomainStorageUpdatePhysical:
10927  * @driver: qemu driver
10928  * @cfg: qemu driver configuration object
10929  * @vm: domain object
10930  * @src: storage source to update
10931  *
10932  * Update the physical size of the disk by reading the actual size of the image
10933  * on disk.
10934  *
10935  * Returns 0 on successful update and -1 otherwise (some uncommon errors may be
10936  * reported but are reset (thus only logged)).
10937  */
10938 static int
qemuDomainStorageUpdatePhysical(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * vm,virStorageSource * src)10939 qemuDomainStorageUpdatePhysical(virQEMUDriver *driver,
10940                                 virQEMUDriverConfig *cfg,
10941                                 virDomainObj *vm,
10942                                 virStorageSource *src)
10943 {
10944     int ret;
10945     int fd = -1;
10946     struct stat sb;
10947 
10948     if (virStorageSourceIsEmpty(src))
10949         return 0;
10950 
10951     if ((ret = qemuDomainStorageOpenStat(driver, cfg, vm, src, &fd, &sb, true)) <= 0) {
10952         if (ret < 0)
10953             virResetLastError();
10954         return -1;
10955     }
10956 
10957     ret = virStorageSourceUpdatePhysicalSize(src, fd, &sb);
10958 
10959     qemuDomainStorageCloseStat(src, &fd);
10960 
10961     return ret;
10962 }
10963 
10964 
10965 /**
10966  * @driver: qemu driver data
10967  * @cfg: driver configuration data
10968  * @vm: domain object
10969  * @src: storage source data
10970  * @skipInaccessible: Suppress reporting of common errors when accessing @src
10971  *
10972  * Refresh the capacity and allocation limits of a given storage source.
10973  *
10974  * Assumes that the caller has already obtained a domain job and only
10975  * called for an offline domain. Being offline is particularly important
10976  * since reading a file while qemu is writing it risks the reader seeing
10977  * bogus data or avoiding opening a file in order to get stat data.
10978  *
10979  * We always want to check current on-disk statistics (as users have been
10980  * known to change offline images behind our backs).
10981  *
10982  * For read-only disks, nothing should be changing unless the user has
10983  * requested a block-commit action.  For read-write disks, we know some
10984  * special cases: capacity should not change without a block-resize (where
10985  * capacity is the only stat that requires reading a file, and even then,
10986  * only for non-raw files); and physical size of a raw image or of a
10987  * block device should likewise not be changing without block-resize.
10988  * On the other hand, allocation of a raw file can change (if the file
10989  * is sparse, but the amount of sparseness changes due to writes or
10990  * punching holes), and physical size of a non-raw file can change.
10991  *
10992  * Returns 1 if @src was successfully updated, 0 if @src can't be opened and
10993  * @skipInaccessible is true (no errors are reported) or -1 otherwise (errors
10994  * are reported).
10995  */
10996 static int
qemuStorageLimitsRefresh(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * vm,virStorageSource * src,bool skipInaccessible)10997 qemuStorageLimitsRefresh(virQEMUDriver *driver,
10998                          virQEMUDriverConfig *cfg,
10999                          virDomainObj *vm,
11000                          virStorageSource *src,
11001                          bool skipInaccessible)
11002 {
11003     int rc;
11004     int ret = -1;
11005     int fd = -1;
11006     struct stat sb;
11007     g_autofree char *buf = NULL;
11008     ssize_t len;
11009 
11010     if ((rc = qemuDomainStorageOpenStat(driver, cfg, vm, src, &fd, &sb,
11011                                         skipInaccessible)) <= 0)
11012         return rc;
11013 
11014     if (virStorageSourceIsLocalStorage(src)) {
11015         if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
11016             virReportSystemError(errno, _("cannot read header '%s'"),
11017                                  src->path);
11018             goto cleanup;
11019         }
11020     } else {
11021         if ((len = virStorageSourceRead(src, 0, VIR_STORAGE_MAX_HEADER, &buf)) < 0)
11022             goto cleanup;
11023     }
11024 
11025     if (virStorageSourceUpdateBackingSizes(src, fd, &sb) < 0)
11026         goto cleanup;
11027 
11028     if (virStorageSourceUpdateCapacity(src, buf, len) < 0)
11029         goto cleanup;
11030 
11031     /* If guest is not using raw disk format and is on a host block
11032      * device, then leave the value unspecified, so caller knows to
11033      * query the highest allocated extent from QEMU
11034      */
11035     if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK &&
11036         src->format != VIR_STORAGE_FILE_RAW &&
11037         S_ISBLK(sb.st_mode))
11038         src->allocation = 0;
11039 
11040     ret = 1;
11041 
11042  cleanup:
11043     qemuDomainStorageCloseStat(src, &fd);
11044     return ret;
11045 }
11046 
11047 
11048 static int
qemuDomainGetBlockInfo(virDomainPtr dom,const char * path,virDomainBlockInfoPtr info,unsigned int flags)11049 qemuDomainGetBlockInfo(virDomainPtr dom,
11050                        const char *path,
11051                        virDomainBlockInfoPtr info,
11052                        unsigned int flags)
11053 {
11054     virQEMUDriver *driver = dom->conn->privateData;
11055     virDomainObj *vm;
11056     int ret = -1;
11057     virDomainDiskDef *disk;
11058     g_autoptr(virQEMUDriverConfig) cfg = NULL;
11059     qemuBlockStats *entry = NULL;
11060 
11061     virCheckFlags(0, -1);
11062 
11063     if (!(vm = qemuDomainObjFromDomain(dom)))
11064         return -1;
11065 
11066     cfg = virQEMUDriverGetConfig(driver);
11067 
11068     if (virDomainGetBlockInfoEnsureACL(dom->conn, vm->def) < 0)
11069         goto cleanup;
11070 
11071     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
11072         goto cleanup;
11073 
11074     if (!(disk = virDomainDiskByName(vm->def, path, false))) {
11075         virReportError(VIR_ERR_INVALID_ARG,
11076                        _("invalid path %s not assigned to domain"), path);
11077         goto endjob;
11078     }
11079 
11080     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
11081         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
11082                        _("block info is not supported for vhostuser disk"));
11083         goto endjob;
11084     }
11085 
11086     if (virStorageSourceIsEmpty(disk->src)) {
11087         virReportError(VIR_ERR_INVALID_ARG,
11088                        _("disk '%s' does not currently have a source assigned"),
11089                        path);
11090         goto endjob;
11091     }
11092 
11093     /* for inactive domains we have to peek into the files */
11094     if (!virDomainObjIsActive(vm)) {
11095         if ((qemuStorageLimitsRefresh(driver, cfg, vm, disk->src, false)) < 0)
11096             goto endjob;
11097 
11098         info->capacity = disk->src->capacity;
11099         info->allocation = disk->src->allocation;
11100         info->physical = disk->src->physical;
11101 
11102         ret = 0;
11103         goto endjob;
11104     }
11105 
11106     if (qemuDomainBlocksStatsGather(driver, vm, path, true, &entry) < 0)
11107         goto endjob;
11108 
11109     if (!entry->wr_highest_offset_valid) {
11110         info->allocation = entry->physical;
11111     } else {
11112         if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_FILE &&
11113             disk->src->format == VIR_STORAGE_FILE_QCOW2)
11114             info->allocation = entry->physical;
11115         else
11116             info->allocation = entry->wr_highest_offset;
11117     }
11118 
11119     /* Unlike GetStatsBlock, this API has defined the expected return values
11120      * for allocation and physical slightly differently.
11121      *
11122      * Having a zero for either or if they're the same is an indication that
11123      * there's a sparse file backing this device. In this case, we'll force
11124      * the setting of physical based on the on disk file size.
11125      *
11126      * Additionally, if qemu hasn't written to the file yet, then set the
11127      * allocation to whatever qemu returned for physical (e.g. the "actual-
11128      * size" from the json query) as that will match the expected allocation
11129      * value for this API. NB: May still be 0 for block. */
11130     if (entry->physical == 0 || info->allocation == 0 ||
11131         info->allocation == entry->physical) {
11132         if (info->allocation == 0)
11133             info->allocation = entry->physical;
11134 
11135         if (qemuDomainStorageUpdatePhysical(driver, cfg, vm, disk->src) == 0) {
11136             info->physical = disk->src->physical;
11137         } else {
11138             info->physical = entry->physical;
11139         }
11140     } else {
11141         info->physical = entry->physical;
11142     }
11143 
11144     info->capacity = entry->capacity;
11145 
11146     ret = 0;
11147 
11148  endjob:
11149     qemuDomainObjEndJob(driver, vm);
11150  cleanup:
11151     VIR_FREE(entry);
11152     virDomainObjEndAPI(&vm);
11153     return ret;
11154 }
11155 
11156 
11157 static int
qemuConnectDomainEventRegister(virConnectPtr conn,virConnectDomainEventCallback callback,void * opaque,virFreeCallback freecb)11158 qemuConnectDomainEventRegister(virConnectPtr conn,
11159                                virConnectDomainEventCallback callback,
11160                                void *opaque,
11161                                virFreeCallback freecb)
11162 {
11163     virQEMUDriver *driver = conn->privateData;
11164 
11165     if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
11166         return -1;
11167 
11168     if (virDomainEventStateRegister(conn,
11169                                     driver->domainEventState,
11170                                     callback, opaque, freecb) < 0)
11171         return -1;
11172 
11173     return 0;
11174 }
11175 
11176 
11177 static int
qemuConnectDomainEventDeregister(virConnectPtr conn,virConnectDomainEventCallback callback)11178 qemuConnectDomainEventDeregister(virConnectPtr conn,
11179                                  virConnectDomainEventCallback callback)
11180 {
11181     virQEMUDriver *driver = conn->privateData;
11182 
11183     if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
11184         return -1;
11185 
11186     if (virDomainEventStateDeregister(conn,
11187                                       driver->domainEventState,
11188                                       callback) < 0)
11189         return -1;
11190 
11191     return 0;
11192 }
11193 
11194 
11195 static int
qemuConnectDomainEventRegisterAny(virConnectPtr conn,virDomainPtr dom,int eventID,virConnectDomainEventGenericCallback callback,void * opaque,virFreeCallback freecb)11196 qemuConnectDomainEventRegisterAny(virConnectPtr conn,
11197                                   virDomainPtr dom,
11198                                   int eventID,
11199                                   virConnectDomainEventGenericCallback callback,
11200                                   void *opaque,
11201                                   virFreeCallback freecb)
11202 {
11203     virQEMUDriver *driver = conn->privateData;
11204     int ret = -1;
11205 
11206     if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
11207         return -1;
11208 
11209     if (virDomainEventStateRegisterID(conn,
11210                                       driver->domainEventState,
11211                                       dom, eventID,
11212                                       callback, opaque, freecb, &ret) < 0)
11213         ret = -1;
11214 
11215     return ret;
11216 }
11217 
11218 
11219 static int
qemuConnectDomainEventDeregisterAny(virConnectPtr conn,int callbackID)11220 qemuConnectDomainEventDeregisterAny(virConnectPtr conn,
11221                                     int callbackID)
11222 {
11223     virQEMUDriver *driver = conn->privateData;
11224 
11225     if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
11226         return -1;
11227 
11228     if (virObjectEventStateDeregisterID(conn,
11229                                         driver->domainEventState,
11230                                         callbackID, true) < 0)
11231         return -1;
11232 
11233     return 0;
11234 }
11235 
11236 
11237 /*******************************************************************
11238  * Migration Protocol Version 2
11239  *******************************************************************/
11240 
11241 /* Prepare is the first step, and it runs on the destination host.
11242  *
11243  * This version starts an empty VM listening on a localhost TCP port, and
11244  * sets up the corresponding virStream to handle the incoming data.
11245  */
11246 static int
qemuDomainMigratePrepareTunnel(virConnectPtr dconn,virStreamPtr st,unsigned long flags,const char * dname,unsigned long resource G_GNUC_UNUSED,const char * dom_xml)11247 qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
11248                                virStreamPtr st,
11249                                unsigned long flags,
11250                                const char *dname,
11251                                unsigned long resource G_GNUC_UNUSED,
11252                                const char *dom_xml)
11253 {
11254     virQEMUDriver *driver = dconn->privateData;
11255     g_autoptr(virDomainDef) def = NULL;
11256     g_autofree char *origname = NULL;
11257     g_autoptr(qemuMigrationParams) migParams = NULL;
11258 
11259     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11260 
11261     if (!(flags & VIR_MIGRATE_TUNNELLED)) {
11262         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11263                        _("PrepareTunnel called but no TUNNELLED flag set"));
11264         return -1;
11265     }
11266 
11267     if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
11268                                                    QEMU_MIGRATION_DESTINATION)))
11269         return -1;
11270 
11271     if (virLockManagerPluginUsesState(driver->lockManager)) {
11272         virReportError(VIR_ERR_INTERNAL_ERROR,
11273                        _("Cannot use migrate v2 protocol with lock manager %s"),
11274                        virLockManagerPluginGetName(driver->lockManager));
11275         return -1;
11276     }
11277 
11278     if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
11279         return -1;
11280 
11281     if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0)
11282         return -1;
11283 
11284     return qemuMigrationDstPrepareTunnel(driver, dconn,
11285                                          NULL, 0, NULL, NULL, /* No cookies in v2 */
11286                                          st, &def, origname, migParams, flags);
11287 }
11288 
11289 /* Prepare is the first step, and it runs on the destination host.
11290  *
11291  * This starts an empty VM listening on a TCP port.
11292  */
11293 static int ATTRIBUTE_NONNULL(5)
qemuDomainMigratePrepare2(virConnectPtr dconn,char ** cookie G_GNUC_UNUSED,int * cookielen G_GNUC_UNUSED,const char * uri_in,char ** uri_out,unsigned long flags,const char * dname,unsigned long resource G_GNUC_UNUSED,const char * dom_xml)11294 qemuDomainMigratePrepare2(virConnectPtr dconn,
11295                           char **cookie G_GNUC_UNUSED,
11296                           int *cookielen G_GNUC_UNUSED,
11297                           const char *uri_in,
11298                           char **uri_out,
11299                           unsigned long flags,
11300                           const char *dname,
11301                           unsigned long resource G_GNUC_UNUSED,
11302                           const char *dom_xml)
11303 {
11304     virQEMUDriver *driver = dconn->privateData;
11305     g_autoptr(virDomainDef) def = NULL;
11306     g_autofree char *origname = NULL;
11307     g_autoptr(qemuMigrationParams) migParams = NULL;
11308 
11309     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11310 
11311     if (flags & VIR_MIGRATE_TUNNELLED) {
11312         /* this is a logical error; we never should have gotten here with
11313          * VIR_MIGRATE_TUNNELLED set
11314          */
11315         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11316                        _("Tunnelled migration requested but invalid "
11317                          "RPC method called"));
11318         return -1;
11319     }
11320 
11321     if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
11322                                                    QEMU_MIGRATION_DESTINATION)))
11323         return -1;
11324 
11325     if (virLockManagerPluginUsesState(driver->lockManager)) {
11326         virReportError(VIR_ERR_INTERNAL_ERROR,
11327                        _("Cannot use migrate v2 protocol with lock manager %s"),
11328                        virLockManagerPluginGetName(driver->lockManager));
11329         return -1;
11330     }
11331 
11332     if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
11333         return -1;
11334 
11335     if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0)
11336         return -1;
11337 
11338     /* Do not use cookies in v2 protocol, since the cookie
11339      * length was not sufficiently large, causing failures
11340      * migrating between old & new libvirtd
11341      */
11342     return qemuMigrationDstPrepareDirect(driver, dconn,
11343                                          NULL, 0, NULL, NULL, /* No cookies */
11344                                          uri_in, uri_out,
11345                                          &def, origname, NULL, 0, NULL, 0, NULL,
11346                                          migParams, flags);
11347 }
11348 
11349 
11350 /* Perform is the second step, and it runs on the source host. */
11351 static int
qemuDomainMigratePerform(virDomainPtr dom,const char * cookie,int cookielen,const char * uri,unsigned long flags,const char * dname,unsigned long resource)11352 qemuDomainMigratePerform(virDomainPtr dom,
11353                          const char *cookie,
11354                          int cookielen,
11355                          const char *uri,
11356                          unsigned long flags,
11357                          const char *dname,
11358                          unsigned long resource)
11359 {
11360     virQEMUDriver *driver = dom->conn->privateData;
11361     virDomainObj *vm = NULL;
11362     int ret = -1;
11363     const char *dconnuri = NULL;
11364     g_autoptr(qemuMigrationParams) migParams = NULL;
11365 
11366     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11367 
11368     if (virLockManagerPluginUsesState(driver->lockManager)) {
11369         virReportError(VIR_ERR_INTERNAL_ERROR,
11370                        _("Cannot use migrate v2 protocol with lock manager %s"),
11371                        virLockManagerPluginGetName(driver->lockManager));
11372         goto cleanup;
11373     }
11374 
11375     if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
11376                                                    QEMU_MIGRATION_SOURCE)))
11377         goto cleanup;
11378 
11379     if (!(vm = qemuDomainObjFromDomain(dom)))
11380         goto cleanup;
11381 
11382     if (virDomainMigratePerformEnsureACL(dom->conn, vm->def) < 0)
11383         goto cleanup;
11384 
11385     if (flags & VIR_MIGRATE_PEER2PEER)
11386         dconnuri = g_steal_pointer(&uri);
11387 
11388     /* Do not output cookies in v2 protocol, since the cookie
11389      * length was not sufficiently large, causing failures
11390      * migrating between old & new libvirtd.
11391      *
11392      * Consume any cookie we were able to decode though
11393      */
11394     ret = qemuMigrationSrcPerform(driver, dom->conn, vm, NULL,
11395                                   NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0,
11396                                   NULL,
11397                                   migParams, cookie, cookielen,
11398                                   NULL, NULL, /* No output cookies in v2 */
11399                                   flags, dname, resource, false);
11400 
11401  cleanup:
11402     virDomainObjEndAPI(&vm);
11403     return ret;
11404 }
11405 
11406 
11407 /* Finish is the third and final step, and it runs on the destination host. */
11408 static virDomainPtr
qemuDomainMigrateFinish2(virConnectPtr dconn,const char * dname,const char * cookie G_GNUC_UNUSED,int cookielen G_GNUC_UNUSED,const char * uri G_GNUC_UNUSED,unsigned long flags,int retcode)11409 qemuDomainMigrateFinish2(virConnectPtr dconn,
11410                          const char *dname,
11411                          const char *cookie G_GNUC_UNUSED,
11412                          int cookielen G_GNUC_UNUSED,
11413                          const char *uri G_GNUC_UNUSED,
11414                          unsigned long flags,
11415                          int retcode)
11416 {
11417     virQEMUDriver *driver = dconn->privateData;
11418     virDomainObj *vm;
11419 
11420     virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
11421 
11422     vm = virDomainObjListFindByName(driver->domains, dname);
11423     if (!vm) {
11424         virReportError(VIR_ERR_NO_DOMAIN,
11425                        _("no domain with matching name '%s'"), dname);
11426         qemuMigrationDstErrorReport(driver, dname);
11427         return NULL;
11428     }
11429 
11430     if (virDomainMigrateFinish2EnsureACL(dconn, vm->def) < 0) {
11431         virDomainObjEndAPI(&vm);
11432         return NULL;
11433     }
11434 
11435     /* Do not use cookies in v2 protocol, since the cookie
11436      * length was not sufficiently large, causing failures
11437      * migrating between old & new libvirtd
11438      */
11439     return qemuMigrationDstFinish(driver, dconn, vm,
11440                                   NULL, 0, NULL, NULL, /* No cookies */
11441                                   flags, retcode, false);
11442 }
11443 
11444 
11445 /*******************************************************************
11446  * Migration Protocol Version 3
11447  *******************************************************************/
11448 
11449 static char *
qemuDomainMigrateBegin3(virDomainPtr domain,const char * xmlin,char ** cookieout,int * cookieoutlen,unsigned long flags,const char * dname,unsigned long resource G_GNUC_UNUSED)11450 qemuDomainMigrateBegin3(virDomainPtr domain,
11451                         const char *xmlin,
11452                         char **cookieout,
11453                         int *cookieoutlen,
11454                         unsigned long flags,
11455                         const char *dname,
11456                         unsigned long resource G_GNUC_UNUSED)
11457 {
11458     virDomainObj *vm;
11459 
11460     virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
11461 
11462     if (!(vm = qemuDomainObjFromDomain(domain)))
11463         return NULL;
11464 
11465     if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) {
11466         virDomainObjEndAPI(&vm);
11467         return NULL;
11468     }
11469 
11470     return qemuMigrationSrcBegin(domain->conn, vm, xmlin, dname,
11471                                  cookieout, cookieoutlen, 0, NULL, flags);
11472 }
11473 
11474 static char *
qemuDomainMigrateBegin3Params(virDomainPtr domain,virTypedParameterPtr params,int nparams,char ** cookieout,int * cookieoutlen,unsigned int flags)11475 qemuDomainMigrateBegin3Params(virDomainPtr domain,
11476                               virTypedParameterPtr params,
11477                               int nparams,
11478                               char **cookieout,
11479                               int *cookieoutlen,
11480                               unsigned int flags)
11481 {
11482     const char *xmlin = NULL;
11483     const char *dname = NULL;
11484     g_autofree const char **migrate_disks = NULL;
11485     int nmigrate_disks;
11486     virDomainObj *vm;
11487 
11488     virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
11489     if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
11490         return NULL;
11491 
11492     if (virTypedParamsGetString(params, nparams,
11493                                 VIR_MIGRATE_PARAM_DEST_XML,
11494                                 &xmlin) < 0 ||
11495         virTypedParamsGetString(params, nparams,
11496                                 VIR_MIGRATE_PARAM_DEST_NAME,
11497                                 &dname) < 0)
11498         return NULL;
11499 
11500     nmigrate_disks = virTypedParamsGetStringList(params, nparams,
11501                                                  VIR_MIGRATE_PARAM_MIGRATE_DISKS,
11502                                                  &migrate_disks);
11503 
11504     if (nmigrate_disks < 0)
11505         return NULL;
11506 
11507     if (!(vm = qemuDomainObjFromDomain(domain)))
11508         return NULL;
11509 
11510     if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) {
11511         virDomainObjEndAPI(&vm);
11512         return NULL;
11513     }
11514 
11515     return qemuMigrationSrcBegin(domain->conn, vm, xmlin, dname,
11516                                  cookieout, cookieoutlen,
11517                                  nmigrate_disks, migrate_disks, flags);
11518 }
11519 
11520 
11521 static int
qemuDomainMigratePrepare3(virConnectPtr dconn,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,const char * uri_in,char ** uri_out,unsigned long flags,const char * dname,unsigned long resource G_GNUC_UNUSED,const char * dom_xml)11522 qemuDomainMigratePrepare3(virConnectPtr dconn,
11523                           const char *cookiein,
11524                           int cookieinlen,
11525                           char **cookieout,
11526                           int *cookieoutlen,
11527                           const char *uri_in,
11528                           char **uri_out,
11529                           unsigned long flags,
11530                           const char *dname,
11531                           unsigned long resource G_GNUC_UNUSED,
11532                           const char *dom_xml)
11533 {
11534     virQEMUDriver *driver = dconn->privateData;
11535     g_autoptr(virDomainDef) def = NULL;
11536     g_autofree char *origname = NULL;
11537     g_autoptr(qemuMigrationParams) migParams = NULL;
11538 
11539     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11540 
11541     if (flags & VIR_MIGRATE_TUNNELLED) {
11542         /* this is a logical error; we never should have gotten here with
11543          * VIR_MIGRATE_TUNNELLED set
11544          */
11545         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11546                        _("Tunnelled migration requested but invalid "
11547                          "RPC method called"));
11548         return -1;
11549     }
11550 
11551     if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
11552                                                    QEMU_MIGRATION_DESTINATION)))
11553         return -1;
11554 
11555     if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
11556         return -1;
11557 
11558     if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0)
11559         return -1;
11560 
11561     return qemuMigrationDstPrepareDirect(driver, dconn,
11562                                          cookiein, cookieinlen,
11563                                          cookieout, cookieoutlen,
11564                                          uri_in, uri_out,
11565                                          &def, origname, NULL, 0, NULL, 0,
11566                                          NULL, migParams, flags);
11567 }
11568 
11569 static int
qemuDomainMigratePrepare3Params(virConnectPtr dconn,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,char ** uri_out,unsigned int flags)11570 qemuDomainMigratePrepare3Params(virConnectPtr dconn,
11571                                 virTypedParameterPtr params,
11572                                 int nparams,
11573                                 const char *cookiein,
11574                                 int cookieinlen,
11575                                 char **cookieout,
11576                                 int *cookieoutlen,
11577                                 char **uri_out,
11578                                 unsigned int flags)
11579 {
11580     virQEMUDriver *driver = dconn->privateData;
11581     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
11582     g_autoptr(virDomainDef) def = NULL;
11583     const char *dom_xml = NULL;
11584     const char *dname = NULL;
11585     const char *uri_in = NULL;
11586     const char *listenAddress = NULL;
11587     int nbdPort = 0;
11588     int nmigrate_disks;
11589     g_autofree const char **migrate_disks = NULL;
11590     g_autofree char *origname = NULL;
11591     g_autoptr(qemuMigrationParams) migParams = NULL;
11592     const char *nbdURI = NULL;
11593 
11594     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11595     if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
11596         return -1;
11597 
11598     if (virTypedParamsGetString(params, nparams,
11599                                 VIR_MIGRATE_PARAM_DEST_XML,
11600                                 &dom_xml) < 0 ||
11601         virTypedParamsGetString(params, nparams,
11602                                 VIR_MIGRATE_PARAM_DEST_NAME,
11603                                 &dname) < 0 ||
11604         virTypedParamsGetString(params, nparams,
11605                                 VIR_MIGRATE_PARAM_URI,
11606                                 &uri_in) < 0 ||
11607         virTypedParamsGetString(params, nparams,
11608                                 VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
11609                                 &listenAddress) < 0 ||
11610         virTypedParamsGetString(params, nparams,
11611                                 VIR_MIGRATE_PARAM_DISKS_URI,
11612                                 &nbdURI) < 0 ||
11613         virTypedParamsGetInt(params, nparams,
11614                              VIR_MIGRATE_PARAM_DISKS_PORT,
11615                              &nbdPort) < 0)
11616         return -1;
11617 
11618     nmigrate_disks = virTypedParamsGetStringList(params, nparams,
11619                                                  VIR_MIGRATE_PARAM_MIGRATE_DISKS,
11620                                                  &migrate_disks);
11621 
11622     if (nmigrate_disks < 0)
11623         return -1;
11624 
11625     if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
11626                                                    QEMU_MIGRATION_DESTINATION)))
11627         return -1;
11628 
11629     if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) ||
11630         nmigrate_disks > 0) {
11631         if (uri_in && STRPREFIX(uri_in, "unix:") && !nbdURI) {
11632             virReportError(VIR_ERR_INVALID_ARG, "%s",
11633                            _("NBD URI must be supplied when "
11634                              "migration URI uses UNIX transport method"));
11635             return -1;
11636         }
11637     }
11638 
11639     if (nbdURI && nbdPort) {
11640         virReportError(VIR_ERR_INVALID_ARG, "%s",
11641                        _("Both port and URI requested for disk migration "
11642                          "while being mutually exclusive"));
11643         return -1;
11644     }
11645 
11646     if (listenAddress) {
11647         if (uri_in && STRPREFIX(uri_in, "unix:")) {
11648             virReportError(VIR_ERR_INVALID_ARG, "%s",
11649                            _("Usage of listen-address is forbidden when "
11650                              "migration URI uses UNIX transport method"));
11651             return -1;
11652         }
11653     } else {
11654         listenAddress = cfg->migrationAddress;
11655     }
11656 
11657     if (flags & VIR_MIGRATE_TUNNELLED) {
11658         /* this is a logical error; we never should have gotten here with
11659          * VIR_MIGRATE_TUNNELLED set
11660          */
11661         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11662                        _("Tunnelled migration requested but invalid "
11663                          "RPC method called"));
11664         return -1;
11665     }
11666 
11667     if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
11668         return -1;
11669 
11670     if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
11671         return -1;
11672 
11673     return qemuMigrationDstPrepareDirect(driver, dconn,
11674                                          cookiein, cookieinlen,
11675                                          cookieout, cookieoutlen,
11676                                          uri_in, uri_out,
11677                                          &def, origname, listenAddress,
11678                                          nmigrate_disks, migrate_disks, nbdPort,
11679                                          nbdURI, migParams, flags);
11680 }
11681 
11682 
11683 static int
qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,virStreamPtr st,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned long flags,const char * dname,unsigned long resource G_GNUC_UNUSED,const char * dom_xml)11684 qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
11685                                 virStreamPtr st,
11686                                 const char *cookiein,
11687                                 int cookieinlen,
11688                                 char **cookieout,
11689                                 int *cookieoutlen,
11690                                 unsigned long flags,
11691                                 const char *dname,
11692                                 unsigned long resource G_GNUC_UNUSED,
11693                                 const char *dom_xml)
11694 {
11695     virQEMUDriver *driver = dconn->privateData;
11696     g_autoptr(virDomainDef) def = NULL;
11697     g_autofree char *origname = NULL;
11698     g_autoptr(qemuMigrationParams) migParams = NULL;
11699 
11700     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11701 
11702     if (!(flags & VIR_MIGRATE_TUNNELLED)) {
11703         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11704                        _("PrepareTunnel called but no TUNNELLED flag set"));
11705         return -1;
11706     }
11707 
11708     if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
11709                                                    QEMU_MIGRATION_DESTINATION)))
11710         return -1;
11711 
11712     if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
11713         return -1;
11714 
11715     if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0)
11716         return -1;
11717 
11718     return qemuMigrationDstPrepareTunnel(driver, dconn,
11719                                          cookiein, cookieinlen,
11720                                          cookieout, cookieoutlen,
11721                                          st, &def, origname, migParams, flags);
11722 }
11723 
11724 static int
qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,virStreamPtr st,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned int flags)11725 qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
11726                                       virStreamPtr st,
11727                                       virTypedParameterPtr params,
11728                                       int nparams,
11729                                       const char *cookiein,
11730                                       int cookieinlen,
11731                                       char **cookieout,
11732                                       int *cookieoutlen,
11733                                       unsigned int flags)
11734 {
11735     virQEMUDriver *driver = dconn->privateData;
11736     g_autoptr(virDomainDef) def = NULL;
11737     const char *dom_xml = NULL;
11738     const char *dname = NULL;
11739     g_autofree char *origname = NULL;
11740     g_autoptr(qemuMigrationParams) migParams = NULL;
11741 
11742     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11743     if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
11744         return -1;
11745 
11746     if (virTypedParamsGetString(params, nparams,
11747                                 VIR_MIGRATE_PARAM_DEST_XML,
11748                                 &dom_xml) < 0 ||
11749         virTypedParamsGetString(params, nparams,
11750                                 VIR_MIGRATE_PARAM_DEST_NAME,
11751                                 &dname) < 0)
11752         return -1;
11753 
11754     if (!(flags & VIR_MIGRATE_TUNNELLED)) {
11755         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11756                        _("PrepareTunnel called but no TUNNELLED flag set"));
11757         return -1;
11758     }
11759 
11760     if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
11761                                                    QEMU_MIGRATION_DESTINATION)))
11762         return -1;
11763 
11764     if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
11765         return -1;
11766 
11767     if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0)
11768         return -1;
11769 
11770     return qemuMigrationDstPrepareTunnel(driver, dconn,
11771                                          cookiein, cookieinlen,
11772                                          cookieout, cookieoutlen,
11773                                          st, &def, origname, migParams, flags);
11774 }
11775 
11776 
11777 static int
qemuDomainMigratePerform3(virDomainPtr dom,const char * xmlin,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,const char * dconnuri,const char * uri,unsigned long flags,const char * dname,unsigned long resource)11778 qemuDomainMigratePerform3(virDomainPtr dom,
11779                           const char *xmlin,
11780                           const char *cookiein,
11781                           int cookieinlen,
11782                           char **cookieout,
11783                           int *cookieoutlen,
11784                           const char *dconnuri,
11785                           const char *uri,
11786                           unsigned long flags,
11787                           const char *dname,
11788                           unsigned long resource)
11789 {
11790     virQEMUDriver *driver = dom->conn->privateData;
11791     virDomainObj *vm = NULL;
11792     g_autoptr(qemuMigrationParams) migParams = NULL;
11793     int ret = -1;
11794 
11795     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11796 
11797     if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
11798                                                    QEMU_MIGRATION_SOURCE)))
11799         goto cleanup;
11800 
11801     if (!(vm = qemuDomainObjFromDomain(dom)))
11802         goto cleanup;
11803 
11804     if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0)
11805         goto cleanup;
11806 
11807     ret = qemuMigrationSrcPerform(driver, dom->conn, vm, xmlin, NULL,
11808                                   dconnuri, uri, NULL, NULL, 0, NULL, 0,
11809                                   NULL, migParams,
11810                                   cookiein, cookieinlen,
11811                                   cookieout, cookieoutlen,
11812                                   flags, dname, resource, true);
11813 
11814  cleanup:
11815     virDomainObjEndAPI(&vm);
11816     return ret;
11817 }
11818 
11819 static int
qemuDomainMigratePerform3Params(virDomainPtr dom,const char * dconnuri,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned int flags)11820 qemuDomainMigratePerform3Params(virDomainPtr dom,
11821                                 const char *dconnuri,
11822                                 virTypedParameterPtr params,
11823                                 int nparams,
11824                                 const char *cookiein,
11825                                 int cookieinlen,
11826                                 char **cookieout,
11827                                 int *cookieoutlen,
11828                                 unsigned int flags)
11829 {
11830     virQEMUDriver *driver = dom->conn->privateData;
11831     virDomainObj *vm = NULL;
11832     const char *dom_xml = NULL;
11833     const char *persist_xml = NULL;
11834     const char *dname = NULL;
11835     const char *uri = NULL;
11836     const char *graphicsuri = NULL;
11837     const char *listenAddress = NULL;
11838     int nmigrate_disks;
11839     g_autofree const char **migrate_disks = NULL;
11840     unsigned long long bandwidth = 0;
11841     int nbdPort = 0;
11842     g_autoptr(qemuMigrationParams) migParams = NULL;
11843     const char *nbdURI = NULL;
11844     int ret = -1;
11845 
11846     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
11847     if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
11848         return ret;
11849 
11850     if (virTypedParamsGetString(params, nparams,
11851                                 VIR_MIGRATE_PARAM_DEST_XML,
11852                                 &dom_xml) < 0 ||
11853         virTypedParamsGetString(params, nparams,
11854                                 VIR_MIGRATE_PARAM_DEST_NAME,
11855                                 &dname) < 0 ||
11856         virTypedParamsGetString(params, nparams,
11857                                 VIR_MIGRATE_PARAM_URI,
11858                                 &uri) < 0 ||
11859         virTypedParamsGetULLong(params, nparams,
11860                                 VIR_MIGRATE_PARAM_BANDWIDTH,
11861                                 &bandwidth) < 0 ||
11862         virTypedParamsGetString(params, nparams,
11863                                 VIR_MIGRATE_PARAM_GRAPHICS_URI,
11864                                 &graphicsuri) < 0 ||
11865         virTypedParamsGetString(params, nparams,
11866                                 VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
11867                                 &listenAddress) < 0 ||
11868         virTypedParamsGetInt(params, nparams,
11869                              VIR_MIGRATE_PARAM_DISKS_PORT,
11870                              &nbdPort) < 0 ||
11871         virTypedParamsGetString(params, nparams,
11872                                 VIR_MIGRATE_PARAM_DISKS_URI,
11873                                 &nbdURI) < 0 ||
11874         virTypedParamsGetString(params, nparams,
11875                                 VIR_MIGRATE_PARAM_PERSIST_XML,
11876                                 &persist_xml) < 0)
11877         goto cleanup;
11878 
11879 
11880     if (nbdURI && nbdPort) {
11881         virReportError(VIR_ERR_INVALID_ARG, "%s",
11882                        _("Both port and URI requested for disk migration "
11883                          "while being mutually exclusive"));
11884         goto cleanup;
11885     }
11886 
11887     if (listenAddress) {
11888         if (uri && STRPREFIX(uri, "unix:")) {
11889             virReportError(VIR_ERR_INVALID_ARG, "%s",
11890                            _("Usage of listen-address is forbidden when "
11891                              "migration URI uses UNIX transport method"));
11892             return -1;
11893         }
11894     }
11895 
11896     nmigrate_disks = virTypedParamsGetStringList(params, nparams,
11897                                                  VIR_MIGRATE_PARAM_MIGRATE_DISKS,
11898                                                  &migrate_disks);
11899 
11900     if (nmigrate_disks < 0)
11901         goto cleanup;
11902 
11903     if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) ||
11904         nmigrate_disks > 0) {
11905         if (uri && STRPREFIX(uri, "unix:") && !nbdURI) {
11906             virReportError(VIR_ERR_INVALID_ARG, "%s",
11907                            _("NBD URI must be supplied when "
11908                              "migration URI uses UNIX transport method"));
11909             return -1;
11910         }
11911     }
11912 
11913     if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
11914                                                    QEMU_MIGRATION_SOURCE)))
11915         goto cleanup;
11916 
11917     if (!(vm = qemuDomainObjFromDomain(dom)))
11918         goto cleanup;
11919 
11920     if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0)
11921         goto cleanup;
11922 
11923     ret = qemuMigrationSrcPerform(driver, dom->conn, vm, dom_xml, persist_xml,
11924                                   dconnuri, uri, graphicsuri, listenAddress,
11925                                   nmigrate_disks, migrate_disks, nbdPort,
11926                                   nbdURI, migParams,
11927                                   cookiein, cookieinlen, cookieout, cookieoutlen,
11928                                   flags, dname, bandwidth, true);
11929  cleanup:
11930     virDomainObjEndAPI(&vm);
11931     return ret;
11932 }
11933 
11934 
11935 static virDomainPtr
qemuDomainMigrateFinish3(virConnectPtr dconn,const char * dname,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,const char * dconnuri G_GNUC_UNUSED,const char * uri G_GNUC_UNUSED,unsigned long flags,int cancelled)11936 qemuDomainMigrateFinish3(virConnectPtr dconn,
11937                          const char *dname,
11938                          const char *cookiein,
11939                          int cookieinlen,
11940                          char **cookieout,
11941                          int *cookieoutlen,
11942                          const char *dconnuri G_GNUC_UNUSED,
11943                          const char *uri G_GNUC_UNUSED,
11944                          unsigned long flags,
11945                          int cancelled)
11946 {
11947     virQEMUDriver *driver = dconn->privateData;
11948     virDomainObj *vm;
11949 
11950     virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
11951 
11952     if (!dname) {
11953         virReportError(VIR_ERR_NO_DOMAIN, "%s", _("missing domain name"));
11954         return NULL;
11955     }
11956 
11957     vm = virDomainObjListFindByName(driver->domains, dname);
11958     if (!vm) {
11959         virReportError(VIR_ERR_NO_DOMAIN,
11960                        _("no domain with matching name '%s'"), dname);
11961         qemuMigrationDstErrorReport(driver, dname);
11962         return NULL;
11963     }
11964 
11965     if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) {
11966         virDomainObjEndAPI(&vm);
11967         return NULL;
11968     }
11969 
11970     return qemuMigrationDstFinish(driver, dconn, vm,
11971                                   cookiein, cookieinlen,
11972                                   cookieout, cookieoutlen,
11973                                   flags, cancelled, true);
11974 }
11975 
11976 static virDomainPtr
qemuDomainMigrateFinish3Params(virConnectPtr dconn,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned int flags,int cancelled)11977 qemuDomainMigrateFinish3Params(virConnectPtr dconn,
11978                                virTypedParameterPtr params,
11979                                int nparams,
11980                                const char *cookiein,
11981                                int cookieinlen,
11982                                char **cookieout,
11983                                int *cookieoutlen,
11984                                unsigned int flags,
11985                                int cancelled)
11986 {
11987     virQEMUDriver *driver = dconn->privateData;
11988     virDomainObj *vm;
11989     const char *dname = NULL;
11990 
11991     virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
11992     if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
11993         return NULL;
11994 
11995     if (virTypedParamsGetString(params, nparams,
11996                                 VIR_MIGRATE_PARAM_DEST_NAME,
11997                                 &dname) < 0)
11998         return NULL;
11999 
12000     if (!dname) {
12001         virReportError(VIR_ERR_NO_DOMAIN, "%s", _("missing domain name"));
12002         return NULL;
12003     }
12004 
12005     vm = virDomainObjListFindByName(driver->domains, dname);
12006     if (!vm) {
12007         virReportError(VIR_ERR_NO_DOMAIN,
12008                        _("no domain with matching name '%s'"), dname);
12009         qemuMigrationDstErrorReport(driver, dname);
12010         return NULL;
12011     }
12012 
12013     if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
12014         virDomainObjEndAPI(&vm);
12015         return NULL;
12016     }
12017 
12018     return qemuMigrationDstFinish(driver, dconn, vm,
12019                                   cookiein, cookieinlen,
12020                                   cookieout, cookieoutlen,
12021                                   flags, cancelled, true);
12022 }
12023 
12024 
12025 static int
qemuDomainMigrateConfirm3(virDomainPtr domain,const char * cookiein,int cookieinlen,unsigned long flags,int cancelled)12026 qemuDomainMigrateConfirm3(virDomainPtr domain,
12027                           const char *cookiein,
12028                           int cookieinlen,
12029                           unsigned long flags,
12030                           int cancelled)
12031 {
12032     virDomainObj *vm;
12033 
12034     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12035 
12036     if (!(vm = qemuDomainObjFromDomain(domain)))
12037         return -1;
12038 
12039     if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) {
12040         virDomainObjEndAPI(&vm);
12041         return -1;
12042     }
12043 
12044     return qemuMigrationSrcConfirm(domain->conn->privateData, vm, cookiein, cookieinlen,
12045                                    flags, cancelled);
12046 }
12047 
12048 static int
qemuDomainMigrateConfirm3Params(virDomainPtr domain,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,unsigned int flags,int cancelled)12049 qemuDomainMigrateConfirm3Params(virDomainPtr domain,
12050                                 virTypedParameterPtr params,
12051                                 int nparams,
12052                                 const char *cookiein,
12053                                 int cookieinlen,
12054                                 unsigned int flags,
12055                                 int cancelled)
12056 {
12057     virDomainObj *vm;
12058 
12059     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12060 
12061     if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
12062         return -1;
12063 
12064     if (!(vm = qemuDomainObjFromDomain(domain)))
12065         return -1;
12066 
12067     if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) {
12068         virDomainObjEndAPI(&vm);
12069         return -1;
12070     }
12071 
12072     return qemuMigrationSrcConfirm(domain->conn->privateData, vm, cookiein, cookieinlen,
12073                                    flags, cancelled);
12074 }
12075 
12076 
12077 static int
qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,const char * driverName,unsigned int flags)12078 qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,
12079                           const char *driverName,
12080                           unsigned int flags)
12081 {
12082     virQEMUDriver *driver = dev->conn->privateData;
12083     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
12084 
12085     virCheckFlags(0, -1);
12086 
12087     if (!driverName)
12088         driverName = "vfio";
12089 
12090     /* Only the 'vfio' driver is supported and a special error message for
12091      * the previously supported 'kvm' driver is provided below. */
12092     if (STRNEQ(driverName, "vfio") && STRNEQ(driverName, "kvm")) {
12093         virReportError(VIR_ERR_INVALID_ARG,
12094                        _("unknown driver name '%s'"), driverName);
12095         return -1;
12096     }
12097 
12098     if (STREQ(driverName, "kvm")) {
12099         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
12100                        _("KVM device assignment is no longer "
12101                          "supported on this system"));
12102         return -1;
12103     }
12104 
12105     if (!qemuHostdevHostSupportsPassthroughVFIO()) {
12106         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
12107                        _("VFIO device assignment is currently not "
12108                          "supported on this system"));
12109          return -1;
12110     }
12111 
12112     /* virNodeDeviceDetachFlagsEnsureACL() is being called by
12113      * virDomainDriverNodeDeviceDetachFlags() */
12114     return virDomainDriverNodeDeviceDetachFlags(dev, hostdev_mgr, driverName);
12115 }
12116 
12117 static int
qemuNodeDeviceDettach(virNodeDevicePtr dev)12118 qemuNodeDeviceDettach(virNodeDevicePtr dev)
12119 {
12120     return qemuNodeDeviceDetachFlags(dev, NULL, 0);
12121 }
12122 
12123 static int
qemuNodeDeviceReAttach(virNodeDevicePtr dev)12124 qemuNodeDeviceReAttach(virNodeDevicePtr dev)
12125 {
12126     virQEMUDriver *driver = dev->conn->privateData;
12127     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
12128 
12129     /* virNodeDeviceReAttachEnsureACL() is being called by
12130      * virDomainDriverNodeDeviceReAttach() */
12131     return virDomainDriverNodeDeviceReAttach(dev, hostdev_mgr);
12132 }
12133 
12134 static int
qemuNodeDeviceReset(virNodeDevicePtr dev)12135 qemuNodeDeviceReset(virNodeDevicePtr dev)
12136 {
12137     virQEMUDriver *driver = dev->conn->privateData;
12138     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
12139 
12140     /* virNodeDeviceResetEnsureACL() is being called by
12141      * virDomainDriverNodeDeviceReset() */
12142     return virDomainDriverNodeDeviceReset(dev, hostdev_mgr);
12143 }
12144 
12145 static int
qemuConnectCompareCPU(virConnectPtr conn,const char * xmlDesc,unsigned int flags)12146 qemuConnectCompareCPU(virConnectPtr conn,
12147                       const char *xmlDesc,
12148                       unsigned int flags)
12149 {
12150     virQEMUDriver *driver = conn->privateData;
12151     g_autoptr(virCPUDef) cpu = NULL;
12152     bool failIncompatible;
12153     bool validateXML;
12154 
12155     virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE |
12156                   VIR_CONNECT_COMPARE_CPU_VALIDATE_XML,
12157                   VIR_CPU_COMPARE_ERROR);
12158 
12159     if (virConnectCompareCPUEnsureACL(conn) < 0)
12160         return VIR_CPU_COMPARE_ERROR;
12161 
12162     failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
12163     validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML);
12164 
12165     if (!(cpu = virQEMUDriverGetHostCPU(driver)))
12166         return VIR_CPU_COMPARE_ERROR;
12167 
12168     return virCPUCompareXML(driver->hostarch, cpu,
12169                             xmlDesc, failIncompatible, validateXML);
12170 }
12171 
12172 
12173 static virCPUCompareResult
qemuConnectCPUModelComparison(virQEMUCaps * qemuCaps,const char * libDir,uid_t runUid,gid_t runGid,virCPUDef * cpu_a,virCPUDef * cpu_b,bool failIncompatible)12174 qemuConnectCPUModelComparison(virQEMUCaps *qemuCaps,
12175                               const char *libDir,
12176                               uid_t runUid,
12177                               gid_t runGid,
12178                               virCPUDef *cpu_a,
12179                               virCPUDef *cpu_b,
12180                               bool failIncompatible)
12181 {
12182     g_autoptr(qemuProcessQMP) proc = NULL;
12183     g_autofree char *result = NULL;
12184 
12185     if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps),
12186                                    libDir, runUid, runGid, false)))
12187         return VIR_CPU_COMPARE_ERROR;
12188 
12189     if (qemuProcessQMPStart(proc) < 0)
12190         return VIR_CPU_COMPARE_ERROR;
12191 
12192     if (qemuMonitorGetCPUModelComparison(proc->mon, cpu_a, cpu_b, &result) < 0)
12193         return VIR_CPU_COMPARE_ERROR;
12194 
12195     if (STREQ(result, "identical"))
12196         return VIR_CPU_COMPARE_IDENTICAL;
12197 
12198     if (STREQ(result, "superset"))
12199         return VIR_CPU_COMPARE_SUPERSET;
12200 
12201     if (failIncompatible) {
12202         virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
12203         return VIR_CPU_COMPARE_ERROR;
12204     }
12205 
12206     return VIR_CPU_COMPARE_INCOMPATIBLE;
12207 }
12208 
12209 
12210 static int
qemuConnectCompareHypervisorCPU(virConnectPtr conn,const char * emulator,const char * archStr,const char * machine,const char * virttypeStr,const char * xmlCPU,unsigned int flags)12211 qemuConnectCompareHypervisorCPU(virConnectPtr conn,
12212                                 const char *emulator,
12213                                 const char *archStr,
12214                                 const char *machine,
12215                                 const char *virttypeStr,
12216                                 const char *xmlCPU,
12217                                 unsigned int flags)
12218 {
12219     int ret = VIR_CPU_COMPARE_ERROR;
12220     virQEMUDriver *driver = conn->privateData;
12221     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
12222     g_autoptr(virQEMUCaps) qemuCaps = NULL;
12223     bool failIncompatible;
12224     bool validateXML;
12225     virCPUDef *hvCPU;
12226     virCPUDef *cpu = NULL;
12227     virArch arch;
12228     virDomainVirtType virttype;
12229 
12230     virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE |
12231                   VIR_CONNECT_COMPARE_CPU_VALIDATE_XML,
12232                   VIR_CPU_COMPARE_ERROR);
12233 
12234     if (virConnectCompareHypervisorCPUEnsureACL(conn) < 0)
12235         goto cleanup;
12236 
12237     failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
12238     validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML);
12239 
12240     qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
12241                                              emulator,
12242                                              archStr,
12243                                              virttypeStr,
12244                                              machine,
12245                                              &arch, &virttype, NULL);
12246     if (!qemuCaps)
12247         goto cleanup;
12248 
12249     hvCPU = virQEMUCapsGetHostModel(qemuCaps, virttype,
12250                                     VIR_QEMU_CAPS_HOST_CPU_REPORTED);
12251 
12252     if (!hvCPU || hvCPU->fallback != VIR_CPU_FALLBACK_FORBID) {
12253         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
12254                        _("QEMU '%s' does not support reporting CPU model for "
12255                          "virttype '%s'"),
12256                        virQEMUCapsGetBinary(qemuCaps),
12257                        virDomainVirtTypeToString(virttype));
12258         goto cleanup;
12259     }
12260 
12261     if (ARCH_IS_X86(arch)) {
12262         ret = virCPUCompareXML(arch, hvCPU, xmlCPU, failIncompatible,
12263                                validateXML);
12264     } else if (ARCH_IS_S390(arch) &&
12265                virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_COMPARISON)) {
12266         if (virCPUDefParseXMLString(xmlCPU, VIR_CPU_TYPE_AUTO, &cpu,
12267                                     validateXML) < 0)
12268             goto cleanup;
12269 
12270         if (!cpu->model) {
12271             if (cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) {
12272                 cpu->model = g_strdup("host");
12273             } else if (cpu->mode == VIR_CPU_MODE_MAXIMUM) {
12274                 cpu->model = g_strdup("max");
12275             } else {
12276                 virReportError(VIR_ERR_INVALID_ARG, "%s",
12277                                _("cpu parameter is missing a model name"));
12278                 goto cleanup;
12279             }
12280         }
12281         ret = qemuConnectCPUModelComparison(qemuCaps, cfg->libDir,
12282                                             cfg->user, cfg->group,
12283                                             hvCPU, cpu, failIncompatible);
12284     } else {
12285         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
12286                        _("comparing with the hypervisor CPU is not supported "
12287                          "for arch %s"), virArchToString(arch));
12288     }
12289 
12290  cleanup:
12291     virCPUDefFree(cpu);
12292     return ret;
12293 }
12294 
12295 
12296 static char *
qemuConnectBaselineCPU(virConnectPtr conn G_GNUC_UNUSED,const char ** xmlCPUs,unsigned int ncpus,unsigned int flags)12297 qemuConnectBaselineCPU(virConnectPtr conn G_GNUC_UNUSED,
12298                        const char **xmlCPUs,
12299                        unsigned int ncpus,
12300                        unsigned int flags)
12301 {
12302     virCPUDef **cpus = NULL;
12303     virCPUDef *baseline = NULL;
12304     virCPUDef *cpu = NULL;
12305     char *cpustr = NULL;
12306 
12307     virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
12308                   VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
12309 
12310     if (virConnectBaselineCPUEnsureACL(conn) < 0)
12311         goto cleanup;
12312 
12313     if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
12314         goto cleanup;
12315 
12316     if (!(baseline = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL,
12317                                     !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE))))
12318         goto cleanup;
12319 
12320     if (!(cpu = virCPUDefCopyWithoutModel(baseline)))
12321         goto cleanup;
12322 
12323     if (virCPUDefCopyModelFilter(cpu, baseline, false,
12324                                  virQEMUCapsCPUFilterFeatures,
12325                                  &cpus[0]->arch) < 0)
12326         goto cleanup;
12327 
12328     if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
12329         virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
12330         goto cleanup;
12331 
12332     cpustr = virCPUDefFormat(cpu, NULL);
12333 
12334  cleanup:
12335     virCPUDefListFree(cpus);
12336     virCPUDefFree(baseline);
12337     virCPUDefFree(cpu);
12338 
12339     return cpustr;
12340 }
12341 
12342 
12343 /**
12344  * qemuConnectStealCPUModelFromInfo:
12345  *
12346  * Consumes @src and replaces the content of @dst with CPU model name and
12347  * features from @src. When this function returns (both with success or
12348  * failure), @src is freed.
12349  */
12350 static int
qemuConnectStealCPUModelFromInfo(virCPUDef * dst,qemuMonitorCPUModelInfo ** src)12351 qemuConnectStealCPUModelFromInfo(virCPUDef *dst,
12352                                  qemuMonitorCPUModelInfo **src)
12353 {
12354     g_autoptr(qemuMonitorCPUModelInfo) info = NULL;
12355     size_t i;
12356 
12357     virCPUDefFreeModel(dst);
12358 
12359     info = g_steal_pointer(&*src);
12360     dst->model = g_steal_pointer(&info->name);
12361 
12362     for (i = 0; i < info->nprops; i++) {
12363         char *name = info->props[i].name;
12364 
12365         if (info->props[i].type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN ||
12366             !info->props[i].value.boolean)
12367             continue;
12368 
12369         if (virCPUDefAddFeature(dst, name, VIR_CPU_FEATURE_REQUIRE) < 0)
12370             return -1;
12371     }
12372 
12373     return 0;
12374 }
12375 
12376 
12377 static virCPUDef *
qemuConnectCPUModelBaseline(virQEMUCaps * qemuCaps,const char * libDir,uid_t runUid,gid_t runGid,bool expand_features,virCPUDef ** cpus,int ncpus,virDomainCapsCPUModels * cpuModels)12378 qemuConnectCPUModelBaseline(virQEMUCaps *qemuCaps,
12379                             const char *libDir,
12380                             uid_t runUid,
12381                             gid_t runGid,
12382                             bool expand_features,
12383                             virCPUDef **cpus,
12384                             int ncpus,
12385                             virDomainCapsCPUModels *cpuModels)
12386 {
12387     g_autoptr(qemuProcessQMP) proc = NULL;
12388     g_autoptr(virCPUDef) baseline = NULL;
12389     qemuMonitorCPUModelInfo *result = NULL;
12390     qemuMonitorCPUModelExpansionType expansion_type;
12391     size_t i;
12392 
12393     for (i = 0; i < ncpus; i++) {
12394         if (!cpus[i]) {
12395             virReportError(VIR_ERR_INVALID_ARG,
12396                            _("invalid CPU definition at index %zu"), i);
12397             return NULL;
12398         }
12399         if (!cpus[i]->model) {
12400             virReportError(VIR_ERR_INVALID_ARG,
12401                            _("no CPU model specified at index %zu"), i);
12402             return NULL;
12403         }
12404 
12405         if (!virDomainCapsCPUModelsGet(cpuModels, cpus[i]->model)) {
12406             virReportError(VIR_ERR_INVALID_ARG,
12407                            _("CPU model '%s' not supported by hypervisor"),
12408                            cpus[i]->model);
12409             return NULL;
12410         }
12411     }
12412 
12413     if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps),
12414                                    libDir, runUid, runGid, false)))
12415         return NULL;
12416 
12417     if (qemuProcessQMPStart(proc) < 0)
12418         return NULL;
12419 
12420     baseline = g_new0(virCPUDef, 1);
12421 
12422     if (virCPUDefCopyModel(baseline, cpus[0], false) < 0)
12423         return NULL;
12424 
12425     for (i = 1; i < ncpus; i++) {
12426         if (qemuMonitorGetCPUModelBaseline(proc->mon, baseline,
12427                                            cpus[i], &result) < 0)
12428             return NULL;
12429 
12430         if (qemuConnectStealCPUModelFromInfo(baseline, &result) < 0)
12431             return NULL;
12432     }
12433 
12434     if (expand_features || ncpus == 1) {
12435         expansion_type = expand_features ? QEMU_MONITOR_CPU_MODEL_EXPANSION_FULL
12436                                          : QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC;
12437 
12438         if (qemuMonitorGetCPUModelExpansion(proc->mon, expansion_type,
12439                                             baseline, true, false, &result) < 0)
12440             return NULL;
12441 
12442         if (qemuConnectStealCPUModelFromInfo(baseline, &result) < 0)
12443             return NULL;
12444     }
12445 
12446     return g_steal_pointer(&baseline);
12447 }
12448 
12449 
12450 static char *
qemuConnectBaselineHypervisorCPU(virConnectPtr conn,const char * emulator,const char * archStr,const char * machine,const char * virttypeStr,const char ** xmlCPUs,unsigned int ncpus,unsigned int flags)12451 qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
12452                                  const char *emulator,
12453                                  const char *archStr,
12454                                  const char *machine,
12455                                  const char *virttypeStr,
12456                                  const char **xmlCPUs,
12457                                  unsigned int ncpus,
12458                                  unsigned int flags)
12459 {
12460     virQEMUDriver *driver = conn->privateData;
12461     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
12462     virCPUDef **cpus = NULL;
12463     g_autoptr(virQEMUCaps) qemuCaps = NULL;
12464     virArch arch;
12465     virDomainVirtType virttype;
12466     g_autoptr(virDomainCapsCPUModels) cpuModels = NULL;
12467     bool migratable;
12468     virCPUDef *cpu = NULL;
12469     char *cpustr = NULL;
12470     g_auto(GStrv) features = NULL;
12471 
12472     virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
12473                   VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
12474 
12475     if (virConnectBaselineHypervisorCPUEnsureACL(conn) < 0)
12476         goto cleanup;
12477 
12478     migratable = !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE);
12479 
12480     if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_AUTO)))
12481         goto cleanup;
12482 
12483     qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
12484                                              emulator,
12485                                              archStr,
12486                                              virttypeStr,
12487                                              machine,
12488                                              &arch, &virttype, NULL);
12489     if (!qemuCaps)
12490         goto cleanup;
12491 
12492     if (!(cpuModels = virQEMUCapsGetCPUModels(qemuCaps, virttype, NULL, NULL)) ||
12493         cpuModels->nmodels == 0) {
12494         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
12495                        _("QEMU '%s' does not support any CPU models for "
12496                          "virttype '%s'"),
12497                        virQEMUCapsGetBinary(qemuCaps),
12498                        virDomainVirtTypeToString(virttype));
12499         goto cleanup;
12500     }
12501 
12502     if (ARCH_IS_X86(arch)) {
12503         int rc = virQEMUCapsGetCPUFeatures(qemuCaps, virttype,
12504                                            migratable, &features);
12505         if (rc < 0)
12506             goto cleanup;
12507         if (features && rc == 0) {
12508             /* We got only migratable features from QEMU if we asked for them,
12509              * no further filtering in virCPUBaseline is desired. */
12510             migratable = false;
12511         }
12512 
12513         if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
12514                                    (const char **)features, migratable)))
12515             goto cleanup;
12516     } else if (ARCH_IS_S390(arch) &&
12517                virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_BASELINE) &&
12518                virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) {
12519         bool expand_features = (flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES);
12520 
12521         if (!(cpu = qemuConnectCPUModelBaseline(qemuCaps, cfg->libDir,
12522                                                 cfg->user, cfg->group,
12523                                                 expand_features, cpus, ncpus,
12524                                                 cpuModels)))
12525             goto cleanup;
12526     } else {
12527         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
12528                        _("computing baseline hypervisor CPU is not supported "
12529                          "for arch %s"), virArchToString(arch));
12530         goto cleanup;
12531     }
12532 
12533     cpu->fallback = VIR_CPU_FALLBACK_FORBID;
12534 
12535     if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
12536         virCPUExpandFeatures(arch, cpu) < 0)
12537         goto cleanup;
12538 
12539     cpustr = virCPUDefFormat(cpu, NULL);
12540 
12541  cleanup:
12542     virCPUDefListFree(cpus);
12543     virCPUDefFree(cpu);
12544 
12545     return cpustr;
12546 }
12547 
12548 
12549 static int
qemuDomainGetJobInfoMigrationStats(virQEMUDriver * driver,virDomainObj * vm,qemuDomainJobInfo * jobInfo)12550 qemuDomainGetJobInfoMigrationStats(virQEMUDriver *driver,
12551                                    virDomainObj *vm,
12552                                    qemuDomainJobInfo *jobInfo)
12553 {
12554     qemuDomainObjPrivate *priv = vm->privateData;
12555     bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
12556 
12557     if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE ||
12558         jobInfo->status == QEMU_DOMAIN_JOB_STATUS_MIGRATING ||
12559         jobInfo->status == QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED ||
12560         jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) {
12561         if (events &&
12562             jobInfo->status != QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
12563             qemuMigrationAnyFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE,
12564                                        jobInfo, NULL) < 0)
12565             return -1;
12566 
12567         if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
12568             jobInfo->statsType == QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION &&
12569             qemuMigrationSrcFetchMirrorStats(driver, vm, QEMU_ASYNC_JOB_NONE,
12570                                              jobInfo) < 0)
12571             return -1;
12572 
12573         if (qemuDomainJobInfoUpdateTime(jobInfo) < 0)
12574             return -1;
12575     }
12576 
12577     return 0;
12578 }
12579 
12580 
12581 static int
qemuDomainGetJobInfoDumpStats(virQEMUDriver * driver,virDomainObj * vm,qemuDomainJobInfo * jobInfo)12582 qemuDomainGetJobInfoDumpStats(virQEMUDriver *driver,
12583                               virDomainObj *vm,
12584                               qemuDomainJobInfo *jobInfo)
12585 {
12586     qemuDomainObjPrivate *priv = vm->privateData;
12587     qemuMonitorDumpStats stats = { 0 };
12588     int rc;
12589 
12590     if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
12591         return -1;
12592 
12593     rc = qemuMonitorQueryDump(priv->mon, &stats);
12594 
12595     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
12596         return -1;
12597 
12598     jobInfo->stats.dump = stats;
12599 
12600     if (qemuDomainJobInfoUpdateTime(jobInfo) < 0)
12601         return -1;
12602 
12603     switch (jobInfo->stats.dump.status) {
12604     case QEMU_MONITOR_DUMP_STATUS_NONE:
12605     case QEMU_MONITOR_DUMP_STATUS_FAILED:
12606     case QEMU_MONITOR_DUMP_STATUS_LAST:
12607         virReportError(VIR_ERR_OPERATION_FAILED,
12608                        _("dump query failed, status=%d"),
12609                        jobInfo->stats.dump.status);
12610         return -1;
12611         break;
12612 
12613     case QEMU_MONITOR_DUMP_STATUS_ACTIVE:
12614         jobInfo->status = QEMU_DOMAIN_JOB_STATUS_ACTIVE;
12615         VIR_DEBUG("dump active, bytes written='%llu' remaining='%llu'",
12616                   jobInfo->stats.dump.completed,
12617                   jobInfo->stats.dump.total -
12618                   jobInfo->stats.dump.completed);
12619         break;
12620 
12621     case QEMU_MONITOR_DUMP_STATUS_COMPLETED:
12622         jobInfo->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED;
12623         VIR_DEBUG("dump completed, bytes written='%llu'",
12624                   jobInfo->stats.dump.completed);
12625         break;
12626     }
12627 
12628     return 0;
12629 }
12630 
12631 
12632 static int
qemuDomainGetJobStatsInternal(virQEMUDriver * driver,virDomainObj * vm,bool completed,qemuDomainJobInfo ** jobInfo)12633 qemuDomainGetJobStatsInternal(virQEMUDriver *driver,
12634                               virDomainObj *vm,
12635                               bool completed,
12636                               qemuDomainJobInfo **jobInfo)
12637 {
12638     qemuDomainObjPrivate *priv = vm->privateData;
12639     int ret = -1;
12640 
12641     *jobInfo = NULL;
12642 
12643     if (completed) {
12644         if (priv->job.completed && !priv->job.current)
12645             *jobInfo = qemuDomainJobInfoCopy(priv->job.completed);
12646 
12647         return 0;
12648     }
12649 
12650     if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
12651         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
12652                _("migration statistics are available only on "
12653                  "the source host"));
12654         return -1;
12655     }
12656 
12657     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12658         return -1;
12659 
12660     if (virDomainObjCheckActive(vm) < 0)
12661         goto cleanup;
12662 
12663     if (!priv->job.current) {
12664         ret = 0;
12665         goto cleanup;
12666     }
12667     *jobInfo = qemuDomainJobInfoCopy(priv->job.current);
12668 
12669     switch ((*jobInfo)->statsType) {
12670     case QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION:
12671     case QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP:
12672         if (qemuDomainGetJobInfoMigrationStats(driver, vm, *jobInfo) < 0)
12673             goto cleanup;
12674         break;
12675 
12676     case QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP:
12677         if (qemuDomainGetJobInfoDumpStats(driver, vm, *jobInfo) < 0)
12678             goto cleanup;
12679         break;
12680 
12681     case QEMU_DOMAIN_JOB_STATS_TYPE_BACKUP:
12682         if (qemuBackupGetJobInfoStats(driver, vm, *jobInfo) < 0)
12683             goto cleanup;
12684         break;
12685 
12686     case QEMU_DOMAIN_JOB_STATS_TYPE_NONE:
12687         break;
12688     }
12689 
12690     ret = 0;
12691 
12692  cleanup:
12693     qemuDomainObjEndJob(driver, vm);
12694     return ret;
12695 }
12696 
12697 
12698 static int
qemuDomainGetJobInfo(virDomainPtr dom,virDomainJobInfoPtr info)12699 qemuDomainGetJobInfo(virDomainPtr dom,
12700                      virDomainJobInfoPtr info)
12701 {
12702     virQEMUDriver *driver = dom->conn->privateData;
12703     g_autoptr(qemuDomainJobInfo) jobInfo = NULL;
12704     virDomainObj *vm;
12705     int ret = -1;
12706 
12707     memset(info, 0, sizeof(*info));
12708 
12709     if (!(vm = qemuDomainObjFromDomain(dom)))
12710         goto cleanup;
12711 
12712     if (virDomainGetJobInfoEnsureACL(dom->conn, vm->def) < 0)
12713         goto cleanup;
12714 
12715     if (qemuDomainGetJobStatsInternal(driver, vm, false, &jobInfo) < 0)
12716         goto cleanup;
12717 
12718     if (!jobInfo ||
12719         jobInfo->status == QEMU_DOMAIN_JOB_STATUS_NONE) {
12720         ret = 0;
12721         goto cleanup;
12722     }
12723 
12724     ret = qemuDomainJobInfoToInfo(jobInfo, info);
12725 
12726  cleanup:
12727     virDomainObjEndAPI(&vm);
12728     return ret;
12729 }
12730 
12731 
12732 static int
qemuDomainGetJobStats(virDomainPtr dom,int * type,virTypedParameterPtr * params,int * nparams,unsigned int flags)12733 qemuDomainGetJobStats(virDomainPtr dom,
12734                       int *type,
12735                       virTypedParameterPtr *params,
12736                       int *nparams,
12737                       unsigned int flags)
12738 {
12739     virQEMUDriver *driver = dom->conn->privateData;
12740     virDomainObj *vm;
12741     qemuDomainObjPrivate *priv;
12742     g_autoptr(qemuDomainJobInfo) jobInfo = NULL;
12743     bool completed = !!(flags & VIR_DOMAIN_JOB_STATS_COMPLETED);
12744     int ret = -1;
12745 
12746     virCheckFlags(VIR_DOMAIN_JOB_STATS_COMPLETED |
12747                   VIR_DOMAIN_JOB_STATS_KEEP_COMPLETED, -1);
12748 
12749     if (!(vm = qemuDomainObjFromDomain(dom)))
12750         goto cleanup;
12751 
12752     if (virDomainGetJobStatsEnsureACL(dom->conn, vm->def) < 0)
12753         goto cleanup;
12754 
12755     priv = vm->privateData;
12756     if (qemuDomainGetJobStatsInternal(driver, vm, completed, &jobInfo) < 0)
12757         goto cleanup;
12758 
12759     if (!jobInfo ||
12760         jobInfo->status == QEMU_DOMAIN_JOB_STATUS_NONE) {
12761         *type = VIR_DOMAIN_JOB_NONE;
12762         *params = NULL;
12763         *nparams = 0;
12764         ret = 0;
12765         goto cleanup;
12766     }
12767 
12768     ret = qemuDomainJobInfoToParams(jobInfo, type, params, nparams);
12769 
12770     if (completed && ret == 0 && !(flags & VIR_DOMAIN_JOB_STATS_KEEP_COMPLETED))
12771         g_clear_pointer(&priv->job.completed, qemuDomainJobInfoFree);
12772 
12773  cleanup:
12774     virDomainObjEndAPI(&vm);
12775     return ret;
12776 }
12777 
12778 
12779 static int
qemuDomainAbortJobMigration(virDomainObj * vm)12780 qemuDomainAbortJobMigration(virDomainObj *vm)
12781 {
12782     qemuDomainObjPrivate *priv = vm->privateData;
12783     int ret;
12784 
12785     VIR_DEBUG("Cancelling migration job at client request");
12786 
12787     qemuDomainObjAbortAsyncJob(vm);
12788     qemuDomainObjEnterMonitor(priv->driver, vm);
12789     ret = qemuMonitorMigrateCancel(priv->mon);
12790     if (qemuDomainObjExitMonitor(priv->driver, vm) < 0)
12791         ret = -1;
12792 
12793     return ret;
12794 }
12795 
12796 
qemuDomainAbortJob(virDomainPtr dom)12797 static int qemuDomainAbortJob(virDomainPtr dom)
12798 {
12799     virQEMUDriver *driver = dom->conn->privateData;
12800     virDomainObj *vm;
12801     int ret = -1;
12802     qemuDomainObjPrivate *priv;
12803     int reason;
12804 
12805     if (!(vm = qemuDomainObjFromDomain(dom)))
12806         goto cleanup;
12807 
12808     if (virDomainAbortJobEnsureACL(dom->conn, vm->def) < 0)
12809         goto cleanup;
12810 
12811     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0)
12812         goto cleanup;
12813 
12814     if (virDomainObjCheckActive(vm) < 0)
12815         goto endjob;
12816 
12817     priv = vm->privateData;
12818 
12819     switch (priv->job.asyncJob) {
12820     case QEMU_ASYNC_JOB_NONE:
12821         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
12822                        _("no job is active on the domain"));
12823         break;
12824 
12825     case QEMU_ASYNC_JOB_MIGRATION_IN:
12826         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
12827                        _("cannot abort incoming migration;"
12828                          " use virDomainDestroy instead"));
12829         break;
12830 
12831     case QEMU_ASYNC_JOB_START:
12832         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
12833                        _("cannot abort VM start;"
12834                          " use virDomainDestroy instead"));
12835         break;
12836 
12837     case QEMU_ASYNC_JOB_MIGRATION_OUT:
12838         if ((priv->job.current->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY ||
12839              (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
12840               reason == VIR_DOMAIN_PAUSED_POSTCOPY))) {
12841             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
12842                            _("cannot abort migration in post-copy mode"));
12843             goto endjob;
12844         }
12845 
12846         ret = qemuDomainAbortJobMigration(vm);
12847         break;
12848 
12849     case QEMU_ASYNC_JOB_SAVE:
12850         ret = qemuDomainAbortJobMigration(vm);
12851         break;
12852 
12853     case QEMU_ASYNC_JOB_DUMP:
12854         if (priv->job.apiFlags & VIR_DUMP_MEMORY_ONLY) {
12855             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
12856                            _("cannot abort memory-only dump"));
12857             goto endjob;
12858         }
12859 
12860         ret = qemuDomainAbortJobMigration(vm);
12861         break;
12862 
12863     case QEMU_ASYNC_JOB_SNAPSHOT:
12864         ret = qemuDomainAbortJobMigration(vm);
12865         break;
12866 
12867     case QEMU_ASYNC_JOB_BACKUP:
12868         qemuBackupJobCancelBlockjobs(vm, priv->backup, true, QEMU_ASYNC_JOB_NONE);
12869         ret = 0;
12870         break;
12871 
12872     case QEMU_ASYNC_JOB_LAST:
12873     default:
12874         virReportEnumRangeError(qemuDomainAsyncJob, priv->job.asyncJob);
12875         break;
12876     }
12877 
12878  endjob:
12879     qemuDomainObjEndJob(driver, vm);
12880 
12881  cleanup:
12882     virDomainObjEndAPI(&vm);
12883     return ret;
12884 }
12885 
12886 
12887 static int
qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,unsigned long long downtime,unsigned int flags)12888 qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
12889                                 unsigned long long downtime,
12890                                 unsigned int flags)
12891 {
12892     virQEMUDriver *driver = dom->conn->privateData;
12893     virDomainObj *vm;
12894     qemuDomainObjPrivate *priv;
12895     g_autoptr(qemuMigrationParams) migParams = NULL;
12896     int ret = -1;
12897     int rc;
12898 
12899     virCheckFlags(0, -1);
12900 
12901     if (!(vm = qemuDomainObjFromDomain(dom)))
12902         goto cleanup;
12903 
12904     if (virDomainMigrateSetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0)
12905         goto cleanup;
12906 
12907     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
12908         goto cleanup;
12909 
12910     if (virDomainObjCheckActive(vm) < 0)
12911         goto endjob;
12912 
12913     priv = vm->privateData;
12914 
12915     VIR_DEBUG("Setting migration downtime to %llums", downtime);
12916 
12917     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_DOWNTIME)) {
12918         if (!(migParams = qemuMigrationParamsNew()))
12919             goto endjob;
12920 
12921         if (qemuMigrationParamsSetULL(migParams,
12922                                       QEMU_MIGRATION_PARAM_DOWNTIME_LIMIT,
12923                                       downtime) < 0)
12924             goto endjob;
12925 
12926         if (qemuMigrationParamsApply(driver, vm, QEMU_ASYNC_JOB_NONE,
12927                                      migParams) < 0)
12928             goto endjob;
12929     } else {
12930         qemuDomainObjEnterMonitor(driver, vm);
12931         rc = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
12932         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
12933             goto endjob;
12934     }
12935 
12936     ret = 0;
12937 
12938  endjob:
12939     qemuDomainObjEndJob(driver, vm);
12940 
12941  cleanup:
12942     virDomainObjEndAPI(&vm);
12943     return ret;
12944 }
12945 
12946 
12947 static int
qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,unsigned long long * downtime,unsigned int flags)12948 qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,
12949                                 unsigned long long *downtime,
12950                                 unsigned int flags)
12951 {
12952     virQEMUDriver *driver = dom->conn->privateData;
12953     virDomainObj *vm;
12954     g_autoptr(qemuMigrationParams) migParams = NULL;
12955     int ret = -1;
12956     int rc;
12957 
12958     virCheckFlags(0, -1);
12959 
12960     if (!(vm = qemuDomainObjFromDomain(dom)))
12961         return -1;
12962 
12963     if (virDomainMigrateGetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0)
12964         goto cleanup;
12965 
12966     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12967         goto cleanup;
12968 
12969     if (virDomainObjCheckActive(vm) < 0)
12970         goto endjob;
12971 
12972     if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
12973                                  &migParams) < 0)
12974         goto endjob;
12975 
12976     if ((rc = qemuMigrationParamsGetULL(migParams,
12977                                         QEMU_MIGRATION_PARAM_DOWNTIME_LIMIT,
12978                                         downtime)) < 0) {
12979         goto endjob;
12980     }
12981 
12982     if (rc == 1) {
12983         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
12984                        _("Querying migration downtime is not supported by "
12985                          "QEMU binary"));
12986         goto endjob;
12987     }
12988 
12989     ret = 0;
12990 
12991  endjob:
12992     qemuDomainObjEndJob(driver, vm);
12993 
12994  cleanup:
12995     virDomainObjEndAPI(&vm);
12996     return ret;
12997 }
12998 
12999 
13000 static int
qemuDomainMigrateGetCompressionCache(virDomainPtr dom,unsigned long long * cacheSize,unsigned int flags)13001 qemuDomainMigrateGetCompressionCache(virDomainPtr dom,
13002                                      unsigned long long *cacheSize,
13003                                      unsigned int flags)
13004 {
13005     virQEMUDriver *driver = dom->conn->privateData;
13006     virDomainObj *vm;
13007     qemuDomainObjPrivate *priv;
13008     g_autoptr(qemuMigrationParams) migParams = NULL;
13009     int ret = -1;
13010     int rc;
13011 
13012     virCheckFlags(0, -1);
13013 
13014     if (!(vm = qemuDomainObjFromDomain(dom)))
13015         goto cleanup;
13016 
13017     if (virDomainMigrateGetCompressionCacheEnsureACL(dom->conn, vm->def) < 0)
13018         goto cleanup;
13019 
13020     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
13021         goto cleanup;
13022 
13023     if (virDomainObjCheckActive(vm) < 0)
13024         goto endjob;
13025 
13026     priv = vm->privateData;
13027 
13028     if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) {
13029         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
13030                        _("Compressed migration is not supported by "
13031                          "QEMU binary"));
13032         goto endjob;
13033     }
13034 
13035     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE)) {
13036         if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
13037                                      &migParams) < 0)
13038             goto endjob;
13039 
13040         if (qemuMigrationParamsGetULL(migParams,
13041                                       QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE,
13042                                       cacheSize) < 0)
13043             goto endjob;
13044     } else {
13045         qemuDomainObjEnterMonitor(driver, vm);
13046         rc = qemuMonitorGetMigrationCacheSize(priv->mon, cacheSize);
13047         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
13048             goto endjob;
13049     }
13050 
13051     ret = 0;
13052 
13053  endjob:
13054     qemuDomainObjEndJob(driver, vm);
13055 
13056  cleanup:
13057     virDomainObjEndAPI(&vm);
13058     return ret;
13059 }
13060 
13061 static int
qemuDomainMigrateSetCompressionCache(virDomainPtr dom,unsigned long long cacheSize,unsigned int flags)13062 qemuDomainMigrateSetCompressionCache(virDomainPtr dom,
13063                                      unsigned long long cacheSize,
13064                                      unsigned int flags)
13065 {
13066     virQEMUDriver *driver = dom->conn->privateData;
13067     virDomainObj *vm;
13068     qemuDomainObjPrivate *priv;
13069     g_autoptr(qemuMigrationParams) migParams = NULL;
13070     int ret = -1;
13071     int rc;
13072 
13073     virCheckFlags(0, -1);
13074 
13075     if (!(vm = qemuDomainObjFromDomain(dom)))
13076         goto cleanup;
13077 
13078     if (virDomainMigrateSetCompressionCacheEnsureACL(dom->conn, vm->def) < 0)
13079         goto cleanup;
13080 
13081     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
13082         goto cleanup;
13083 
13084     if (virDomainObjCheckActive(vm) < 0)
13085         goto endjob;
13086 
13087     priv = vm->privateData;
13088 
13089     if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) {
13090         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
13091                        _("Compressed migration is not supported by "
13092                          "QEMU binary"));
13093         goto endjob;
13094     }
13095 
13096     VIR_DEBUG("Setting compression cache to %llu B", cacheSize);
13097     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE)) {
13098         if (!(migParams = qemuMigrationParamsNew()))
13099             goto endjob;
13100 
13101         if (qemuMigrationParamsSetULL(migParams,
13102                                       QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE,
13103                                       cacheSize) < 0)
13104             goto endjob;
13105 
13106         if (qemuMigrationParamsApply(driver, vm, QEMU_ASYNC_JOB_NONE,
13107                                      migParams) < 0)
13108             goto endjob;
13109     } else {
13110         qemuDomainObjEnterMonitor(driver, vm);
13111         rc = qemuMonitorSetMigrationCacheSize(priv->mon, cacheSize);
13112         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
13113             goto endjob;
13114     }
13115 
13116     ret = 0;
13117 
13118  endjob:
13119     qemuDomainObjEndJob(driver, vm);
13120 
13121  cleanup:
13122     virDomainObjEndAPI(&vm);
13123     return ret;
13124 }
13125 
13126 static int
qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,unsigned long bandwidth,unsigned int flags)13127 qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
13128                              unsigned long bandwidth,
13129                              unsigned int flags)
13130 {
13131     virQEMUDriver *driver = dom->conn->privateData;
13132     virDomainObj *vm;
13133     qemuDomainObjPrivate *priv;
13134     bool postcopy = !!(flags & VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY);
13135     g_autoptr(qemuMigrationParams) migParams = NULL;
13136     bool bwParam;
13137     unsigned long long max;
13138     int ret = -1;
13139 
13140     virCheckFlags(VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY, -1);
13141 
13142     if (!(vm = qemuDomainObjFromDomain(dom)))
13143         goto cleanup;
13144 
13145     priv = vm->privateData;
13146 
13147     if (virDomainMigrateSetMaxSpeedEnsureACL(dom->conn, vm->def) < 0)
13148         goto cleanup;
13149 
13150     if (postcopy)
13151         max = ULLONG_MAX / 1024 / 1024;
13152     else
13153         max = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
13154 
13155     if (bandwidth > max) {
13156         virReportError(VIR_ERR_OVERFLOW,
13157                        _("bandwidth must be less than %llu"), max + 1);
13158         goto cleanup;
13159     }
13160 
13161     if (!postcopy && !virDomainObjIsActive(vm)) {
13162         priv->migMaxBandwidth = bandwidth;
13163         ret = 0;
13164         goto cleanup;
13165     }
13166 
13167     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
13168         goto cleanup;
13169 
13170     if (virDomainObjCheckActive(vm) < 0)
13171         goto endjob;
13172 
13173     VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
13174 
13175     bwParam = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_BANDWIDTH);
13176 
13177     if (postcopy || bwParam) {
13178         qemuMigrationParam param;
13179 
13180         if (!(migParams = qemuMigrationParamsNew()))
13181             goto endjob;
13182 
13183         if (postcopy)
13184             param = QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH;
13185         else
13186             param = QEMU_MIGRATION_PARAM_MAX_BANDWIDTH;
13187 
13188         if (qemuMigrationParamsSetULL(migParams, param,
13189                                       bandwidth * 1024 * 1024) < 0)
13190             goto endjob;
13191 
13192         if (qemuMigrationParamsApply(driver, vm, QEMU_ASYNC_JOB_NONE,
13193                                      migParams) < 0)
13194             goto endjob;
13195     } else {
13196         int rc;
13197 
13198         qemuDomainObjEnterMonitor(driver, vm);
13199         rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
13200         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
13201             goto endjob;
13202     }
13203 
13204     if (!postcopy)
13205         priv->migMaxBandwidth = bandwidth;
13206 
13207     ret = 0;
13208 
13209  endjob:
13210     qemuDomainObjEndJob(driver, vm);
13211 
13212  cleanup:
13213     virDomainObjEndAPI(&vm);
13214     return ret;
13215 }
13216 
13217 
13218 static int
qemuDomainMigrationGetPostcopyBandwidth(virQEMUDriver * driver,virDomainObj * vm,unsigned long * bandwidth)13219 qemuDomainMigrationGetPostcopyBandwidth(virQEMUDriver *driver,
13220                                         virDomainObj *vm,
13221                                         unsigned long *bandwidth)
13222 {
13223     g_autoptr(qemuMigrationParams) migParams = NULL;
13224     unsigned long long bw;
13225     int rc;
13226     int ret = -1;
13227 
13228     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
13229         return -1;
13230 
13231     if (virDomainObjCheckActive(vm) < 0)
13232         goto cleanup;
13233 
13234     if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
13235                                  &migParams) < 0)
13236         goto cleanup;
13237 
13238     if ((rc = qemuMigrationParamsGetULL(migParams,
13239                                         QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
13240                                         &bw)) < 0)
13241         goto cleanup;
13242 
13243     if (rc == 1) {
13244         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
13245                        _("querying maximum post-copy migration speed is "
13246                          "not supported by QEMU binary"));
13247         goto cleanup;
13248     }
13249 
13250     /* QEMU reports B/s while we use MiB/s */
13251     bw /= 1024 * 1024;
13252 
13253     if (bw > ULONG_MAX) {
13254         virReportError(VIR_ERR_OVERFLOW,
13255                        _("bandwidth %llu is greater than %lu which is the "
13256                          "maximum value supported by this API"),
13257                        bw, ULONG_MAX);
13258         goto cleanup;
13259     }
13260 
13261     *bandwidth = bw;
13262     ret = 0;
13263 
13264  cleanup:
13265     qemuDomainObjEndJob(driver, vm);
13266     return ret;
13267 }
13268 
13269 
13270 static int
qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,unsigned long * bandwidth,unsigned int flags)13271 qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,
13272                              unsigned long *bandwidth,
13273                              unsigned int flags)
13274 {
13275     virQEMUDriver *driver = dom->conn->privateData;
13276     virDomainObj *vm;
13277     qemuDomainObjPrivate *priv;
13278     bool postcopy = !!(flags & VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY);
13279     int ret = -1;
13280 
13281     virCheckFlags(VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY, -1);
13282 
13283     if (!(vm = qemuDomainObjFromDomain(dom)))
13284         goto cleanup;
13285 
13286     priv = vm->privateData;
13287 
13288     if (virDomainMigrateGetMaxSpeedEnsureACL(dom->conn, vm->def) < 0)
13289         goto cleanup;
13290 
13291     if (postcopy) {
13292         if (qemuDomainMigrationGetPostcopyBandwidth(driver, vm, bandwidth) < 0)
13293             goto cleanup;
13294     } else {
13295         *bandwidth = priv->migMaxBandwidth;
13296     }
13297 
13298     ret = 0;
13299 
13300  cleanup:
13301     virDomainObjEndAPI(&vm);
13302     return ret;
13303 }
13304 
13305 
13306 static int
qemuDomainMigrateStartPostCopy(virDomainPtr dom,unsigned int flags)13307 qemuDomainMigrateStartPostCopy(virDomainPtr dom,
13308                                unsigned int flags)
13309 {
13310     virQEMUDriver *driver = dom->conn->privateData;
13311     virDomainObj *vm;
13312     qemuDomainObjPrivate *priv;
13313     int ret = -1;
13314 
13315     virCheckFlags(0, -1);
13316 
13317     if (!(vm = qemuDomainObjFromDomain(dom)))
13318         goto cleanup;
13319 
13320     if (virDomainMigrateStartPostCopyEnsureACL(dom->conn, vm->def) < 0)
13321         goto cleanup;
13322 
13323     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
13324         goto cleanup;
13325 
13326     if (virDomainObjCheckActive(vm) < 0)
13327         goto endjob;
13328 
13329     priv = vm->privateData;
13330 
13331     if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
13332         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
13333                        _("post-copy can only be started while "
13334                          "outgoing migration is in progress"));
13335         goto endjob;
13336     }
13337 
13338     if (!(priv->job.apiFlags & VIR_MIGRATE_POSTCOPY)) {
13339         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
13340                        _("switching to post-copy requires migration to be "
13341                          "started with VIR_MIGRATE_POSTCOPY flag"));
13342         goto endjob;
13343     }
13344 
13345     VIR_DEBUG("Starting post-copy");
13346     qemuDomainObjEnterMonitor(driver, vm);
13347     ret = qemuMonitorMigrateStartPostCopy(priv->mon);
13348     if (qemuDomainObjExitMonitor(driver, vm) < 0)
13349         ret = -1;
13350 
13351  endjob:
13352     qemuDomainObjEndJob(driver, vm);
13353 
13354  cleanup:
13355     virDomainObjEndAPI(&vm);
13356     return ret;
13357 }
13358 
13359 
13360 static virDomainSnapshotPtr
qemuDomainSnapshotCreateXML(virDomainPtr domain,const char * xmlDesc,unsigned int flags)13361 qemuDomainSnapshotCreateXML(virDomainPtr domain,
13362                             const char *xmlDesc,
13363                             unsigned int flags)
13364 {
13365     virDomainObj *vm = NULL;
13366     virDomainSnapshotPtr snapshot = NULL;
13367 
13368     if (!(vm = qemuDomainObjFromDomain(domain)))
13369         goto cleanup;
13370 
13371     if (virDomainSnapshotCreateXMLEnsureACL(domain->conn, vm->def, flags) < 0)
13372         goto cleanup;
13373 
13374     snapshot = qemuSnapshotCreateXML(domain, vm, xmlDesc, flags);
13375 
13376  cleanup:
13377     virDomainObjEndAPI(&vm);
13378     return snapshot;
13379 }
13380 
13381 
13382 static int
qemuDomainSnapshotListNames(virDomainPtr domain,char ** names,int nameslen,unsigned int flags)13383 qemuDomainSnapshotListNames(virDomainPtr domain,
13384                             char **names,
13385                             int nameslen,
13386                             unsigned int flags)
13387 {
13388     virDomainObj *vm = NULL;
13389     int n = -1;
13390 
13391     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
13392                   VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
13393                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
13394 
13395     if (!(vm = qemuDomainObjFromDomain(domain)))
13396         return -1;
13397 
13398     if (virDomainSnapshotListNamesEnsureACL(domain->conn, vm->def) < 0)
13399         goto cleanup;
13400 
13401     n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
13402                                          flags);
13403 
13404  cleanup:
13405     virDomainObjEndAPI(&vm);
13406     return n;
13407 }
13408 
13409 
13410 static int
qemuDomainSnapshotNum(virDomainPtr domain,unsigned int flags)13411 qemuDomainSnapshotNum(virDomainPtr domain,
13412                       unsigned int flags)
13413 {
13414     virDomainObj *vm = NULL;
13415     int n = -1;
13416 
13417     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
13418                   VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
13419                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
13420 
13421     if (!(vm = qemuDomainObjFromDomain(domain)))
13422         return -1;
13423 
13424     if (virDomainSnapshotNumEnsureACL(domain->conn, vm->def) < 0)
13425         goto cleanup;
13426 
13427     n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);
13428 
13429  cleanup:
13430     virDomainObjEndAPI(&vm);
13431     return n;
13432 }
13433 
13434 
13435 static int
qemuDomainListAllSnapshots(virDomainPtr domain,virDomainSnapshotPtr ** snaps,unsigned int flags)13436 qemuDomainListAllSnapshots(virDomainPtr domain,
13437                            virDomainSnapshotPtr **snaps,
13438                            unsigned int flags)
13439 {
13440     virDomainObj *vm = NULL;
13441     int n = -1;
13442 
13443     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
13444                   VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
13445                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
13446 
13447     if (!(vm = qemuDomainObjFromDomain(domain)))
13448         return -1;
13449 
13450     if (virDomainListAllSnapshotsEnsureACL(domain->conn, vm->def) < 0)
13451         goto cleanup;
13452 
13453     n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);
13454 
13455  cleanup:
13456     virDomainObjEndAPI(&vm);
13457     return n;
13458 }
13459 
13460 
13461 static int
qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,char ** names,int nameslen,unsigned int flags)13462 qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
13463                                     char **names,
13464                                     int nameslen,
13465                                     unsigned int flags)
13466 {
13467     virDomainObj *vm = NULL;
13468     virDomainMomentObj *snap = NULL;
13469     int n = -1;
13470 
13471     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
13472                   VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
13473                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
13474 
13475     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13476         return -1;
13477 
13478     if (virDomainSnapshotListChildrenNamesEnsureACL(snapshot->domain->conn, vm->def) < 0)
13479         goto cleanup;
13480 
13481     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13482         goto cleanup;
13483 
13484     n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
13485                                          flags);
13486 
13487  cleanup:
13488     virDomainObjEndAPI(&vm);
13489     return n;
13490 }
13491 
13492 
13493 static int
qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,unsigned int flags)13494 qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
13495                               unsigned int flags)
13496 {
13497     virDomainObj *vm = NULL;
13498     virDomainMomentObj *snap = NULL;
13499     int n = -1;
13500 
13501     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
13502                   VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
13503                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
13504 
13505     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13506         return -1;
13507 
13508     if (virDomainSnapshotNumChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0)
13509         goto cleanup;
13510 
13511     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13512         goto cleanup;
13513 
13514     n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);
13515 
13516  cleanup:
13517     virDomainObjEndAPI(&vm);
13518     return n;
13519 }
13520 
13521 
13522 static int
qemuDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,virDomainSnapshotPtr ** snaps,unsigned int flags)13523 qemuDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
13524                                   virDomainSnapshotPtr **snaps,
13525                                   unsigned int flags)
13526 {
13527     virDomainObj *vm = NULL;
13528     virDomainMomentObj *snap = NULL;
13529     int n = -1;
13530 
13531     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
13532                   VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
13533                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
13534 
13535     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13536         return -1;
13537 
13538     if (virDomainSnapshotListAllChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0)
13539         goto cleanup;
13540 
13541     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13542         goto cleanup;
13543 
13544     n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
13545                                flags);
13546 
13547  cleanup:
13548     virDomainObjEndAPI(&vm);
13549     return n;
13550 }
13551 
13552 
13553 static virDomainSnapshotPtr
qemuDomainSnapshotLookupByName(virDomainPtr domain,const char * name,unsigned int flags)13554 qemuDomainSnapshotLookupByName(virDomainPtr domain,
13555                                const char *name,
13556                                unsigned int flags)
13557 {
13558     virDomainObj *vm;
13559     virDomainMomentObj *snap = NULL;
13560     virDomainSnapshotPtr snapshot = NULL;
13561 
13562     virCheckFlags(0, NULL);
13563 
13564     if (!(vm = qemuDomainObjFromDomain(domain)))
13565         return NULL;
13566 
13567     if (virDomainSnapshotLookupByNameEnsureACL(domain->conn, vm->def) < 0)
13568         goto cleanup;
13569 
13570     if (!(snap = qemuSnapObjFromName(vm, name)))
13571         goto cleanup;
13572 
13573     snapshot = virGetDomainSnapshot(domain, snap->def->name);
13574 
13575  cleanup:
13576     virDomainObjEndAPI(&vm);
13577     return snapshot;
13578 }
13579 
13580 
13581 static int
qemuDomainHasCurrentSnapshot(virDomainPtr domain,unsigned int flags)13582 qemuDomainHasCurrentSnapshot(virDomainPtr domain,
13583                              unsigned int flags)
13584 {
13585     virDomainObj *vm;
13586     int ret = -1;
13587 
13588     virCheckFlags(0, -1);
13589 
13590     if (!(vm = qemuDomainObjFromDomain(domain)))
13591         return -1;
13592 
13593     if (virDomainHasCurrentSnapshotEnsureACL(domain->conn, vm->def) < 0)
13594         goto cleanup;
13595 
13596     ret = (virDomainSnapshotGetCurrent(vm->snapshots) != NULL);
13597 
13598  cleanup:
13599     virDomainObjEndAPI(&vm);
13600     return ret;
13601 }
13602 
13603 
13604 static virDomainSnapshotPtr
qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,unsigned int flags)13605 qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
13606                             unsigned int flags)
13607 {
13608     virDomainObj *vm;
13609     virDomainMomentObj *snap = NULL;
13610     virDomainSnapshotPtr parent = NULL;
13611 
13612     virCheckFlags(0, NULL);
13613 
13614     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13615         return NULL;
13616 
13617     if (virDomainSnapshotGetParentEnsureACL(snapshot->domain->conn, vm->def) < 0)
13618         goto cleanup;
13619 
13620     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13621         goto cleanup;
13622 
13623     if (!snap->def->parent_name) {
13624         virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
13625                        _("snapshot '%s' does not have a parent"),
13626                        snap->def->name);
13627         goto cleanup;
13628     }
13629 
13630     parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent_name);
13631 
13632  cleanup:
13633     virDomainObjEndAPI(&vm);
13634     return parent;
13635 }
13636 
13637 
13638 static virDomainSnapshotPtr
qemuDomainSnapshotCurrent(virDomainPtr domain,unsigned int flags)13639 qemuDomainSnapshotCurrent(virDomainPtr domain,
13640                           unsigned int flags)
13641 {
13642     virDomainObj *vm;
13643     virDomainSnapshotPtr snapshot = NULL;
13644     const char *name;
13645 
13646     virCheckFlags(0, NULL);
13647 
13648     if (!(vm = qemuDomainObjFromDomain(domain)))
13649         return NULL;
13650 
13651     if (virDomainSnapshotCurrentEnsureACL(domain->conn, vm->def) < 0)
13652         goto cleanup;
13653 
13654     name = virDomainSnapshotGetCurrentName(vm->snapshots);
13655     if (!name) {
13656         virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
13657                        _("the domain does not have a current snapshot"));
13658         goto cleanup;
13659     }
13660 
13661     snapshot = virGetDomainSnapshot(domain, name);
13662 
13663  cleanup:
13664     virDomainObjEndAPI(&vm);
13665     return snapshot;
13666 }
13667 
13668 
13669 static char *
qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,unsigned int flags)13670 qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
13671                              unsigned int flags)
13672 {
13673     virQEMUDriver *driver = snapshot->domain->conn->privateData;
13674     virDomainObj *vm = NULL;
13675     char *xml = NULL;
13676     virDomainMomentObj *snap = NULL;
13677     char uuidstr[VIR_UUID_STRING_BUFLEN];
13678 
13679     virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
13680 
13681     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13682         return NULL;
13683 
13684     if (virDomainSnapshotGetXMLDescEnsureACL(snapshot->domain->conn, vm->def, flags) < 0)
13685         goto cleanup;
13686 
13687     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13688         goto cleanup;
13689 
13690     virUUIDFormat(snapshot->domain->uuid, uuidstr);
13691 
13692     xml = virDomainSnapshotDefFormat(uuidstr, virDomainSnapshotObjGetDef(snap),
13693                                      driver->xmlopt,
13694                                      virDomainSnapshotFormatConvertXMLFlags(flags));
13695 
13696  cleanup:
13697     virDomainObjEndAPI(&vm);
13698     return xml;
13699 }
13700 
13701 
13702 static int
qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,unsigned int flags)13703 qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
13704                             unsigned int flags)
13705 {
13706     virDomainObj *vm = NULL;
13707     int ret = -1;
13708     virDomainMomentObj *snap = NULL;
13709 
13710     virCheckFlags(0, -1);
13711 
13712     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13713         return -1;
13714 
13715     if (virDomainSnapshotIsCurrentEnsureACL(snapshot->domain->conn, vm->def) < 0)
13716         goto cleanup;
13717 
13718     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13719         goto cleanup;
13720 
13721     ret = snap == virDomainSnapshotGetCurrent(vm->snapshots);
13722 
13723  cleanup:
13724     virDomainObjEndAPI(&vm);
13725     return ret;
13726 }
13727 
13728 
13729 static int
qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,unsigned int flags)13730 qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
13731                               unsigned int flags)
13732 {
13733     virDomainObj *vm = NULL;
13734     int ret = -1;
13735     virDomainMomentObj *snap = NULL;
13736 
13737     virCheckFlags(0, -1);
13738 
13739     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13740         return -1;
13741 
13742     if (virDomainSnapshotHasMetadataEnsureACL(snapshot->domain->conn, vm->def) < 0)
13743         goto cleanup;
13744 
13745     if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
13746         goto cleanup;
13747 
13748     /* XXX Someday, we should recognize internal snapshots in qcow2
13749      * images that are not tied to a libvirt snapshot; if we ever do
13750      * that, then we would have a reason to return 0 here.  */
13751     ret = 1;
13752 
13753  cleanup:
13754     virDomainObjEndAPI(&vm);
13755     return ret;
13756 }
13757 
13758 
13759 static int
qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,unsigned int flags)13760 qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
13761                            unsigned int flags)
13762 {
13763     virDomainObj *vm = NULL;
13764     int ret = -1;
13765 
13766     virNWFilterReadLockFilterUpdates();
13767 
13768     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13769         goto cleanup;
13770 
13771     if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0)
13772         goto cleanup;
13773 
13774     ret = qemuSnapshotRevert(vm, snapshot, flags);
13775 
13776  cleanup:
13777     virDomainObjEndAPI(&vm);
13778     virNWFilterUnlockFilterUpdates();
13779     return ret;
13780 }
13781 
13782 
13783 static int
qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,unsigned int flags)13784 qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
13785                          unsigned int flags)
13786 {
13787     virDomainObj *vm = NULL;
13788     int ret = -1;
13789 
13790     if (!(vm = qemuDomObjFromSnapshot(snapshot)))
13791         return -1;
13792 
13793     if (virDomainSnapshotDeleteEnsureACL(snapshot->domain->conn, vm->def) < 0)
13794         goto cleanup;
13795 
13796     ret = qemuSnapshotDelete(vm, snapshot, flags);
13797 
13798  cleanup:
13799     virDomainObjEndAPI(&vm);
13800     return ret;
13801 }
13802 
13803 
13804 static virDomainCheckpointPtr
qemuDomainCheckpointCreateXML(virDomainPtr domain,const char * xmlDesc,unsigned int flags)13805 qemuDomainCheckpointCreateXML(virDomainPtr domain,
13806                               const char *xmlDesc,
13807                               unsigned int flags)
13808 {
13809     virDomainObj *vm = NULL;
13810     virDomainCheckpointPtr checkpoint = NULL;
13811 
13812     if (!(vm = qemuDomainObjFromDomain(domain)))
13813         goto cleanup;
13814 
13815     if (virDomainCheckpointCreateXMLEnsureACL(domain->conn, vm->def, flags) < 0)
13816         goto cleanup;
13817 
13818     checkpoint = qemuCheckpointCreateXML(domain, vm, xmlDesc, flags);
13819 
13820  cleanup:
13821     virDomainObjEndAPI(&vm);
13822     return checkpoint;
13823 }
13824 
13825 
13826 static int
qemuDomainListAllCheckpoints(virDomainPtr domain,virDomainCheckpointPtr ** chks,unsigned int flags)13827 qemuDomainListAllCheckpoints(virDomainPtr domain,
13828                              virDomainCheckpointPtr **chks,
13829                              unsigned int flags)
13830 {
13831     virDomainObj *vm = NULL;
13832     int n = -1;
13833 
13834     virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS |
13835                   VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL |
13836                   VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);
13837 
13838     if (!(vm = qemuDomainObjFromDomain(domain)))
13839         return -1;
13840 
13841     if (virDomainListAllCheckpointsEnsureACL(domain->conn, vm->def) < 0)
13842         goto cleanup;
13843 
13844     n = virDomainListCheckpoints(vm->checkpoints, NULL, domain, chks, flags);
13845 
13846  cleanup:
13847     virDomainObjEndAPI(&vm);
13848     return n;
13849 }
13850 
13851 
13852 static int
qemuDomainCheckpointListAllChildren(virDomainCheckpointPtr checkpoint,virDomainCheckpointPtr ** chks,unsigned int flags)13853 qemuDomainCheckpointListAllChildren(virDomainCheckpointPtr checkpoint,
13854                                     virDomainCheckpointPtr **chks,
13855                                     unsigned int flags)
13856 {
13857     virDomainObj *vm = NULL;
13858     virDomainMomentObj *chk = NULL;
13859     int n = -1;
13860 
13861     virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS |
13862                   VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL |
13863                   VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);
13864 
13865     if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
13866         return -1;
13867 
13868     if (virDomainCheckpointListAllChildrenEnsureACL(checkpoint->domain->conn,
13869                                                     vm->def) < 0)
13870         goto cleanup;
13871 
13872     if (!(chk = qemuCheckpointObjFromCheckpoint(vm, checkpoint)))
13873         goto cleanup;
13874 
13875     n = virDomainListCheckpoints(vm->checkpoints, chk, checkpoint->domain,
13876                                  chks, flags);
13877 
13878  cleanup:
13879     virDomainObjEndAPI(&vm);
13880     return n;
13881 }
13882 
13883 
13884 static virDomainCheckpointPtr
qemuDomainCheckpointLookupByName(virDomainPtr domain,const char * name,unsigned int flags)13885 qemuDomainCheckpointLookupByName(virDomainPtr domain,
13886                                  const char *name,
13887                                  unsigned int flags)
13888 {
13889     virDomainObj *vm;
13890     virDomainMomentObj *chk = NULL;
13891     virDomainCheckpointPtr checkpoint = NULL;
13892 
13893     virCheckFlags(0, NULL);
13894 
13895     if (!(vm = qemuDomainObjFromDomain(domain)))
13896         return NULL;
13897 
13898     if (virDomainCheckpointLookupByNameEnsureACL(domain->conn, vm->def) < 0)
13899         goto cleanup;
13900 
13901     if (!(chk = qemuCheckpointObjFromName(vm, name)))
13902         goto cleanup;
13903 
13904     checkpoint = virGetDomainCheckpoint(domain, chk->def->name);
13905 
13906  cleanup:
13907     virDomainObjEndAPI(&vm);
13908     return checkpoint;
13909 }
13910 
13911 
13912 static virDomainCheckpointPtr
qemuDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,unsigned int flags)13913 qemuDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,
13914                               unsigned int flags)
13915 {
13916     virDomainObj *vm;
13917     virDomainMomentObj *chk = NULL;
13918     virDomainCheckpointPtr parent = NULL;
13919 
13920     virCheckFlags(0, NULL);
13921 
13922     if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
13923         return NULL;
13924 
13925     if (virDomainCheckpointGetParentEnsureACL(checkpoint->domain->conn, vm->def) < 0)
13926         goto cleanup;
13927 
13928     if (!(chk = qemuCheckpointObjFromCheckpoint(vm, checkpoint)))
13929         goto cleanup;
13930 
13931     if (!chk->def->parent_name) {
13932         virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
13933                        _("checkpoint '%s' does not have a parent"),
13934                        chk->def->name);
13935         goto cleanup;
13936     }
13937 
13938     parent = virGetDomainCheckpoint(checkpoint->domain, chk->def->parent_name);
13939 
13940  cleanup:
13941     virDomainObjEndAPI(&vm);
13942     return parent;
13943 }
13944 
13945 
13946 static char *
qemuDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,unsigned int flags)13947 qemuDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,
13948                                unsigned int flags)
13949 {
13950     virDomainObj *vm = NULL;
13951     char *xml = NULL;
13952 
13953     if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
13954         return NULL;
13955 
13956     if (virDomainCheckpointGetXMLDescEnsureACL(checkpoint->domain->conn, vm->def, flags) < 0)
13957         goto cleanup;
13958 
13959     xml = qemuCheckpointGetXMLDesc(vm, checkpoint, flags);
13960 
13961  cleanup:
13962     virDomainObjEndAPI(&vm);
13963     return xml;
13964 }
13965 
13966 
13967 static int
qemuDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,unsigned int flags)13968 qemuDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,
13969                            unsigned int flags)
13970 {
13971     virDomainObj *vm = NULL;
13972     int ret = -1;
13973 
13974     if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
13975         return -1;
13976 
13977     if (virDomainCheckpointDeleteEnsureACL(checkpoint->domain->conn, vm->def) < 0)
13978         goto cleanup;
13979 
13980     ret = qemuCheckpointDelete(vm, checkpoint, flags);
13981 
13982  cleanup:
13983     virDomainObjEndAPI(&vm);
13984     return ret;
13985 }
13986 
13987 
13988 static int
qemuDomainBackupBegin(virDomainPtr domain,const char * backupXML,const char * checkpointXML,unsigned int flags)13989 qemuDomainBackupBegin(virDomainPtr domain,
13990                       const char *backupXML,
13991                       const char *checkpointXML,
13992                       unsigned int flags)
13993 {
13994     virDomainObj *vm = NULL;
13995     int ret = -1;
13996 
13997     if (!(vm = qemuDomainObjFromDomain(domain)))
13998         goto cleanup;
13999 
14000     if (virDomainBackupBeginEnsureACL(domain->conn, vm->def) < 0)
14001         goto cleanup;
14002 
14003     ret = qemuBackupBegin(vm, backupXML, checkpointXML, flags);
14004 
14005  cleanup:
14006     virDomainObjEndAPI(&vm);
14007     return ret;
14008 }
14009 
14010 
14011 static char *
qemuDomainBackupGetXMLDesc(virDomainPtr domain,unsigned int flags)14012 qemuDomainBackupGetXMLDesc(virDomainPtr domain,
14013                            unsigned int flags)
14014 {
14015     virDomainObj *vm = NULL;
14016     char *ret = NULL;
14017 
14018     if (!(vm = qemuDomainObjFromDomain(domain)))
14019         return NULL;
14020 
14021     if (virDomainBackupGetXMLDescEnsureACL(domain->conn, vm->def) < 0)
14022         goto cleanup;
14023 
14024     ret = qemuBackupGetXMLDesc(vm, flags);
14025 
14026  cleanup:
14027     virDomainObjEndAPI(&vm);
14028     return ret;
14029 }
14030 
14031 
qemuDomainQemuMonitorCommand(virDomainPtr domain,const char * cmd,char ** result,unsigned int flags)14032 static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
14033                                         char **result, unsigned int flags)
14034 {
14035     virQEMUDriver *driver = domain->conn->privateData;
14036     virDomainObj *vm = NULL;
14037     int ret = -1;
14038     qemuDomainObjPrivate *priv;
14039     bool hmp;
14040 
14041     virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
14042 
14043     if (!(vm = qemuDomainObjFromDomain(domain)))
14044         goto cleanup;
14045 
14046     if (virDomainQemuMonitorCommandEnsureACL(domain->conn, vm->def) < 0)
14047         goto cleanup;
14048 
14049     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14050         goto cleanup;
14051 
14052     if (virDomainObjCheckActive(vm) < 0)
14053         goto endjob;
14054 
14055     priv = vm->privateData;
14056 
14057     qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, NULL);
14058 
14059     hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);
14060 
14061     qemuDomainObjEnterMonitor(driver, vm);
14062     ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
14063     if (qemuDomainObjExitMonitor(driver, vm) < 0)
14064         ret = -1;
14065 
14066  endjob:
14067     qemuDomainObjEndJob(driver, vm);
14068 
14069  cleanup:
14070     virDomainObjEndAPI(&vm);
14071     return ret;
14072 }
14073 
14074 
14075 static int
qemuDomainOpenConsole(virDomainPtr dom,const char * dev_name,virStreamPtr st,unsigned int flags)14076 qemuDomainOpenConsole(virDomainPtr dom,
14077                       const char *dev_name,
14078                       virStreamPtr st,
14079                       unsigned int flags)
14080 {
14081     virDomainObj *vm = NULL;
14082     int ret = -1;
14083     size_t i;
14084     virDomainChrDef *chr = NULL;
14085     qemuDomainObjPrivate *priv;
14086 
14087     virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE |
14088                   VIR_DOMAIN_CONSOLE_FORCE, -1);
14089 
14090     if (!(vm = qemuDomainObjFromDomain(dom)))
14091         goto cleanup;
14092 
14093     if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
14094         goto cleanup;
14095 
14096     if (virDomainObjCheckActive(vm) < 0)
14097         goto cleanup;
14098 
14099     priv = vm->privateData;
14100 
14101     if (dev_name) {
14102         for (i = 0; !chr && i < vm->def->nconsoles; i++) {
14103             if (vm->def->consoles[i]->info.alias &&
14104                 STREQ(dev_name, vm->def->consoles[i]->info.alias))
14105                 chr = vm->def->consoles[i];
14106         }
14107         for (i = 0; !chr && i < vm->def->nserials; i++) {
14108             if (STREQ(dev_name, vm->def->serials[i]->info.alias))
14109                 chr = vm->def->serials[i];
14110         }
14111         for (i = 0; !chr && i < vm->def->nparallels; i++) {
14112             if (STREQ(dev_name, vm->def->parallels[i]->info.alias))
14113                 chr = vm->def->parallels[i];
14114         }
14115     } else {
14116         if (vm->def->nconsoles)
14117             chr = vm->def->consoles[0];
14118         else if (vm->def->nserials)
14119             chr = vm->def->serials[0];
14120     }
14121 
14122     if (!chr) {
14123         virReportError(VIR_ERR_INTERNAL_ERROR,
14124                        _("cannot find character device %s"),
14125                        NULLSTR(dev_name));
14126         goto cleanup;
14127     }
14128 
14129     if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
14130         virReportError(VIR_ERR_INTERNAL_ERROR,
14131                        _("character device %s is not using a PTY"),
14132                        dev_name ? dev_name : NULLSTR(chr->info.alias));
14133         goto cleanup;
14134     }
14135 
14136     /* handle mutually exclusive access to console devices */
14137     ret = virChrdevOpen(priv->devs,
14138                         chr->source,
14139                         st,
14140                         (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
14141 
14142     if (ret == 1) {
14143         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
14144                        _("Active console session exists for this domain"));
14145         ret = -1;
14146     }
14147 
14148  cleanup:
14149     virDomainObjEndAPI(&vm);
14150     return ret;
14151 }
14152 
14153 static int
qemuDomainOpenChannel(virDomainPtr dom,const char * name,virStreamPtr st,unsigned int flags)14154 qemuDomainOpenChannel(virDomainPtr dom,
14155                       const char *name,
14156                       virStreamPtr st,
14157                       unsigned int flags)
14158 {
14159     virDomainObj *vm = NULL;
14160     int ret = -1;
14161     size_t i;
14162     virDomainChrDef *chr = NULL;
14163     qemuDomainObjPrivate *priv;
14164 
14165     virCheckFlags(VIR_DOMAIN_CHANNEL_FORCE, -1);
14166 
14167     if (!(vm = qemuDomainObjFromDomain(dom)))
14168         goto cleanup;
14169 
14170     if (virDomainOpenChannelEnsureACL(dom->conn, vm->def) < 0)
14171         goto cleanup;
14172 
14173     if (virDomainObjCheckActive(vm) < 0)
14174         goto cleanup;
14175 
14176     priv = vm->privateData;
14177 
14178     if (name) {
14179         for (i = 0; !chr && i < vm->def->nchannels; i++) {
14180             if (STREQ(name, vm->def->channels[i]->info.alias))
14181                 chr = vm->def->channels[i];
14182 
14183             if (vm->def->channels[i]->targetType == \
14184                 VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
14185                 STREQ_NULLABLE(name, vm->def->channels[i]->target.name))
14186                 chr = vm->def->channels[i];
14187         }
14188     } else {
14189         if (vm->def->nchannels)
14190             chr = vm->def->channels[0];
14191     }
14192 
14193     if (!chr) {
14194         virReportError(VIR_ERR_INTERNAL_ERROR,
14195                        _("cannot find channel %s"),
14196                        NULLSTR(name));
14197         goto cleanup;
14198     }
14199 
14200     if (chr->source->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
14201         virReportError(VIR_ERR_INTERNAL_ERROR,
14202                        _("channel %s is not using a UNIX socket"),
14203                        name ? name : NULLSTR(chr->info.alias));
14204         goto cleanup;
14205     }
14206 
14207     /* handle mutually exclusive access to channel devices */
14208     ret = virChrdevOpen(priv->devs,
14209                         chr->source,
14210                         st,
14211                         (flags & VIR_DOMAIN_CHANNEL_FORCE) != 0);
14212 
14213     if (ret == 1) {
14214         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
14215                        _("Active channel stream exists for this domain"));
14216         ret = -1;
14217     }
14218 
14219  cleanup:
14220     virDomainObjEndAPI(&vm);
14221     return ret;
14222 }
14223 
14224 
14225 /* Called while holding the VM job lock, to implement a block job
14226  * abort with pivot; this updates the VM definition as appropriate, on
14227  * either success or failure.  */
14228 static int
qemuDomainBlockPivot(virQEMUDriver * driver,virDomainObj * vm,qemuBlockJobData * job,virDomainDiskDef * disk)14229 qemuDomainBlockPivot(virQEMUDriver *driver,
14230                      virDomainObj *vm,
14231                      qemuBlockJobData *job,
14232                      virDomainDiskDef *disk)
14233 {
14234     g_autoptr(qemuBlockStorageSourceChainData) chainattachdata = NULL;
14235     int ret = -1;
14236     qemuDomainObjPrivate *priv = vm->privateData;
14237     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
14238     g_autoptr(virJSONValue) bitmapactions = NULL;
14239     g_autoptr(virJSONValue) reopenactions = NULL;
14240 
14241     if (job->state != QEMU_BLOCKJOB_STATE_READY) {
14242         virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
14243                        _("block job '%s' not ready for pivot yet"),
14244                        job->name);
14245         return -1;
14246     }
14247 
14248     switch ((qemuBlockJobType) job->type) {
14249     case QEMU_BLOCKJOB_TYPE_NONE:
14250     case QEMU_BLOCKJOB_TYPE_LAST:
14251         virReportError(VIR_ERR_INTERNAL_ERROR,
14252                        _("invalid job type '%d'"), job->type);
14253         return -1;
14254 
14255     case QEMU_BLOCKJOB_TYPE_PULL:
14256     case QEMU_BLOCKJOB_TYPE_COMMIT:
14257     case QEMU_BLOCKJOB_TYPE_BACKUP:
14258     case QEMU_BLOCKJOB_TYPE_INTERNAL:
14259     case QEMU_BLOCKJOB_TYPE_CREATE:
14260     case QEMU_BLOCKJOB_TYPE_BROKEN:
14261         virReportError(VIR_ERR_OPERATION_INVALID,
14262                        _("job type '%s' does not support pivot"),
14263                        qemuBlockjobTypeToString(job->type));
14264         return -1;
14265 
14266     case QEMU_BLOCKJOB_TYPE_COPY:
14267         if (blockdev && !job->jobflagsmissing) {
14268             bool shallow = job->jobflags & VIR_DOMAIN_BLOCK_COPY_SHALLOW;
14269             bool reuse = job->jobflags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT;
14270 
14271             bitmapactions = virJSONValueNewArray();
14272 
14273             if (qemuMonitorTransactionBitmapAdd(bitmapactions,
14274                                                 disk->mirror->nodeformat,
14275                                                 "libvirt-tmp-activewrite",
14276                                                 false,
14277                                                 false,
14278                                                 0) < 0)
14279                 return -1;
14280 
14281             /* Open and install the backing chain of 'mirror' late if we can use
14282              * blockdev-snapshot to do it. This is to appease oVirt that wants
14283              * to copy data into the backing chain while the top image is being
14284              * copied shallow */
14285             if (reuse && shallow &&
14286                 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY) &&
14287                 virStorageSourceHasBacking(disk->mirror)) {
14288 
14289                 if (!(chainattachdata = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->mirror->backingStore)))
14290                     return -1;
14291 
14292                 reopenactions = virJSONValueNewArray();
14293 
14294                 if (qemuMonitorTransactionSnapshotBlockdev(reopenactions,
14295                                                            disk->mirror->backingStore->nodeformat,
14296                                                            disk->mirror->nodeformat))
14297                     return -1;
14298             }
14299 
14300         }
14301         break;
14302 
14303     case QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT:
14304         if (blockdev) {
14305             bitmapactions = virJSONValueNewArray();
14306 
14307             if (qemuMonitorTransactionBitmapAdd(bitmapactions,
14308                                                 job->data.commit.base->nodeformat,
14309                                                 "libvirt-tmp-activewrite",
14310                                                 false,
14311                                                 false,
14312                                                 0) < 0)
14313                 return -1;
14314         }
14315 
14316         break;
14317     }
14318 
14319     qemuDomainObjEnterMonitor(driver, vm);
14320     if (blockdev) {
14321         int rc = 0;
14322 
14323         if (chainattachdata) {
14324             if ((rc = qemuBlockStorageSourceChainAttach(priv->mon, chainattachdata)) == 0) {
14325                 /* install backing images on success, or unplug them on failure */
14326                 if ((rc = qemuMonitorTransaction(priv->mon, &reopenactions)) != 0)
14327                     qemuBlockStorageSourceChainDetach(priv->mon, chainattachdata);
14328             }
14329         }
14330 
14331         if (bitmapactions && rc == 0)
14332             ignore_value(qemuMonitorTransaction(priv->mon, &bitmapactions));
14333 
14334         if (rc == 0)
14335             ret = qemuMonitorJobComplete(priv->mon, job->name);
14336     } else {
14337         ret = qemuMonitorDrivePivot(priv->mon, job->name);
14338     }
14339     if (qemuDomainObjExitMonitor(driver, vm) < 0)
14340         return -1;
14341 
14342     /* The pivot failed. The block job in QEMU remains in the synchronised state */
14343     if (ret < 0)
14344         return -1;
14345 
14346     if (disk && disk->mirror)
14347         disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT;
14348     job->state = QEMU_BLOCKJOB_STATE_PIVOTING;
14349 
14350     return ret;
14351 }
14352 
14353 
14354 /* bandwidth in MiB/s per public API. Caller must lock vm beforehand,
14355  * and not access it afterwards.  */
14356 static int
qemuDomainBlockPullCommon(virDomainObj * vm,const char * path,const char * base,unsigned long bandwidth,unsigned int flags)14357 qemuDomainBlockPullCommon(virDomainObj *vm,
14358                           const char *path,
14359                           const char *base,
14360                           unsigned long bandwidth,
14361                           unsigned int flags)
14362 {
14363     qemuDomainObjPrivate *priv = vm->privateData;
14364     virQEMUDriver *driver = priv->driver;
14365     const char *device = NULL;
14366     const char *jobname = NULL;
14367     virDomainDiskDef *disk;
14368     virStorageSource *baseSource = NULL;
14369     g_autofree char *basePath = NULL;
14370     g_autofree char *backingPath = NULL;
14371     unsigned long long speed = bandwidth;
14372     qemuBlockJobData *job = NULL;
14373     bool persistjob = false;
14374     const char *nodebase = NULL;
14375     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
14376     int ret = -1;
14377 
14378     if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
14379         virReportError(VIR_ERR_INVALID_ARG, "%s",
14380                        _("flag VIR_DOMAIN_BLOCK_REBASE_RELATIVE is valid only "
14381                          "with non-null base"));
14382         goto cleanup;
14383     }
14384 
14385     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
14386         goto cleanup;
14387 
14388     if (virDomainObjCheckActive(vm) < 0)
14389         goto endjob;
14390 
14391     if (qemuDomainSupportsCheckpointsBlockjobs(vm) < 0)
14392         goto endjob;
14393 
14394     if (!(disk = qemuDomainDiskByName(vm->def, path)))
14395         goto endjob;
14396 
14397     if (qemuDomainDiskBlockJobIsActive(disk))
14398         goto endjob;
14399 
14400     if (!qemuDomainDiskBlockJobIsSupported(vm, disk))
14401         goto endjob;
14402 
14403     if (base &&
14404         !(baseSource = virStorageSourceChainLookup(disk->src, disk->src,
14405                                                    base, disk->dst, NULL)))
14406         goto endjob;
14407 
14408     if (baseSource) {
14409         if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
14410             if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
14411                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
14412                                _("this QEMU binary doesn't support relative "
14413                                  "block pull/rebase"));
14414                 goto endjob;
14415             }
14416 
14417             if (blockdev &&
14418                 qemuBlockUpdateRelativeBacking(vm, disk->src, disk->src) < 0)
14419                 goto endjob;
14420 
14421             if (virStorageSourceGetRelativeBackingPath(disk->src->backingStore,
14422                                                        baseSource,
14423                                                        &backingPath) < 0)
14424                 goto endjob;
14425 
14426             if (!backingPath) {
14427                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14428                                _("can't keep relative backing relationship"));
14429                 goto endjob;
14430             }
14431         }
14432     }
14433 
14434     /* Convert bandwidth MiB to bytes, if needed */
14435     if (!(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES)) {
14436         if (speed > LLONG_MAX >> 20) {
14437             virReportError(VIR_ERR_OVERFLOW,
14438                            _("bandwidth must be less than %llu"),
14439                            LLONG_MAX >> 20);
14440             goto endjob;
14441         }
14442         speed <<= 20;
14443     }
14444 
14445     if (!(job = qemuBlockJobDiskNewPull(vm, disk, baseSource, flags)))
14446         goto endjob;
14447 
14448     if (blockdev) {
14449         jobname = job->name;
14450         persistjob = true;
14451         if (baseSource) {
14452             nodebase = baseSource->nodeformat;
14453             if (!backingPath &&
14454                 !(backingPath = qemuBlockGetBackingStoreString(baseSource, false)))
14455                 goto endjob;
14456         }
14457         device = disk->src->nodeformat;
14458     } else {
14459         device = job->name;
14460     }
14461 
14462     qemuDomainObjEnterMonitor(driver, vm);
14463     if (!blockdev && baseSource)
14464         basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
14465                                              baseSource);
14466 
14467     if (blockdev ||
14468         (!baseSource || basePath))
14469         ret = qemuMonitorBlockStream(priv->mon, device, jobname, persistjob, basePath,
14470                                      nodebase, backingPath, speed);
14471     if (qemuDomainObjExitMonitor(driver, vm) < 0)
14472         ret = -1;
14473 
14474     if (ret < 0)
14475         goto endjob;
14476 
14477     qemuBlockJobStarted(job, vm);
14478 
14479  endjob:
14480     qemuDomainObjEndJob(driver, vm);
14481 
14482  cleanup:
14483     qemuBlockJobStartupFinalize(vm, job);
14484     virDomainObjEndAPI(&vm);
14485     return ret;
14486 }
14487 
14488 
14489 static int
qemuDomainBlockJobAbort(virDomainPtr dom,const char * path,unsigned int flags)14490 qemuDomainBlockJobAbort(virDomainPtr dom,
14491                         const char *path,
14492                         unsigned int flags)
14493 {
14494     virQEMUDriver *driver = dom->conn->privateData;
14495     virDomainDiskDef *disk = NULL;
14496     bool pivot = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT);
14497     bool async = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC);
14498     g_autoptr(qemuBlockJobData) job = NULL;
14499     virDomainObj *vm;
14500     qemuDomainObjPrivate *priv = NULL;
14501     int ret = -1;
14502 
14503     virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC |
14504                   VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1);
14505 
14506     if (!(vm = qemuDomainObjFromDomain(dom)))
14507         return -1;
14508 
14509     if (virDomainBlockJobAbortEnsureACL(dom->conn, vm->def) < 0)
14510         goto cleanup;
14511 
14512     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
14513         goto cleanup;
14514 
14515     if (virDomainObjCheckActive(vm) < 0)
14516         goto endjob;
14517 
14518     if (!(disk = qemuDomainDiskByName(vm->def, path)))
14519         goto endjob;
14520 
14521     if (!(job = qemuBlockJobDiskGetJob(disk))) {
14522         virReportError(VIR_ERR_INVALID_ARG,
14523                        _("disk %s does not have an active block job"), disk->dst);
14524         goto endjob;
14525     }
14526 
14527     priv = vm->privateData;
14528 
14529     if (job->state == QEMU_BLOCKJOB_STATE_ABORTING ||
14530         job->state == QEMU_BLOCKJOB_STATE_PIVOTING) {
14531         virReportError(VIR_ERR_OPERATION_INVALID,
14532                        _("block job on disk '%s' is still being ended"),
14533                        disk->dst);
14534         goto endjob;
14535     }
14536 
14537     if (!async)
14538         qemuBlockJobSyncBegin(job);
14539 
14540     if (pivot) {
14541         if ((ret = qemuDomainBlockPivot(driver, vm, job, disk)) < 0)
14542             goto endjob;
14543     } else {
14544         qemuDomainObjEnterMonitor(driver, vm);
14545         ret = qemuMonitorBlockJobCancel(priv->mon, job->name, false);
14546         if (qemuDomainObjExitMonitor(driver, vm) < 0) {
14547             ret = -1;
14548             goto endjob;
14549         }
14550 
14551         if (ret < 0)
14552             goto endjob;
14553 
14554         if (disk->mirror)
14555             disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_ABORT;
14556         job->state = QEMU_BLOCKJOB_STATE_ABORTING;
14557     }
14558 
14559     qemuDomainSaveStatus(vm);
14560 
14561     if (!async) {
14562         qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
14563         while (qemuBlockJobIsRunning(job)) {
14564             if (virDomainObjWait(vm) < 0) {
14565                 ret = -1;
14566                 goto endjob;
14567             }
14568             qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
14569         }
14570 
14571         if (pivot &&
14572             job->state == QEMU_BLOCKJOB_STATE_FAILED) {
14573             if (job->errmsg) {
14574                 virReportError(VIR_ERR_OPERATION_FAILED,
14575                                _("block job '%s' failed while pivoting"),
14576                                job->name);
14577             } else {
14578                 virReportError(VIR_ERR_OPERATION_FAILED,
14579                                _("block job '%s' failed while pivoting: %s"),
14580                                job->name, job->errmsg);
14581             }
14582 
14583             ret = -1;
14584             goto endjob;
14585         }
14586     }
14587 
14588  endjob:
14589     if (job && !async)
14590         qemuBlockJobSyncEnd(vm, job, QEMU_ASYNC_JOB_NONE);
14591     qemuDomainObjEndJob(driver, vm);
14592 
14593  cleanup:
14594     virDomainObjEndAPI(&vm);
14595     return ret;
14596 }
14597 
14598 
14599 static int
qemuBlockJobInfoTranslate(qemuMonitorBlockJobInfo * rawInfo,virDomainBlockJobInfoPtr info,qemuBlockJobData * job,bool reportBytes)14600 qemuBlockJobInfoTranslate(qemuMonitorBlockJobInfo *rawInfo,
14601                           virDomainBlockJobInfoPtr info,
14602                           qemuBlockJobData *job,
14603                           bool reportBytes)
14604 {
14605     info->type = job->type;
14606 
14607     /* If the job data is no longer present this means that the job already
14608      * disappeared in qemu (pre-blockdev) but libvirt didn't process the
14609      * finishing yet. Fake a incomplete job. */
14610     if (!rawInfo) {
14611         info->cur = 0;
14612         info->end = 1;
14613         return 0;
14614     }
14615 
14616     info->cur = rawInfo->cur;
14617     info->end = rawInfo->end;
14618 
14619     /* Fix job completeness reporting. If cur == end mgmt
14620      * applications think job is completed. Except when both cur
14621      * and end are zero, in which case qemu hasn't started the
14622      * job yet. */
14623     if (info->cur == 0 && info->end == 0) {
14624         if (rawInfo->ready_present) {
14625             info->end = 1;
14626             if (rawInfo->ready)
14627                 info->cur = 1;
14628         }
14629     }
14630 
14631     /* If qemu reports that it's not ready yet don't make the job go to
14632      * cur == end as some apps wrote code polling this instead of waiting for
14633      * the ready event */
14634     if (rawInfo->ready_present &&
14635         !rawInfo->ready &&
14636         info->cur == info->end &&
14637         info->cur > 0)
14638         info->cur -= 1;
14639 
14640     if (rawInfo->bandwidth && !reportBytes)
14641         rawInfo->bandwidth = VIR_DIV_UP(rawInfo->bandwidth, 1024 * 1024);
14642     info->bandwidth = rawInfo->bandwidth;
14643     if (info->bandwidth != rawInfo->bandwidth) {
14644         virReportError(VIR_ERR_OVERFLOW,
14645                        _("bandwidth %llu cannot be represented in result"),
14646                        rawInfo->bandwidth);
14647         return -1;
14648     }
14649 
14650     return 0;
14651 }
14652 
14653 
14654 static int
qemuDomainGetBlockJobInfo(virDomainPtr dom,const char * path,virDomainBlockJobInfoPtr info,unsigned int flags)14655 qemuDomainGetBlockJobInfo(virDomainPtr dom,
14656                           const char *path,
14657                           virDomainBlockJobInfoPtr info,
14658                           unsigned int flags)
14659 {
14660     virQEMUDriver *driver = dom->conn->privateData;
14661     virDomainObj *vm;
14662     virDomainDiskDef *disk;
14663     int ret = -1;
14664     qemuMonitorBlockJobInfo *rawInfo;
14665     g_autoptr(qemuBlockJobData) job = NULL;
14666     g_autoptr(GHashTable) blockjobstats = NULL;
14667 
14668     virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1);
14669 
14670     if (!(vm = qemuDomainObjFromDomain(dom)))
14671         return -1;
14672 
14673     if (virDomainGetBlockJobInfoEnsureACL(dom->conn, vm->def) < 0)
14674         goto cleanup;
14675 
14676 
14677     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14678         goto cleanup;
14679 
14680     if (virDomainObjCheckActive(vm) < 0)
14681         goto endjob;
14682 
14683     if (!(disk = qemuDomainDiskByName(vm->def, path)))
14684         goto endjob;
14685 
14686     if (!(job = qemuBlockJobDiskGetJob(disk))) {
14687         ret = 0;
14688         goto endjob;
14689     }
14690 
14691     qemuDomainObjEnterMonitor(driver, vm);
14692     blockjobstats = qemuMonitorGetAllBlockJobInfo(qemuDomainGetMonitor(vm), true);
14693     if (qemuDomainObjExitMonitor(driver, vm) < 0 || !blockjobstats)
14694         goto endjob;
14695 
14696     rawInfo = g_hash_table_lookup(blockjobstats, job->name);
14697 
14698     if (qemuBlockJobInfoTranslate(rawInfo, info, job,
14699                                   flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES) < 0)
14700         goto endjob;
14701 
14702     ret = 1;
14703 
14704  endjob:
14705     qemuDomainObjEndJob(driver, vm);
14706 
14707  cleanup:
14708     virDomainObjEndAPI(&vm);
14709     return ret;
14710 }
14711 
14712 
14713 static int
qemuDomainBlockJobSetSpeed(virDomainPtr dom,const char * path,unsigned long bandwidth,unsigned int flags)14714 qemuDomainBlockJobSetSpeed(virDomainPtr dom,
14715                            const char *path,
14716                            unsigned long bandwidth,
14717                            unsigned int flags)
14718 {
14719     virQEMUDriver *driver = dom->conn->privateData;
14720     virDomainDiskDef *disk;
14721     int ret = -1;
14722     virDomainObj *vm;
14723     unsigned long long speed = bandwidth;
14724     g_autoptr(qemuBlockJobData) job = NULL;
14725 
14726     virCheckFlags(VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES, -1);
14727 
14728     /* Convert bandwidth MiB to bytes, if needed */
14729     if (!(flags & VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES)) {
14730         if (speed > LLONG_MAX >> 20) {
14731             virReportError(VIR_ERR_OVERFLOW,
14732                            _("bandwidth must be less than %llu"),
14733                            LLONG_MAX >> 20);
14734             return -1;
14735         }
14736         speed <<= 20;
14737     }
14738 
14739     if (!(vm = qemuDomainObjFromDomain(dom)))
14740         return -1;
14741 
14742     if (virDomainBlockJobSetSpeedEnsureACL(dom->conn, vm->def) < 0)
14743         goto cleanup;
14744 
14745     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
14746         goto cleanup;
14747 
14748     if (virDomainObjCheckActive(vm) < 0)
14749         goto endjob;
14750 
14751     if (!(disk = qemuDomainDiskByName(vm->def, path)))
14752         goto endjob;
14753 
14754     if (!(job = qemuBlockJobDiskGetJob(disk))) {
14755         virReportError(VIR_ERR_INVALID_ARG,
14756                        _("disk %s does not have an active block job"), disk->dst);
14757         goto endjob;
14758     }
14759 
14760     qemuDomainObjEnterMonitor(driver, vm);
14761     ret = qemuMonitorBlockJobSetSpeed(qemuDomainGetMonitor(vm),
14762                                       job->name,
14763                                       speed);
14764     if (qemuDomainObjExitMonitor(driver, vm) < 0)
14765         ret = -1;
14766 
14767  endjob:
14768     qemuDomainObjEndJob(driver, vm);
14769 
14770  cleanup:
14771     virDomainObjEndAPI(&vm);
14772 
14773     return ret;
14774 }
14775 
14776 
14777 static int
qemuDomainBlockCopyValidateMirror(virStorageSource * mirror,const char * dst,bool * reuse)14778 qemuDomainBlockCopyValidateMirror(virStorageSource *mirror,
14779                                   const char *dst,
14780                                   bool *reuse)
14781 {
14782     int desttype = virStorageSourceGetActualType(mirror);
14783     struct stat st;
14784 
14785     if (!virStorageSourceIsLocalStorage(mirror))
14786         return 0;
14787 
14788     if (virStorageSourceAccess(mirror, F_OK) < 0) {
14789         if (errno != ENOENT) {
14790             virReportSystemError(errno, "%s",
14791                                  _("unable to verify existence of "
14792                                    "block copy target"));
14793             return -1;
14794         }
14795 
14796         if (*reuse || desttype == VIR_STORAGE_TYPE_BLOCK) {
14797             virReportSystemError(errno,
14798                                  _("missing destination file for disk %s: %s"),
14799                                  dst, mirror->path);
14800             return -1;
14801         }
14802     } else {
14803         if (virStorageSourceStat(mirror, &st) < 0) {
14804             virReportSystemError(errno,
14805                                  _("unable to stat block copy target '%s'"),
14806                                  mirror->path);
14807             return -1;
14808         }
14809 
14810         if (S_ISBLK(st.st_mode)) {
14811             /* if the target is a block device, assume that we are reusing it,
14812              * so there are no attempts to create it */
14813             *reuse = true;
14814         } else {
14815             if (st.st_size && !(*reuse)) {
14816                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14817                                _("external destination file for disk %s already "
14818                                  "exists and is not a block device: %s"),
14819                                dst, mirror->path);
14820                 return -1;
14821             }
14822 
14823             if (desttype == VIR_STORAGE_TYPE_BLOCK) {
14824                 virReportError(VIR_ERR_INVALID_ARG,
14825                                _("blockdev flag requested for disk %s, but file "
14826                                  "'%s' is not a block device"),
14827                                dst, mirror->path);
14828                 return -1;
14829             }
14830         }
14831     }
14832 
14833     return 0;
14834 }
14835 
14836 
14837 /**
14838  * qemuDomainBlockCopyCommonValidateUserMirrorBackingStore:
14839  * @mirror: target of the block copy
14840  * @flags: block copy API flags
14841  * @blockdev: true if blockdev is used for the VM
14842  *
14843  * Validates whether backingStore of @mirror makes sense according to @flags.
14844  * This makes sure that:
14845  * 1) mirror has a terminator if it isn't supposed to have backing chain
14846  * 2) if shallow copy is requested there is a chain or prepopulated image
14847  * 3) user specified chain is present only when blockdev is used
14848  * 4) if deep copy is requested, there's no chain
14849  */
14850 static int
qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(virStorageSource * mirror,bool shallow,bool blockdev)14851 qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(virStorageSource *mirror,
14852                                                         bool shallow,
14853                                                         bool blockdev)
14854 {
14855     if (!virStorageSourceHasBacking(mirror)) {
14856         /* for deep copy there won't be backing chain so we can terminate it */
14857         if (!mirror->backingStore && !shallow)
14858             mirror->backingStore = virStorageSourceNew();
14859 
14860         /* When reusing an external image we document that the user must ensure
14861          * that the <mirror> image must expose data as the original image did
14862          * either by providing correct chain or prepopulating the image. This
14863          * means we can't validate this any more regardless of whether shallow
14864          * copy is requested.
14865          *
14866          * For a copy when we are not reusing external image requesting shallow
14867          * is okay and will inherit the original backing chain */
14868     } else {
14869         if (!blockdev) {
14870             virReportError(VIR_ERR_INVALID_ARG, "%s",
14871                            _("backingStore of mirror target is not supported by this qemu"));
14872             return -1;
14873         }
14874 
14875         if (!shallow) {
14876             virReportError(VIR_ERR_INVALID_ARG, "%s",
14877                            _("backingStore of mirror without VIR_DOMAIN_BLOCK_COPY_SHALLOW doesn't make sense"));
14878             return -1;
14879         }
14880 
14881         if (qemuDomainStorageSourceValidateDepth(mirror, 0, NULL) < 0)
14882             return -1;
14883     }
14884 
14885     return 0;
14886 }
14887 
14888 
14889 /* bandwidth in bytes/s.  Caller must lock vm beforehand, and not
14890  * access mirror afterwards.  */
14891 static int
qemuDomainBlockCopyCommon(virDomainObj * vm,virConnectPtr conn,const char * path,virStorageSource * mirrorsrc,unsigned long long bandwidth,unsigned int granularity,unsigned long long buf_size,unsigned int flags,bool keepParentLabel)14892 qemuDomainBlockCopyCommon(virDomainObj *vm,
14893                           virConnectPtr conn,
14894                           const char *path,
14895                           virStorageSource *mirrorsrc,
14896                           unsigned long long bandwidth,
14897                           unsigned int granularity,
14898                           unsigned long long buf_size,
14899                           unsigned int flags,
14900                           bool keepParentLabel)
14901 {
14902     virQEMUDriver *driver = conn->privateData;
14903     qemuDomainObjPrivate *priv = vm->privateData;
14904     virDomainDiskDef *disk = NULL;
14905     int ret = -1;
14906     bool need_unlink = false;
14907     bool need_revoke = false;
14908     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
14909     const char *format = NULL;
14910     bool mirror_reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT);
14911     bool mirror_shallow = !!(flags & VIR_DOMAIN_BLOCK_COPY_SHALLOW);
14912     bool existing = mirror_reuse;
14913     qemuBlockJobData *job = NULL;
14914     g_autoptr(virStorageSource) mirror = mirrorsrc;
14915     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
14916     bool supports_create = false;
14917     bool supports_access = false;
14918     bool supports_detect = false;
14919     g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
14920     g_autoptr(qemuBlockStorageSourceChainData) crdata = NULL;
14921     virStorageSource *n;
14922     virStorageSource *mirrorBacking = NULL;
14923     g_autoptr(GHashTable) blockNamedNodeData = NULL;
14924     int rc = 0;
14925 
14926     /* Preliminaries: find the disk we are editing, sanity checks */
14927     virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
14928                   VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
14929                   VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB, -1);
14930 
14931     if (virStorageSourceIsRelative(mirror)) {
14932         virReportError(VIR_ERR_INVALID_ARG, "%s",
14933                        _("absolute path must be used as block copy target"));
14934         return -1;
14935     }
14936 
14937     if (bandwidth > LLONG_MAX) {
14938         virReportError(VIR_ERR_INVALID_ARG,
14939                        _("bandwidth must be less than "
14940                          "'%llu' bytes/s (%llu MiB/s)"),
14941                        LLONG_MAX, LLONG_MAX >> 20);
14942         return -1;
14943     }
14944 
14945     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
14946         return -1;
14947 
14948     if (virDomainObjCheckActive(vm) < 0)
14949         goto endjob;
14950 
14951     if (qemuDomainSupportsCheckpointsBlockjobs(vm) < 0)
14952         goto endjob;
14953 
14954     if (!(disk = qemuDomainDiskByName(vm->def, path)))
14955         goto endjob;
14956 
14957     if (qemuDomainDiskBlockJobIsActive(disk))
14958         goto endjob;
14959 
14960     if (!qemuDomainDiskBlockJobIsSupported(vm, disk))
14961         goto endjob;
14962 
14963     if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN &&
14964         virDomainDiskDefSourceLUNValidate(mirror) < 0)
14965         goto endjob;
14966 
14967     if (!(flags & VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB) &&
14968         vm->persistent) {
14969         /* XXX if qemu ever lets us start a new domain with mirroring
14970          * already active, we can relax this; but for now, the risk of
14971          * 'managedsave' due to libvirt-guests means we can't risk
14972          * this on persistent domains.  */
14973         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14974                        _("domain is not transient"));
14975         goto endjob;
14976     }
14977 
14978     /* clear the _SHALLOW flag if there is only one layer */
14979     if (!virStorageSourceHasBacking(disk->src)) {
14980         flags &= ~VIR_DOMAIN_BLOCK_COPY_SHALLOW;
14981         mirror_shallow = false;
14982     }
14983 
14984     if (qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(mirror,
14985                                                                 mirror_shallow,
14986                                                                 blockdev) < 0)
14987         goto endjob;
14988 
14989     /* unless the user provides a pre-created file, shallow copy into a raw
14990      * file is not possible */
14991     if (mirror_shallow && !existing && mirror->format == VIR_STORAGE_FILE_RAW) {
14992         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14993                        _("shallow copy of disk '%s' into a raw file "
14994                          "is not possible"),
14995                        disk->dst);
14996         goto endjob;
14997     }
14998 
14999     /* Prepare the destination file.  */
15000     if (!blockdev &&
15001         !virStorageSourceIsLocalStorage(mirror)) {
15002         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
15003                        _("non-file destination not supported yet"));
15004         goto endjob;
15005     }
15006 
15007     supports_access = virStorageSourceSupportsAccess(mirror) == 1;
15008     supports_create = virStorageSourceSupportsCreate(mirror) == 1;
15009     supports_detect = virStorageSourceSupportsBackingChainTraversal(mirror) == 1;
15010 
15011     if (supports_access || supports_create || supports_detect) {
15012         if (qemuDomainStorageFileInit(driver, vm, mirror, NULL) < 0)
15013             goto endjob;
15014     }
15015 
15016     if (supports_access &&
15017         qemuDomainBlockCopyValidateMirror(mirror, disk->dst, &existing) < 0)
15018         goto endjob;
15019 
15020     if (!mirror->format) {
15021         if (!mirror_reuse) {
15022             mirror->format = disk->src->format;
15023         } else {
15024             /* If the user passed the REUSE_EXT flag, then either they
15025              * can also pass the RAW flag or use XML to tell us the format.
15026              * So if we get here, we assume it is safe for us to probe the
15027              * format from the file that we will be using.  */
15028             if (!supports_detect ||
15029                 !virStorageSourceIsLocalStorage(mirror) ||
15030                 (mirror->format = virStorageFileProbeFormat(mirror->path, cfg->user,
15031                                                             cfg->group)) < 0) {
15032                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15033                                _("reused mirror destination format must be specified"));
15034                 goto endjob;
15035             }
15036         }
15037     }
15038 
15039     /* When copying a shareable disk we need to make sure that the disk can
15040      * be safely shared, since block copy may change the format. */
15041     if (disk->src->shared && !disk->src->readonly &&
15042         !qemuBlockStorageSourceSupportsConcurrentAccess(mirror)) {
15043         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15044                        _("can't pivot a shared disk to a storage volume not "
15045                          "supporting sharing"));
15046         goto endjob;
15047     }
15048 
15049     /* pre-create the image file. In case when 'blockdev' is used this is
15050      * required so that libvirt can properly label the image for access by qemu */
15051     if (!existing) {
15052         if (supports_create) {
15053             if (virStorageSourceCreate(mirror) < 0) {
15054                 virReportSystemError(errno, "%s", _("failed to create copy target"));
15055                 goto endjob;
15056             }
15057 
15058             need_unlink = true;
15059         }
15060     }
15061 
15062     if (mirror->format > 0)
15063         format = virStorageFileFormatTypeToString(mirror->format);
15064 
15065     if (virStorageSourceInitChainElement(mirror, disk->src,
15066                                          keepParentLabel) < 0)
15067         goto endjob;
15068 
15069     if (mirror->readonly) {
15070         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN)) {
15071             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15072                            _("copy of read-only disks is not supported"));
15073             goto endjob;
15074         }
15075         mirror->readonly = false;
15076     }
15077 
15078     /* we must initialize XML-provided chain prior to detecting to keep semantics
15079      * with VM startup */
15080     if (blockdev) {
15081         for (n = mirror; virStorageSourceIsBacking(n); n = n->backingStore) {
15082             if (qemuDomainPrepareStorageSourceBlockdev(disk, n, priv, cfg) < 0)
15083                 goto endjob;
15084         }
15085     }
15086 
15087     /* If reusing an external image that includes a backing file but the user
15088      * did not enumerate the chain in the XML we need to detect the chain */
15089     if (mirror_reuse &&
15090         mirror->format >= VIR_STORAGE_FILE_BACKING &&
15091         mirror->backingStore == NULL &&
15092         qemuDomainDetermineDiskChain(driver, vm, disk, mirror, true) < 0)
15093         goto endjob;
15094 
15095     if (qemuDomainStorageSourceChainAccessAllow(driver, vm, mirror) < 0)
15096         goto endjob;
15097     need_revoke = true;
15098 
15099     if (blockdev) {
15100         if (mirror_reuse) {
15101             /* oVirt depended on late-backing-chain-opening semantics the old
15102              * qemu command had to copy the backing chain data while the top
15103              * level is being copied. To restore this semantics if
15104              * blockdev-reopen is supported defer opening of the backing chain
15105              * of 'mirror' to the pivot step */
15106             if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY)) {
15107                 g_autoptr(virStorageSource) terminator = virStorageSourceNew();
15108 
15109                 if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror,
15110                                                                                  terminator)))
15111                     goto endjob;
15112             } else {
15113                 if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror)))
15114                     goto endjob;
15115             }
15116         } else {
15117             if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
15118                 goto endjob;
15119 
15120             if (qemuBlockStorageSourceCreateDetectSize(blockNamedNodeData,
15121                                                        mirror, disk->src))
15122                 goto endjob;
15123 
15124             if (mirror_shallow) {
15125                 /* if external backing store is populated we'll need to open it */
15126                 if (virStorageSourceHasBacking(mirror)) {
15127                     if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror->backingStore)))
15128                         goto endjob;
15129 
15130                     mirrorBacking = mirror->backingStore;
15131                 } else {
15132                     /* backing store of original image will be reused, but the
15133                      * new image must refer to it in the metadata */
15134                     mirrorBacking = disk->src->backingStore;
15135                 }
15136             } else {
15137                 mirrorBacking = mirror->backingStore;
15138             }
15139 
15140             if (!(crdata = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror,
15141                                                                                mirrorBacking)))
15142                 goto endjob;
15143         }
15144 
15145         if (data) {
15146             qemuDomainObjEnterMonitor(driver, vm);
15147             rc = qemuBlockStorageSourceChainAttach(priv->mon, data);
15148             if (qemuDomainObjExitMonitor(driver, vm) < 0)
15149                 goto endjob;
15150 
15151             if (rc < 0)
15152                 goto endjob;
15153         }
15154 
15155         if (crdata &&
15156             qemuBlockStorageSourceCreate(vm, mirror, mirrorBacking, mirror->backingStore,
15157                                          crdata->srcdata[0], QEMU_ASYNC_JOB_NONE) < 0)
15158             goto endjob;
15159     }
15160 
15161     if (!(job = qemuBlockJobDiskNewCopy(vm, disk, mirror, mirror_shallow, mirror_reuse, flags)))
15162         goto endjob;
15163 
15164     disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
15165 
15166     /* Actually start the mirroring */
15167     qemuDomainObjEnterMonitor(driver, vm);
15168 
15169     if (blockdev) {
15170         ret = qemuMonitorBlockdevMirror(priv->mon, job->name, true,
15171                                         qemuDomainDiskGetTopNodename(disk),
15172                                         mirror->nodeformat, bandwidth,
15173                                         granularity, buf_size, mirror_shallow);
15174     } else {
15175         /* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified
15176          * by the user */
15177         ret = qemuMonitorDriveMirror(priv->mon, job->name, mirror->path, format,
15178                                      bandwidth, granularity, buf_size,
15179                                      mirror_shallow, mirror_reuse);
15180     }
15181 
15182     virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
15183     if (qemuDomainObjExitMonitor(driver, vm) < 0)
15184         ret = -1;
15185     if (ret < 0) {
15186         qemuDomainStorageSourceChainAccessRevoke(driver, vm, mirror);
15187         goto endjob;
15188     }
15189 
15190     /* Update vm in place to match changes.  */
15191     need_unlink = false;
15192     virStorageSourceDeinit(mirror);
15193     disk->mirror = g_steal_pointer(&mirror);
15194     disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
15195     qemuBlockJobStarted(job, vm);
15196 
15197  endjob:
15198     if (ret < 0 &&
15199         virDomainObjIsActive(vm)) {
15200         if (data || crdata) {
15201             qemuDomainObjEnterMonitor(driver, vm);
15202             if (data)
15203                 qemuBlockStorageSourceChainDetach(priv->mon, data);
15204             if (crdata)
15205                 qemuBlockStorageSourceAttachRollback(priv->mon, crdata->srcdata[0]);
15206             ignore_value(qemuDomainObjExitMonitor(driver, vm));
15207         }
15208         if (need_revoke)
15209             qemuDomainStorageSourceChainAccessRevoke(driver, vm, mirror);
15210     }
15211     if (need_unlink && virStorageSourceUnlink(mirror) < 0)
15212         VIR_WARN("%s", _("unable to remove just-created copy target"));
15213     virStorageSourceDeinit(mirror);
15214     qemuDomainObjEndJob(driver, vm);
15215     qemuBlockJobStartupFinalize(vm, job);
15216 
15217     return ret;
15218 }
15219 
15220 static int
qemuDomainBlockRebase(virDomainPtr dom,const char * path,const char * base,unsigned long bandwidth,unsigned int flags)15221 qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
15222                       unsigned long bandwidth, unsigned int flags)
15223 {
15224     virDomainObj *vm;
15225     int ret = -1;
15226     unsigned long long speed = bandwidth;
15227     g_autoptr(virStorageSource) dest = NULL;
15228 
15229     virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
15230                   VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
15231                   VIR_DOMAIN_BLOCK_REBASE_COPY |
15232                   VIR_DOMAIN_BLOCK_REBASE_COPY_RAW |
15233                   VIR_DOMAIN_BLOCK_REBASE_RELATIVE |
15234                   VIR_DOMAIN_BLOCK_REBASE_COPY_DEV |
15235                   VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES, -1);
15236 
15237     if (!(vm = qemuDomainObjFromDomain(dom)))
15238         return -1;
15239 
15240     if (virDomainBlockRebaseEnsureACL(dom->conn, vm->def) < 0)
15241         goto cleanup;
15242 
15243     /* For normal rebase (enhanced blockpull), the common code handles
15244      * everything, including vm cleanup. */
15245     if (!(flags & VIR_DOMAIN_BLOCK_REBASE_COPY))
15246         return qemuDomainBlockPullCommon(vm, path, base, bandwidth, flags);
15247 
15248     /* If we got here, we are doing a block copy rebase. */
15249     dest = virStorageSourceNew();
15250     if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV)
15251         dest->type = VIR_STORAGE_TYPE_BLOCK;
15252     else
15253         dest->type = VIR_STORAGE_TYPE_FILE;
15254     dest->path = g_strdup(base);
15255     if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_RAW)
15256         dest->format = VIR_STORAGE_FILE_RAW;
15257 
15258     /* Convert bandwidth MiB to bytes, if necessary */
15259     if (!(flags & VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES)) {
15260         if (speed > LLONG_MAX >> 20) {
15261             virReportError(VIR_ERR_OVERFLOW,
15262                            _("bandwidth must be less than %llu"),
15263                            LLONG_MAX >> 20);
15264             goto cleanup;
15265         }
15266         speed <<= 20;
15267     }
15268 
15269     /* XXX: If we are doing a shallow copy but not reusing an external
15270      * file, we should attempt to pre-create the destination with a
15271      * relative backing chain instead of qemu's default of absolute */
15272     if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
15273         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
15274                        _("Relative backing during copy not supported yet"));
15275         goto cleanup;
15276     }
15277 
15278     /* We rely on the fact that VIR_DOMAIN_BLOCK_REBASE_SHALLOW
15279      * and VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT map to the same values
15280      * as for block copy. */
15281     flags &= (VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
15282               VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT);
15283     ret = qemuDomainBlockCopyCommon(vm, dom->conn, path, dest,
15284                                     speed, 0, 0, flags, true);
15285     dest = NULL;
15286 
15287  cleanup:
15288     virDomainObjEndAPI(&vm);
15289     return ret;
15290 }
15291 
15292 
15293 static int
qemuDomainBlockCopy(virDomainPtr dom,const char * disk,const char * destxml,virTypedParameterPtr params,int nparams,unsigned int flags)15294 qemuDomainBlockCopy(virDomainPtr dom, const char *disk, const char *destxml,
15295                     virTypedParameterPtr params, int nparams,
15296                     unsigned int flags)
15297 {
15298     virQEMUDriver *driver = dom->conn->privateData;
15299     virDomainObj *vm;
15300     int ret = -1;
15301     unsigned long long bandwidth = 0;
15302     unsigned int granularity = 0;
15303     unsigned long long buf_size = 0;
15304     virStorageSource *dest = NULL;
15305     size_t i;
15306 
15307     virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
15308                   VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
15309                   VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB, -1);
15310     if (virTypedParamsValidate(params, nparams,
15311                                VIR_DOMAIN_BLOCK_COPY_BANDWIDTH,
15312                                VIR_TYPED_PARAM_ULLONG,
15313                                VIR_DOMAIN_BLOCK_COPY_GRANULARITY,
15314                                VIR_TYPED_PARAM_UINT,
15315                                VIR_DOMAIN_BLOCK_COPY_BUF_SIZE,
15316                                VIR_TYPED_PARAM_ULLONG,
15317                                NULL) < 0)
15318         return -1;
15319 
15320     if (!(vm = qemuDomainObjFromDomain(dom)))
15321         return -1;
15322 
15323     if (virDomainBlockCopyEnsureACL(dom->conn, vm->def) < 0)
15324         goto cleanup;
15325 
15326     for (i = 0; i < nparams; i++) {
15327         virTypedParameterPtr param = &params[i];
15328 
15329         /* Typed params (wisely) refused to expose unsigned long, but
15330          * back-compat demands that we stick with a maximum of
15331          * unsigned long bandwidth in MiB/s, while our value is
15332          * unsigned long long in bytes/s.  Hence, we have to do
15333          * overflow detection if this is a 32-bit server handling a
15334          * 64-bit client.  */
15335         if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_BANDWIDTH)) {
15336             if (sizeof(unsigned long)< sizeof(bandwidth) &&
15337                 param->value.ul > ULONG_MAX * (1ULL << 20)) {
15338                 virReportError(VIR_ERR_OVERFLOW,
15339                                _("bandwidth must be less than %llu bytes"),
15340                                ULONG_MAX * (1ULL << 20));
15341                 goto cleanup;
15342             }
15343             bandwidth = param->value.ul;
15344         } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_GRANULARITY)) {
15345             if (param->value.ui != VIR_ROUND_UP_POWER_OF_TWO(param->value.ui)) {
15346                 virReportError(VIR_ERR_INVALID_ARG, "%s",
15347                                _("granularity must be power of 2"));
15348                 goto cleanup;
15349             }
15350             granularity = param->value.ui;
15351         } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_BUF_SIZE)) {
15352             buf_size = param->value.ul;
15353         }
15354     }
15355 
15356     if (!(dest = virDomainDiskDefParseSource(destxml, driver->xmlopt,
15357                                              VIR_DOMAIN_DEF_PARSE_INACTIVE)))
15358         goto cleanup;
15359 
15360     ret = qemuDomainBlockCopyCommon(vm, dom->conn, disk, dest, bandwidth,
15361                                     granularity, buf_size, flags, false);
15362 
15363  cleanup:
15364     virDomainObjEndAPI(&vm);
15365     return ret;
15366 }
15367 
15368 
15369 static int
qemuDomainBlockPull(virDomainPtr dom,const char * path,unsigned long bandwidth,unsigned int flags)15370 qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
15371                     unsigned int flags)
15372 {
15373     virDomainObj *vm;
15374     virCheckFlags(VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES, -1);
15375 
15376     if (!(vm = qemuDomainObjFromDomain(dom)))
15377         return -1;
15378 
15379     if (virDomainBlockPullEnsureACL(dom->conn, vm->def) < 0) {
15380         virDomainObjEndAPI(&vm);
15381         return -1;
15382     }
15383 
15384     /* qemuDomainBlockPullCommon consumes the reference on @vm */
15385     return qemuDomainBlockPullCommon(vm, path, NULL, bandwidth, flags);
15386 }
15387 
15388 
15389 static int
qemuDomainBlockCommit(virDomainPtr dom,const char * path,const char * base,const char * top,unsigned long bandwidth,unsigned int flags)15390 qemuDomainBlockCommit(virDomainPtr dom,
15391                       const char *path,
15392                       const char *base,
15393                       const char *top,
15394                       unsigned long bandwidth,
15395                       unsigned int flags)
15396 {
15397     virQEMUDriver *driver = dom->conn->privateData;
15398     qemuDomainObjPrivate *priv;
15399     virDomainObj *vm = NULL;
15400     const char *device = NULL;
15401     const char *jobname = NULL;
15402     int ret = -1;
15403     virDomainDiskDef *disk = NULL;
15404     virStorageSource *topSource;
15405     virStorageSource *baseSource = NULL;
15406     virStorageSource *top_parent = NULL;
15407     bool clean_access = false;
15408     g_autofree char *topPath = NULL;
15409     g_autofree char *basePath = NULL;
15410     g_autofree char *backingPath = NULL;
15411     unsigned long long speed = bandwidth;
15412     qemuBlockJobData *job = NULL;
15413     g_autoptr(virStorageSource) mirror = NULL;
15414     const char *nodetop = NULL;
15415     const char *nodebase = NULL;
15416     bool persistjob = false;
15417     bool blockdev = false;
15418 
15419     virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
15420                   VIR_DOMAIN_BLOCK_COMMIT_ACTIVE |
15421                   VIR_DOMAIN_BLOCK_COMMIT_RELATIVE |
15422                   VIR_DOMAIN_BLOCK_COMMIT_DELETE |
15423                   VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES, -1);
15424 
15425     if (!(vm = qemuDomainObjFromDomain(dom)))
15426         goto cleanup;
15427     priv = vm->privateData;
15428 
15429     if (virDomainBlockCommitEnsureACL(dom->conn, vm->def) < 0)
15430         goto cleanup;
15431 
15432     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
15433         goto cleanup;
15434 
15435     if (virDomainObjCheckActive(vm) < 0)
15436         goto endjob;
15437 
15438     blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
15439 
15440     /* Convert bandwidth MiB to bytes, if necessary */
15441     if (!(flags & VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES)) {
15442         if (speed > LLONG_MAX >> 20) {
15443             virReportError(VIR_ERR_OVERFLOW,
15444                            _("bandwidth must be less than %llu"),
15445                            LLONG_MAX >> 20);
15446             goto endjob;
15447         }
15448         speed <<= 20;
15449     }
15450 
15451     if (!(disk = qemuDomainDiskByName(vm->def, path)))
15452         goto endjob;
15453 
15454     if (!qemuDomainDiskBlockJobIsSupported(vm, disk))
15455         goto endjob;
15456 
15457     if (virStorageSourceIsEmpty(disk->src)) {
15458         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15459                        _("disk %s has no source file to be committed"),
15460                        disk->dst);
15461         goto endjob;
15462     }
15463 
15464     if (qemuDomainDiskBlockJobIsActive(disk))
15465         goto endjob;
15466 
15467     if (qemuDomainSupportsCheckpointsBlockjobs(vm) < 0)
15468         goto endjob;
15469 
15470     if (!blockdev && (flags & VIR_DOMAIN_BLOCK_COMMIT_DELETE)) {
15471         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15472                        _("deleting committed images is not supported by this VM"));
15473         goto endjob;
15474     }
15475 
15476     if (!top || STREQ(top, disk->dst))
15477         topSource = disk->src;
15478     else if (!(topSource = virStorageSourceChainLookup(disk->src, NULL, top,
15479                                                        disk->dst, &top_parent)))
15480         goto endjob;
15481 
15482     if (topSource == disk->src) {
15483         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) {
15484             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15485                            _("active commit not supported with this QEMU binary"));
15486             goto endjob;
15487         }
15488         /* XXX Should we auto-pivot when COMMIT_ACTIVE is not specified? */
15489         if (!(flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE)) {
15490             virReportError(VIR_ERR_INVALID_ARG,
15491                            _("commit of '%s' active layer requires active flag"),
15492                            disk->dst);
15493             goto endjob;
15494         }
15495     } else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
15496         virReportError(VIR_ERR_INVALID_ARG,
15497                        _("active commit requested but '%s' is not active"),
15498                        topSource->path);
15499         goto endjob;
15500     }
15501 
15502     if (!virStorageSourceHasBacking(topSource)) {
15503         virReportError(VIR_ERR_INVALID_ARG,
15504                        _("top '%s' in chain for '%s' has no backing file"),
15505                        topSource->path, path);
15506         goto endjob;
15507     }
15508 
15509     if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW))
15510         baseSource = topSource->backingStore;
15511     else if (!(baseSource = virStorageSourceChainLookup(disk->src, topSource,
15512                                                         base, disk->dst, NULL)))
15513         goto endjob;
15514 
15515     if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) &&
15516         baseSource != topSource->backingStore) {
15517         virReportError(VIR_ERR_INVALID_ARG,
15518                        _("base '%s' is not immediately below '%s' in chain "
15519                          "for '%s'"),
15520                        base, topSource->path, path);
15521         goto endjob;
15522     }
15523 
15524     /* For an active commit, clone enough of the base to act as the mirror */
15525     if (topSource == disk->src) {
15526         if (!(mirror = virStorageSourceCopy(baseSource, false)))
15527             goto endjob;
15528         if (virStorageSourceInitChainElement(mirror,
15529                                              disk->src,
15530                                              true) < 0)
15531             goto endjob;
15532     }
15533 
15534     if (flags & VIR_DOMAIN_BLOCK_COMMIT_RELATIVE &&
15535         topSource != disk->src) {
15536         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
15537             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15538                            _("this qemu doesn't support relative block commit"));
15539             goto endjob;
15540         }
15541 
15542         if (blockdev && top_parent &&
15543             qemuBlockUpdateRelativeBacking(vm, top_parent, disk->src) < 0)
15544             goto endjob;
15545 
15546         if (virStorageSourceGetRelativeBackingPath(topSource, baseSource,
15547                                                    &backingPath) < 0)
15548             goto endjob;
15549 
15550         if (!backingPath) {
15551             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
15552                            _("can't keep relative backing relationship"));
15553             goto endjob;
15554         }
15555     }
15556 
15557     /* For the commit to succeed, we must allow qemu to open both the
15558      * 'base' image and the parent of 'top' as read/write; 'top' might
15559      * not have a parent, or might already be read-write.  XXX It
15560      * would also be nice to revert 'base' to read-only, as well as
15561      * revoke access to files removed from the chain, when the commit
15562      * operation succeeds, but doing that requires tracking the
15563      * operation in XML across libvirtd restarts.  */
15564     clean_access = true;
15565     if (qemuDomainStorageSourceAccessAllow(driver, vm, baseSource,
15566                                            false, false, false) < 0)
15567         goto endjob;
15568 
15569     if (top_parent && top_parent != disk->src) {
15570         /* While top_parent is topmost image, we don't need to remember its
15571          * owner as it will be overwritten upon finishing the commit. Hence,
15572          * pass chainTop = false. */
15573         if (qemuDomainStorageSourceAccessAllow(driver, vm, top_parent,
15574                                                false, false, false) < 0)
15575             goto endjob;
15576     }
15577 
15578     if (!(job = qemuBlockJobDiskNewCommit(vm, disk, top_parent, topSource,
15579                                           baseSource,
15580                                           flags & VIR_DOMAIN_BLOCK_COMMIT_DELETE,
15581                                           flags)))
15582         goto endjob;
15583 
15584     disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
15585 
15586     /* Start the commit operation.  Pass the user's original spelling,
15587      * if any, through to qemu, since qemu may behave differently
15588      * depending on whether the input was specified as relative or
15589      * absolute (that is, our absolute top_canon may do the wrong
15590      * thing if the user specified a relative name).  */
15591 
15592     if (blockdev) {
15593         persistjob = true;
15594         jobname = job->name;
15595         nodetop = topSource->nodeformat;
15596         nodebase = baseSource->nodeformat;
15597         device = qemuDomainDiskGetTopNodename(disk);
15598         if (!backingPath && top_parent &&
15599             !(backingPath = qemuBlockGetBackingStoreString(baseSource, false)))
15600             goto endjob;
15601 
15602     } else {
15603         device = job->name;
15604     }
15605 
15606     qemuDomainObjEnterMonitor(driver, vm);
15607 
15608     if (!blockdev) {
15609         basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
15610                                              baseSource);
15611         topPath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
15612                                             topSource);
15613     }
15614 
15615     if (blockdev || (basePath && topPath))
15616         ret = qemuMonitorBlockCommit(priv->mon, device, jobname, persistjob,
15617                                      topPath, nodetop, basePath, nodebase,
15618                                      backingPath, speed);
15619 
15620     if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) {
15621         ret = -1;
15622         goto endjob;
15623     }
15624 
15625     if (mirror) {
15626         disk->mirror = g_steal_pointer(&mirror);
15627         disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
15628     }
15629     qemuBlockJobStarted(job, vm);
15630 
15631  endjob:
15632     if (ret < 0 && clean_access) {
15633         virErrorPtr orig_err;
15634         virErrorPreserveLast(&orig_err);
15635         /* Revert access to read-only, if possible.  */
15636         qemuDomainStorageSourceAccessAllow(driver, vm, baseSource,
15637                                            true, false, false);
15638         if (top_parent && top_parent != disk->src)
15639             qemuDomainStorageSourceAccessAllow(driver, vm, top_parent,
15640                                                true, false, false);
15641 
15642         virErrorRestore(&orig_err);
15643     }
15644     qemuBlockJobStartupFinalize(vm, job);
15645     qemuDomainObjEndJob(driver, vm);
15646 
15647  cleanup:
15648     virDomainObjEndAPI(&vm);
15649     return ret;
15650 }
15651 
15652 static int
qemuDomainOpenGraphics(virDomainPtr dom,unsigned int idx,int fd,unsigned int flags)15653 qemuDomainOpenGraphics(virDomainPtr dom,
15654                        unsigned int idx,
15655                        int fd,
15656                        unsigned int flags)
15657 {
15658     virQEMUDriver *driver = dom->conn->privateData;
15659     virDomainObj *vm = NULL;
15660     int ret = -1;
15661     qemuDomainObjPrivate *priv;
15662     const char *protocol;
15663 
15664     virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
15665 
15666     if (!(vm = qemuDomainObjFromDomain(dom)))
15667         return -1;
15668 
15669     if (virDomainOpenGraphicsEnsureACL(dom->conn, vm->def) < 0)
15670         goto cleanup;
15671 
15672     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
15673         goto cleanup;
15674 
15675     if (virDomainObjCheckActive(vm) < 0)
15676         goto endjob;
15677 
15678     priv = vm->privateData;
15679 
15680     if (idx >= vm->def->ngraphics) {
15681         virReportError(VIR_ERR_INTERNAL_ERROR,
15682                        _("No graphics backend with index %d"), idx);
15683         goto endjob;
15684     }
15685     switch (vm->def->graphics[idx]->type) {
15686     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
15687         protocol = "vnc";
15688         break;
15689     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
15690         protocol = "spice";
15691         break;
15692     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
15693     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
15694     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
15695     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
15696         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15697                        _("Can only open VNC or SPICE graphics backends, not %s"),
15698                        virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
15699         goto endjob;
15700     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
15701     default:
15702         virReportEnumRangeError(virDomainGraphicsType,
15703                                 vm->def->graphics[idx]->type);
15704         goto endjob;
15705     }
15706 
15707     if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
15708         goto endjob;
15709 
15710     qemuDomainObjEnterMonitor(driver, vm);
15711     ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
15712                                   (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
15713     if (qemuDomainObjExitMonitor(driver, vm) < 0)
15714         ret = -1;
15715 
15716  endjob:
15717     qemuDomainObjEndJob(driver, vm);
15718 
15719  cleanup:
15720     virDomainObjEndAPI(&vm);
15721     return ret;
15722 }
15723 
15724 static int
qemuDomainOpenGraphicsFD(virDomainPtr dom,unsigned int idx,unsigned int flags)15725 qemuDomainOpenGraphicsFD(virDomainPtr dom,
15726                          unsigned int idx,
15727                          unsigned int flags)
15728 {
15729     virQEMUDriver *driver = dom->conn->privateData;
15730     virDomainObj *vm = NULL;
15731     int ret = -1;
15732     qemuDomainObjPrivate *priv;
15733     const char *protocol;
15734     int pair[2] = {-1, -1};
15735 
15736     virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
15737 
15738     if (!(vm = qemuDomainObjFromDomain(dom)))
15739         return -1;
15740 
15741     if (virDomainOpenGraphicsFdEnsureACL(dom->conn, vm->def) < 0)
15742         goto cleanup;
15743 
15744     if (virDomainObjCheckActive(vm) < 0)
15745         goto cleanup;
15746 
15747     priv = vm->privateData;
15748 
15749     if (idx >= vm->def->ngraphics) {
15750         virReportError(VIR_ERR_INTERNAL_ERROR,
15751                        _("No graphics backend with index %d"), idx);
15752         goto cleanup;
15753     }
15754     switch (vm->def->graphics[idx]->type) {
15755     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
15756         protocol = "vnc";
15757         break;
15758     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
15759         protocol = "spice";
15760         break;
15761     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
15762     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
15763     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
15764     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
15765         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15766                        _("Can only open VNC or SPICE graphics backends, not %s"),
15767                        virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
15768         goto cleanup;
15769     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
15770     default:
15771         virReportEnumRangeError(virDomainGraphicsType,
15772                                 vm->def->graphics[idx]->type);
15773         goto cleanup;
15774     }
15775 
15776     if (qemuSecuritySetSocketLabel(driver->securityManager, vm->def) < 0)
15777         goto cleanup;
15778 
15779     if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) < 0)
15780         goto cleanup;
15781 
15782     if (qemuSecurityClearSocketLabel(driver->securityManager, vm->def) < 0)
15783         goto cleanup;
15784 
15785     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
15786         goto cleanup;
15787     qemuDomainObjEnterMonitor(driver, vm);
15788     ret = qemuMonitorOpenGraphics(priv->mon, protocol, pair[1], "graphicsfd",
15789                                   (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH));
15790     if (qemuDomainObjExitMonitor(driver, vm) < 0)
15791         ret = -1;
15792     qemuDomainObjEndJob(driver, vm);
15793     if (ret < 0)
15794         goto cleanup;
15795 
15796     ret = pair[0];
15797     pair[0] = -1;
15798 
15799  cleanup:
15800     VIR_FORCE_CLOSE(pair[0]);
15801     VIR_FORCE_CLOSE(pair[1]);
15802     virDomainObjEndAPI(&vm);
15803     return ret;
15804 }
15805 
15806 typedef enum {
15807     QEMU_BLOCK_IOTUNE_SET_BYTES            = 1 << 0,
15808     QEMU_BLOCK_IOTUNE_SET_IOPS             = 1 << 1,
15809     QEMU_BLOCK_IOTUNE_SET_BYTES_MAX        = 1 << 2,
15810     QEMU_BLOCK_IOTUNE_SET_IOPS_MAX         = 1 << 3,
15811     QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS        = 1 << 4,
15812     QEMU_BLOCK_IOTUNE_SET_GROUP_NAME       = 1 << 5,
15813     QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH = 1 << 6,
15814     QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH  = 1 << 7,
15815 } qemuBlockIoTuneSetFlags;
15816 
15817 
15818 static bool
qemuDomainDiskBlockIoTuneIsSupported(virStorageSource * src)15819 qemuDomainDiskBlockIoTuneIsSupported(virStorageSource *src)
15820 {
15821     if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_VHOST_USER) {
15822         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15823                        _("a block I/O throttling is not supported for vhostuser disk"));
15824         return false;
15825     }
15826 
15827     return true;
15828 }
15829 
15830 
15831 /* If the user didn't specify bytes limits, inherit previous values;
15832  * likewise if the user didn't specify iops limits.  */
15833 static int
qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfo * newinfo,virDomainBlockIoTuneInfo * oldinfo,qemuBlockIoTuneSetFlags set_fields)15834 qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfo *newinfo,
15835                                  virDomainBlockIoTuneInfo *oldinfo,
15836                                  qemuBlockIoTuneSetFlags set_fields)
15837 {
15838 #define SET_IOTUNE_DEFAULTS(BOOL, FIELD) \
15839     if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL)) { \
15840         newinfo->total_##FIELD = oldinfo->total_##FIELD; \
15841         newinfo->read_##FIELD = oldinfo->read_##FIELD; \
15842         newinfo->write_##FIELD = oldinfo->write_##FIELD; \
15843     }
15844 
15845     SET_IOTUNE_DEFAULTS(BYTES, bytes_sec);
15846     SET_IOTUNE_DEFAULTS(BYTES_MAX, bytes_sec_max);
15847     SET_IOTUNE_DEFAULTS(IOPS, iops_sec);
15848     SET_IOTUNE_DEFAULTS(IOPS_MAX, iops_sec_max);
15849 #undef SET_IOTUNE_DEFAULTS
15850 
15851     if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS))
15852         newinfo->size_iops_sec = oldinfo->size_iops_sec;
15853     if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME))
15854         newinfo->group_name = g_strdup(oldinfo->group_name);
15855 
15856     /* The length field is handled a bit differently. If not defined/set,
15857      * QEMU will default these to 0 or 1 depending on whether something in
15858      * the same family is set or not.
15859      *
15860      * Similar to other values, if nothing in the family is defined/set,
15861      * then take whatever is in the oldinfo.
15862      *
15863      * To clear an existing limit, a 0 is provided; however, passing that
15864      * 0 onto QEMU if there's a family value defined/set (or defaulted)
15865      * will cause an error. So, to mimic that, if our oldinfo was set and
15866      * our newinfo is clearing, then set max_length based on whether we
15867      * have a value in the family set/defined. */
15868 #define SET_MAX_LENGTH(BOOL, FIELD) \
15869     if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL)) \
15870         newinfo->FIELD##_max_length = oldinfo->FIELD##_max_length; \
15871     else if ((set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL) && \
15872              oldinfo->FIELD##_max_length && \
15873              !newinfo->FIELD##_max_length) \
15874         newinfo->FIELD##_max_length = (newinfo->FIELD || \
15875                                        newinfo->FIELD##_max) ? 1 : 0;
15876 
15877     SET_MAX_LENGTH(BYTES_MAX_LENGTH, total_bytes_sec);
15878     SET_MAX_LENGTH(BYTES_MAX_LENGTH, read_bytes_sec);
15879     SET_MAX_LENGTH(BYTES_MAX_LENGTH, write_bytes_sec);
15880     SET_MAX_LENGTH(IOPS_MAX_LENGTH, total_iops_sec);
15881     SET_MAX_LENGTH(IOPS_MAX_LENGTH, read_iops_sec);
15882     SET_MAX_LENGTH(IOPS_MAX_LENGTH, write_iops_sec);
15883 
15884 #undef SET_MAX_LENGTH
15885 
15886     return 0;
15887 }
15888 
15889 
15890 static void
qemuDomainSetGroupBlockIoTune(virDomainDef * def,virDomainBlockIoTuneInfo * iotune)15891 qemuDomainSetGroupBlockIoTune(virDomainDef *def,
15892                               virDomainBlockIoTuneInfo *iotune)
15893 {
15894     size_t i;
15895 
15896     if (!iotune->group_name)
15897         return;
15898 
15899     for (i = 0; i < def->ndisks; i++) {
15900         virDomainDiskDef *d = def->disks[i];
15901 
15902         if (STREQ_NULLABLE(d->blkdeviotune.group_name, iotune->group_name)) {
15903             VIR_FREE(d->blkdeviotune.group_name);
15904             virDomainBlockIoTuneInfoCopy(iotune, &d->blkdeviotune);
15905         }
15906     }
15907 }
15908 
15909 
15910 static virDomainBlockIoTuneInfo *
qemuDomainFindGroupBlockIoTune(virDomainDef * def,virDomainDiskDef * disk,virDomainBlockIoTuneInfo * newiotune)15911 qemuDomainFindGroupBlockIoTune(virDomainDef *def,
15912                                virDomainDiskDef *disk,
15913                                virDomainBlockIoTuneInfo *newiotune)
15914 {
15915     size_t i;
15916 
15917     if (!newiotune->group_name ||
15918         STREQ_NULLABLE(disk->blkdeviotune.group_name, newiotune->group_name))
15919         return &disk->blkdeviotune;
15920 
15921     for (i = 0; i < def->ndisks; i++) {
15922         virDomainDiskDef *d = def->disks[i];
15923 
15924         if (STREQ_NULLABLE(newiotune->group_name, d->blkdeviotune.group_name))
15925             return &d->blkdeviotune;
15926     }
15927 
15928     return &disk->blkdeviotune;
15929 }
15930 
15931 
15932 static int
qemuDomainCheckBlockIoTuneReset(virDomainDiskDef * disk,virDomainBlockIoTuneInfo * newiotune)15933 qemuDomainCheckBlockIoTuneReset(virDomainDiskDef *disk,
15934                                 virDomainBlockIoTuneInfo *newiotune)
15935 {
15936     if (virDomainBlockIoTuneInfoHasAny(newiotune))
15937         return 0;
15938 
15939     if (newiotune->group_name &&
15940         STRNEQ_NULLABLE(newiotune->group_name, disk->blkdeviotune.group_name)) {
15941         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15942                        _("creating a new group/updating existing with all"
15943                          " tune parameters zero is not supported"));
15944         return -1;
15945     }
15946 
15947     /* all zero means remove any throttling and remove from group for qemu */
15948     VIR_FREE(newiotune->group_name);
15949 
15950     return 0;
15951 }
15952 
15953 
15954 static int
qemuDomainSetBlockIoTune(virDomainPtr dom,const char * path,virTypedParameterPtr params,int nparams,unsigned int flags)15955 qemuDomainSetBlockIoTune(virDomainPtr dom,
15956                          const char *path,
15957                          virTypedParameterPtr params,
15958                          int nparams,
15959                          unsigned int flags)
15960 {
15961     virQEMUDriver *driver = dom->conn->privateData;
15962     virDomainObj *vm = NULL;
15963     qemuDomainObjPrivate *priv;
15964     virDomainDef *def = NULL;
15965     virDomainDef *persistentDef = NULL;
15966     virDomainBlockIoTuneInfo info;
15967     virDomainBlockIoTuneInfo conf_info;
15968     g_autofree char *drivealias = NULL;
15969     const char *qdevid = NULL;
15970     int ret = -1;
15971     size_t i;
15972     virDomainDiskDef *conf_disk = NULL;
15973     virDomainDiskDef *disk;
15974     qemuBlockIoTuneSetFlags set_fields = 0;
15975     g_autoptr(virQEMUDriverConfig) cfg = NULL;
15976     virObjectEvent *event = NULL;
15977     virTypedParameterPtr eventParams = NULL;
15978     int eventNparams = 0;
15979     int eventMaxparams = 0;
15980     virDomainBlockIoTuneInfo *cur_info;
15981     virDomainBlockIoTuneInfo *conf_cur_info;
15982 
15983 
15984     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
15985                   VIR_DOMAIN_AFFECT_CONFIG, -1);
15986     if (virTypedParamsValidate(params, nparams,
15987                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
15988                                VIR_TYPED_PARAM_ULLONG,
15989                                VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
15990                                VIR_TYPED_PARAM_ULLONG,
15991                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
15992                                VIR_TYPED_PARAM_ULLONG,
15993                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
15994                                VIR_TYPED_PARAM_ULLONG,
15995                                VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
15996                                VIR_TYPED_PARAM_ULLONG,
15997                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
15998                                VIR_TYPED_PARAM_ULLONG,
15999                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
16000                                VIR_TYPED_PARAM_ULLONG,
16001                                VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
16002                                VIR_TYPED_PARAM_ULLONG,
16003                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
16004                                VIR_TYPED_PARAM_ULLONG,
16005                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
16006                                VIR_TYPED_PARAM_ULLONG,
16007                                VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
16008                                VIR_TYPED_PARAM_ULLONG,
16009                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
16010                                VIR_TYPED_PARAM_ULLONG,
16011                                VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
16012                                VIR_TYPED_PARAM_ULLONG,
16013                                VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
16014                                VIR_TYPED_PARAM_STRING,
16015                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
16016                                VIR_TYPED_PARAM_ULLONG,
16017                                VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
16018                                VIR_TYPED_PARAM_ULLONG,
16019                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
16020                                VIR_TYPED_PARAM_ULLONG,
16021                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
16022                                VIR_TYPED_PARAM_ULLONG,
16023                                VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
16024                                VIR_TYPED_PARAM_ULLONG,
16025                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
16026                                VIR_TYPED_PARAM_ULLONG,
16027                                NULL) < 0)
16028         return -1;
16029 
16030     memset(&info, 0, sizeof(info));
16031     memset(&conf_info, 0, sizeof(conf_info));
16032 
16033     if (!(vm = qemuDomainObjFromDomain(dom)))
16034         return -1;
16035 
16036     if (virDomainSetBlockIoTuneEnsureACL(dom->conn, vm->def, flags) < 0)
16037         goto cleanup;
16038 
16039     cfg = virQEMUDriverGetConfig(driver);
16040 
16041     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
16042         goto cleanup;
16043 
16044     priv = vm->privateData;
16045 
16046     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
16047         goto endjob;
16048 
16049     if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
16050                                 VIR_DOMAIN_TUNABLE_BLKDEV_DISK, path) < 0)
16051         goto endjob;
16052 
16053 #define SET_IOTUNE_FIELD(FIELD, BOOL, CONST) \
16054     if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_##CONST)) { \
16055         info.FIELD = param->value.ul; \
16056         set_fields |= QEMU_BLOCK_IOTUNE_SET_##BOOL; \
16057         if (virTypedParamsAddULLong(&eventParams, &eventNparams, \
16058                                     &eventMaxparams, \
16059                                     VIR_DOMAIN_TUNABLE_BLKDEV_##CONST, \
16060                                     param->value.ul) < 0) \
16061             goto endjob; \
16062         continue; \
16063     }
16064 
16065     for (i = 0; i < nparams; i++) {
16066         virTypedParameterPtr param = &params[i];
16067 
16068         if (param->value.ul > QEMU_BLOCK_IOTUNE_MAX) {
16069             virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
16070                            _("block I/O throttle limit value must"
16071                              " be no more than %llu"), QEMU_BLOCK_IOTUNE_MAX);
16072             goto endjob;
16073         }
16074 
16075         SET_IOTUNE_FIELD(total_bytes_sec, BYTES, TOTAL_BYTES_SEC);
16076         SET_IOTUNE_FIELD(read_bytes_sec, BYTES, READ_BYTES_SEC);
16077         SET_IOTUNE_FIELD(write_bytes_sec, BYTES, WRITE_BYTES_SEC);
16078         SET_IOTUNE_FIELD(total_iops_sec, IOPS, TOTAL_IOPS_SEC);
16079         SET_IOTUNE_FIELD(read_iops_sec, IOPS, READ_IOPS_SEC);
16080         SET_IOTUNE_FIELD(write_iops_sec, IOPS, WRITE_IOPS_SEC);
16081 
16082         SET_IOTUNE_FIELD(total_bytes_sec_max, BYTES_MAX,
16083                          TOTAL_BYTES_SEC_MAX);
16084         SET_IOTUNE_FIELD(read_bytes_sec_max, BYTES_MAX,
16085                          READ_BYTES_SEC_MAX);
16086         SET_IOTUNE_FIELD(write_bytes_sec_max, BYTES_MAX,
16087                          WRITE_BYTES_SEC_MAX);
16088         SET_IOTUNE_FIELD(total_iops_sec_max, IOPS_MAX,
16089                          TOTAL_IOPS_SEC_MAX);
16090         SET_IOTUNE_FIELD(read_iops_sec_max, IOPS_MAX,
16091                          READ_IOPS_SEC_MAX);
16092         SET_IOTUNE_FIELD(write_iops_sec_max, IOPS_MAX,
16093                          WRITE_IOPS_SEC_MAX);
16094         SET_IOTUNE_FIELD(size_iops_sec, SIZE_IOPS, SIZE_IOPS_SEC);
16095 
16096         /* NB: Cannot use macro since this is a value.s not a value.ul */
16097         if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
16098             info.group_name = g_strdup(param->value.s);
16099             set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
16100             if (virTypedParamsAddString(&eventParams, &eventNparams,
16101                                         &eventMaxparams,
16102                                         VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
16103                                         param->value.s) < 0)
16104                 goto endjob;
16105             continue;
16106         }
16107 
16108         SET_IOTUNE_FIELD(total_bytes_sec_max_length, BYTES_MAX_LENGTH,
16109                          TOTAL_BYTES_SEC_MAX_LENGTH);
16110         SET_IOTUNE_FIELD(read_bytes_sec_max_length, BYTES_MAX_LENGTH,
16111                          READ_BYTES_SEC_MAX_LENGTH);
16112         SET_IOTUNE_FIELD(write_bytes_sec_max_length, BYTES_MAX_LENGTH,
16113                          WRITE_BYTES_SEC_MAX_LENGTH);
16114         SET_IOTUNE_FIELD(total_iops_sec_max_length, IOPS_MAX_LENGTH,
16115                          TOTAL_IOPS_SEC_MAX_LENGTH);
16116         SET_IOTUNE_FIELD(read_iops_sec_max_length, IOPS_MAX_LENGTH,
16117                          READ_IOPS_SEC_MAX_LENGTH);
16118         SET_IOTUNE_FIELD(write_iops_sec_max_length, IOPS_MAX_LENGTH,
16119                          WRITE_IOPS_SEC_MAX_LENGTH);
16120     }
16121 
16122 #undef SET_IOTUNE_FIELD
16123 
16124     if ((info.total_bytes_sec && info.read_bytes_sec) ||
16125         (info.total_bytes_sec && info.write_bytes_sec)) {
16126         virReportError(VIR_ERR_INVALID_ARG, "%s",
16127                        _("total and read/write of bytes_sec "
16128                          "cannot be set at the same time"));
16129         goto endjob;
16130     }
16131 
16132     if ((info.total_iops_sec && info.read_iops_sec) ||
16133         (info.total_iops_sec && info.write_iops_sec)) {
16134         virReportError(VIR_ERR_INVALID_ARG, "%s",
16135                        _("total and read/write of iops_sec "
16136                          "cannot be set at the same time"));
16137         goto endjob;
16138     }
16139 
16140     if ((info.total_bytes_sec_max && info.read_bytes_sec_max) ||
16141         (info.total_bytes_sec_max && info.write_bytes_sec_max)) {
16142         virReportError(VIR_ERR_INVALID_ARG, "%s",
16143                        _("total and read/write of bytes_sec_max "
16144                          "cannot be set at the same time"));
16145         goto endjob;
16146     }
16147 
16148     if ((info.total_iops_sec_max && info.read_iops_sec_max) ||
16149         (info.total_iops_sec_max && info.write_iops_sec_max)) {
16150         virReportError(VIR_ERR_INVALID_ARG, "%s",
16151                        _("total and read/write of iops_sec_max "
16152                          "cannot be set at the same time"));
16153         goto endjob;
16154     }
16155 
16156     virDomainBlockIoTuneInfoCopy(&info, &conf_info);
16157 
16158     if (def) {
16159         if (!(disk = qemuDomainDiskByName(def, path)))
16160             goto endjob;
16161 
16162         if (!qemuDomainDiskBlockIoTuneIsSupported(disk->src))
16163             goto endjob;
16164 
16165         if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
16166             QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
16167             qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
16168         } else {
16169             if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
16170                 goto endjob;
16171         }
16172 
16173         cur_info = qemuDomainFindGroupBlockIoTune(def, disk, &info);
16174 
16175         if (qemuDomainSetBlockIoTuneDefaults(&info, cur_info,
16176                                              set_fields) < 0)
16177             goto endjob;
16178 
16179         if (qemuDomainCheckBlockIoTuneReset(disk, &info) < 0)
16180             goto endjob;
16181 
16182 #define CHECK_MAX(val, _bool) \
16183         do { \
16184             if (info.val##_max) { \
16185                 if (!info.val) { \
16186                     if (QEMU_BLOCK_IOTUNE_SET_##_bool) { \
16187                         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
16188                                        _("cannot reset '%s' when " \
16189                                          "'%s' is set"), \
16190                                        #val, #val "_max"); \
16191                     } else { \
16192                         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
16193                                        _("value '%s' cannot be set if " \
16194                                          "'%s' is not set"), \
16195                                        #val "_max", #val); \
16196                     } \
16197                     goto endjob; \
16198                 } \
16199                 if (info.val##_max < info.val) { \
16200                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
16201                                    _("value '%s' cannot be " \
16202                                      "smaller than '%s'"), \
16203                                    #val "_max", #val); \
16204                     goto endjob; \
16205                 } \
16206             } \
16207         } while (false)
16208 
16209         CHECK_MAX(total_bytes_sec, BYTES);
16210         CHECK_MAX(read_bytes_sec, BYTES);
16211         CHECK_MAX(write_bytes_sec, BYTES);
16212         CHECK_MAX(total_iops_sec, IOPS);
16213         CHECK_MAX(read_iops_sec, IOPS);
16214         CHECK_MAX(write_iops_sec, IOPS);
16215 
16216 #undef CHECK_MAX
16217 
16218         /* blockdev-based qemu doesn't want to set the throttling when a cdrom
16219          * is empty. Skip the monitor call here since we will set the throttling
16220          * once new media is inserted */
16221         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) ||
16222             !virStorageSourceIsEmpty(disk->src)) {
16223             int rc = 0;
16224 
16225             qemuDomainObjEnterMonitor(driver, vm);
16226             rc = qemuMonitorSetBlockIoThrottle(priv->mon, drivealias, qdevid, &info);
16227 
16228             if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
16229                 goto endjob;
16230         }
16231 
16232         virDomainDiskSetBlockIOTune(disk, &info);
16233 
16234         qemuDomainSetGroupBlockIoTune(def, &info);
16235 
16236         qemuDomainSaveStatus(vm);
16237 
16238         if (eventNparams) {
16239             event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
16240             eventNparams = 0;
16241             virObjectEventStateQueue(driver->domainEventState, event);
16242         }
16243     }
16244 
16245     if (persistentDef) {
16246         if (!(conf_disk = virDomainDiskByName(persistentDef, path, true))) {
16247             virReportError(VIR_ERR_INVALID_ARG,
16248                            _("missing persistent configuration for disk '%s'"),
16249                            path);
16250             goto endjob;
16251         }
16252 
16253         if (!qemuDomainDiskBlockIoTuneIsSupported(conf_disk->src))
16254             goto endjob;
16255 
16256         conf_cur_info = qemuDomainFindGroupBlockIoTune(persistentDef, conf_disk, &info);
16257 
16258         if (qemuDomainSetBlockIoTuneDefaults(&conf_info, conf_cur_info,
16259                                              set_fields) < 0)
16260             goto endjob;
16261 
16262         if (qemuDomainCheckBlockIoTuneReset(conf_disk, &conf_info) < 0)
16263             goto endjob;
16264 
16265         virDomainDiskSetBlockIOTune(conf_disk, &conf_info);
16266 
16267         qemuDomainSetGroupBlockIoTune(persistentDef, &conf_info);
16268 
16269         if (virDomainDefSave(persistentDef, driver->xmlopt,
16270                              cfg->configDir) < 0)
16271             goto endjob;
16272     }
16273 
16274     ret = 0;
16275  endjob:
16276     qemuDomainObjEndJob(driver, vm);
16277 
16278  cleanup:
16279     VIR_FREE(info.group_name);
16280     VIR_FREE(conf_info.group_name);
16281     virDomainObjEndAPI(&vm);
16282     if (eventNparams)
16283         virTypedParamsFree(eventParams, eventNparams);
16284     return ret;
16285 }
16286 
16287 static int
qemuDomainGetBlockIoTune(virDomainPtr dom,const char * path,virTypedParameterPtr params,int * nparams,unsigned int flags)16288 qemuDomainGetBlockIoTune(virDomainPtr dom,
16289                          const char *path,
16290                          virTypedParameterPtr params,
16291                          int *nparams,
16292                          unsigned int flags)
16293 {
16294     virDomainDiskDef *disk;
16295     virQEMUDriver *driver = dom->conn->privateData;
16296     virDomainObj *vm = NULL;
16297     qemuDomainObjPrivate *priv = NULL;
16298     virDomainDef *def = NULL;
16299     virDomainDef *persistentDef = NULL;
16300     virDomainBlockIoTuneInfo reply = {0};
16301     g_autofree char *drivealias = NULL;
16302     const char *qdevid = NULL;
16303     int ret = -1;
16304     int maxparams;
16305 
16306     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
16307                   VIR_DOMAIN_AFFECT_CONFIG |
16308                   VIR_TYPED_PARAM_STRING_OKAY, -1);
16309 
16310     /* We don't return strings, and thus trivially support this flag.  */
16311     flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
16312 
16313     if (!(vm = qemuDomainObjFromDomain(dom)))
16314         return -1;
16315 
16316     priv = vm->privateData;
16317 
16318     if (virDomainGetBlockIoTuneEnsureACL(dom->conn, vm->def) < 0)
16319         goto cleanup;
16320 
16321     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
16322         goto cleanup;
16323 
16324     /* the API check guarantees that only one of the definitions will be set */
16325     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
16326         goto endjob;
16327 
16328     maxparams = QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS;
16329 
16330     if (*nparams == 0) {
16331         *nparams = maxparams;
16332         ret = 0;
16333         goto endjob;
16334     }
16335     if (*nparams < maxparams)
16336         maxparams = *nparams;
16337 
16338     *nparams = 0;
16339 
16340     if (def) {
16341         int rc = 0;
16342 
16343         if (!(disk = qemuDomainDiskByName(def, path)))
16344             goto endjob;
16345 
16346         if (!qemuDomainDiskBlockIoTuneIsSupported(disk->src))
16347             goto endjob;
16348 
16349         if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
16350             QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
16351             qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
16352         } else {
16353             if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
16354                 goto endjob;
16355         }
16356         qemuDomainObjEnterMonitor(driver, vm);
16357         rc = qemuMonitorGetBlockIoThrottle(priv->mon, drivealias, qdevid, &reply);
16358 
16359         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
16360             goto endjob;
16361     }
16362 
16363     if (persistentDef) {
16364         if (!(disk = virDomainDiskByName(persistentDef, path, true))) {
16365             virReportError(VIR_ERR_INVALID_ARG,
16366                            _("disk '%s' was not found in the domain config"),
16367                            path);
16368             goto endjob;
16369         }
16370 
16371         if (!qemuDomainDiskBlockIoTuneIsSupported(disk->src))
16372             goto endjob;
16373 
16374         reply = disk->blkdeviotune;
16375 
16376         /* Group name needs to be copied since qemuMonitorGetBlockIoThrottle
16377          * allocates it as well */
16378         reply.group_name = g_strdup(disk->blkdeviotune.group_name);
16379     }
16380 
16381 #define BLOCK_IOTUNE_ASSIGN(name, var) \
16382     if (*nparams < maxparams && \
16383         virTypedParameterAssign(&params[(*nparams)++], \
16384                                 VIR_DOMAIN_BLOCK_IOTUNE_ ## name, \
16385                                 VIR_TYPED_PARAM_ULLONG, \
16386                                 reply.var) < 0) \
16387         goto endjob
16388 
16389 
16390     BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC, total_bytes_sec);
16391     BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC, read_bytes_sec);
16392     BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC, write_bytes_sec);
16393 
16394     BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC, total_iops_sec);
16395     BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC, read_iops_sec);
16396     BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC, write_iops_sec);
16397 
16398     BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX, total_bytes_sec_max);
16399     BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX, read_bytes_sec_max);
16400     BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX, write_bytes_sec_max);
16401 
16402     BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX, total_iops_sec_max);
16403     BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX, read_iops_sec_max);
16404     BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX, write_iops_sec_max);
16405 
16406     BLOCK_IOTUNE_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
16407 
16408     if (*nparams < maxparams) {
16409         if (virTypedParameterAssign(&params[(*nparams)++],
16410                                     VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
16411                                     VIR_TYPED_PARAM_STRING,
16412                                     reply.group_name) < 0)
16413             goto endjob;
16414 
16415         reply.group_name = NULL;
16416     }
16417 
16418     BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_length);
16419     BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_length);
16420     BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_length);
16421 
16422     BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_length);
16423     BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_length);
16424     BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_length);
16425 #undef BLOCK_IOTUNE_ASSIGN
16426 
16427     ret = 0;
16428 
16429  endjob:
16430     qemuDomainObjEndJob(driver, vm);
16431 
16432  cleanup:
16433     VIR_FREE(reply.group_name);
16434     virDomainObjEndAPI(&vm);
16435     return ret;
16436 }
16437 
16438 static int
qemuDomainGetDiskErrors(virDomainPtr dom,virDomainDiskErrorPtr errors,unsigned int nerrors,unsigned int flags)16439 qemuDomainGetDiskErrors(virDomainPtr dom,
16440                         virDomainDiskErrorPtr errors,
16441                         unsigned int nerrors,
16442                         unsigned int flags)
16443 {
16444     virQEMUDriver *driver = dom->conn->privateData;
16445     virDomainObj *vm = NULL;
16446     qemuDomainObjPrivate *priv;
16447     GHashTable *table = NULL;
16448     bool blockdev = false;
16449     int ret = -1;
16450     size_t i;
16451     int n = 0;
16452 
16453     virCheckFlags(0, -1);
16454 
16455     if (!(vm = qemuDomainObjFromDomain(dom)))
16456         goto cleanup;
16457 
16458     priv = vm->privateData;
16459     blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
16460 
16461     if (virDomainGetDiskErrorsEnsureACL(dom->conn, vm->def) < 0)
16462         goto cleanup;
16463 
16464     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
16465         goto cleanup;
16466 
16467     if (virDomainObjCheckActive(vm) < 0)
16468         goto endjob;
16469 
16470     if (!errors) {
16471         ret = vm->def->ndisks;
16472         goto endjob;
16473     }
16474 
16475     qemuDomainObjEnterMonitor(driver, vm);
16476     table = qemuMonitorGetBlockInfo(priv->mon);
16477     if (qemuDomainObjExitMonitor(driver, vm) < 0)
16478         goto endjob;
16479     if (!table)
16480         goto endjob;
16481 
16482     for (i = n = 0; i < vm->def->ndisks; i++) {
16483         struct qemuDomainDiskInfo *info;
16484         virDomainDiskDef *disk = vm->def->disks[i];
16485         qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
16486         const char *entryname = disk->info.alias;
16487 
16488         if (blockdev && diskPriv->qomName)
16489             entryname = diskPriv->qomName;
16490 
16491         if ((info = virHashLookup(table, entryname)) &&
16492             info->io_status != VIR_DOMAIN_DISK_ERROR_NONE) {
16493             if (n == nerrors)
16494                 break;
16495 
16496             errors[n].disk = g_strdup(disk->dst);
16497             errors[n].error = info->io_status;
16498             n++;
16499         }
16500     }
16501 
16502     ret = n;
16503 
16504  endjob:
16505     qemuDomainObjEndJob(driver, vm);
16506 
16507  cleanup:
16508     virDomainObjEndAPI(&vm);
16509     virHashFree(table);
16510     if (ret < 0) {
16511         for (i = 0; i < n; i++)
16512             VIR_FREE(errors[i].disk);
16513     }
16514     return ret;
16515 }
16516 
16517 static int
qemuDomainSetMetadata(virDomainPtr dom,int type,const char * metadata,const char * key,const char * uri,unsigned int flags)16518 qemuDomainSetMetadata(virDomainPtr dom,
16519                       int type,
16520                       const char *metadata,
16521                       const char *key,
16522                       const char *uri,
16523                       unsigned int flags)
16524 {
16525     virQEMUDriver *driver = dom->conn->privateData;
16526     virDomainObj *vm;
16527     g_autoptr(virQEMUDriverConfig) cfg = NULL;
16528     int ret = -1;
16529 
16530     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
16531                   VIR_DOMAIN_AFFECT_CONFIG, -1);
16532 
16533     if (!(vm = qemuDomainObjFromDomain(dom)))
16534         return -1;
16535 
16536     cfg = virQEMUDriverGetConfig(driver);
16537 
16538     if (virDomainSetMetadataEnsureACL(dom->conn, vm->def, flags) < 0)
16539         goto cleanup;
16540 
16541     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
16542         goto cleanup;
16543 
16544     ret = virDomainObjSetMetadata(vm, type, metadata, key, uri,
16545                                   driver->xmlopt, cfg->stateDir,
16546                                   cfg->configDir, flags);
16547 
16548     if (ret == 0) {
16549         virObjectEvent *ev = NULL;
16550         ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
16551         virObjectEventStateQueue(driver->domainEventState, ev);
16552     }
16553 
16554     qemuDomainObjEndJob(driver, vm);
16555 
16556  cleanup:
16557     virDomainObjEndAPI(&vm);
16558     return ret;
16559 }
16560 
16561 static char *
qemuDomainGetMetadata(virDomainPtr dom,int type,const char * uri,unsigned int flags)16562 qemuDomainGetMetadata(virDomainPtr dom,
16563                       int type,
16564                       const char *uri,
16565                       unsigned int flags)
16566 {
16567     virDomainObj *vm;
16568     char *ret = NULL;
16569 
16570     if (!(vm = qemuDomainObjFromDomain(dom)))
16571         return NULL;
16572 
16573     if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0)
16574         goto cleanup;
16575 
16576     ret = virDomainObjGetMetadata(vm, type, uri, flags);
16577 
16578  cleanup:
16579     virDomainObjEndAPI(&vm);
16580     return ret;
16581 }
16582 
16583 
16584 static int
qemuDomainGetCPUStats(virDomainPtr domain,virTypedParameterPtr params,unsigned int nparams,int start_cpu,unsigned int ncpus,unsigned int flags)16585 qemuDomainGetCPUStats(virDomainPtr domain,
16586                       virTypedParameterPtr params,
16587                       unsigned int nparams,
16588                       int start_cpu,
16589                       unsigned int ncpus,
16590                       unsigned int flags)
16591 {
16592     virDomainObj *vm = NULL;
16593     int ret = -1;
16594     qemuDomainObjPrivate *priv;
16595     virBitmap *guestvcpus = NULL;
16596 
16597     virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
16598 
16599     if (!(vm = qemuDomainObjFromDomain(domain)))
16600         return -1;
16601 
16602     priv = vm->privateData;
16603 
16604     if (virDomainGetCPUStatsEnsureACL(domain->conn, vm->def) < 0)
16605         goto cleanup;
16606 
16607     if (virDomainObjCheckActive(vm) < 0)
16608         goto cleanup;
16609 
16610     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) {
16611         virReportError(VIR_ERR_OPERATION_INVALID,
16612                        "%s", _("cgroup CPUACCT controller is not mounted"));
16613         goto cleanup;
16614     }
16615 
16616     if (qemuDomainHasVcpuPids(vm) &&
16617         !(guestvcpus = virDomainDefGetOnlineVcpumap(vm->def)))
16618         goto cleanup;
16619 
16620     if (start_cpu == -1)
16621         ret = virCgroupGetDomainTotalCpuStats(priv->cgroup,
16622                                               params, nparams);
16623     else
16624         ret = virCgroupGetPercpuStats(priv->cgroup, params, nparams,
16625                                       start_cpu, ncpus, guestvcpus);
16626  cleanup:
16627     virBitmapFree(guestvcpus);
16628     virDomainObjEndAPI(&vm);
16629     return ret;
16630 }
16631 
16632 
16633 static int
qemuDomainProbeQMPCurrentMachine(virQEMUDriver * driver,virDomainObj * vm,bool * wakeupSupported)16634 qemuDomainProbeQMPCurrentMachine(virQEMUDriver *driver,
16635                                  virDomainObj *vm,
16636                                  bool *wakeupSupported)
16637 {
16638     qemuDomainObjPrivate *priv = vm->privateData;
16639     qemuMonitorCurrentMachineInfo info = { 0 };
16640     int rv;
16641 
16642     qemuDomainObjEnterMonitor(driver, vm);
16643     rv = qemuMonitorGetCurrentMachineInfo(priv->mon, &info);
16644     if (qemuDomainObjExitMonitor(driver, vm) < 0 ||
16645         rv < 0)
16646         return -1;
16647 
16648     *wakeupSupported = info.wakeupSuspendSupport;
16649     return 0;
16650 }
16651 
16652 
16653 /* returns -1 on error, or if query is not supported, 0 if query was successful */
16654 static int
qemuDomainQueryWakeupSuspendSupport(virQEMUDriver * driver,virDomainObj * vm,bool * wakeupSupported)16655 qemuDomainQueryWakeupSuspendSupport(virQEMUDriver *driver,
16656                                     virDomainObj *vm,
16657                                     bool *wakeupSupported)
16658 {
16659     qemuDomainObjPrivate *priv = vm->privateData;
16660     int ret = -1;
16661 
16662     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CURRENT_MACHINE))
16663         return -1;
16664 
16665     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
16666         return -1;
16667 
16668     if ((ret = virDomainObjCheckActive(vm)) < 0)
16669         goto endjob;
16670 
16671     ret = qemuDomainProbeQMPCurrentMachine(driver, vm, wakeupSupported);
16672 
16673  endjob:
16674     qemuDomainObjEndJob(driver, vm);
16675     return ret;
16676 }
16677 
16678 
16679 static int
qemuDomainPMSuspendAgent(virQEMUDriver * driver,virDomainObj * vm,unsigned int target)16680 qemuDomainPMSuspendAgent(virQEMUDriver *driver,
16681                          virDomainObj *vm,
16682                          unsigned int target)
16683 {
16684     qemuAgent *agent;
16685     int ret = -1;
16686 
16687     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
16688         return -1;
16689 
16690     if (virDomainObjCheckActive(vm) < 0)
16691         goto endjob;
16692 
16693     if (!qemuDomainAgentAvailable(vm, true))
16694         goto endjob;
16695 
16696     agent = qemuDomainObjEnterAgent(vm);
16697     ret = qemuAgentSuspend(agent, target);
16698     qemuDomainObjExitAgent(vm, agent);
16699 
16700  endjob:
16701     qemuDomainObjEndAgentJob(vm);
16702     return ret;
16703 }
16704 
16705 
16706 static int
qemuDomainPMSuspendForDuration(virDomainPtr dom,unsigned int target,unsigned long long duration,unsigned int flags)16707 qemuDomainPMSuspendForDuration(virDomainPtr dom,
16708                                unsigned int target,
16709                                unsigned long long duration,
16710                                unsigned int flags)
16711 {
16712     virQEMUDriver *driver = dom->conn->privateData;
16713     virDomainObj *vm;
16714     int ret = -1;
16715     bool wakeupSupported;
16716 
16717     virCheckFlags(0, -1);
16718 
16719     if (duration) {
16720         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
16721                        _("Duration not supported. Use 0 for now"));
16722         return -1;
16723     }
16724 
16725     if (!(target == VIR_NODE_SUSPEND_TARGET_MEM ||
16726           target == VIR_NODE_SUSPEND_TARGET_DISK ||
16727           target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
16728         virReportError(VIR_ERR_INVALID_ARG,
16729                        _("Unknown suspend target: %u"),
16730                        target);
16731         return -1;
16732     }
16733 
16734     if (!(vm = qemuDomainObjFromDomain(dom)))
16735         goto cleanup;
16736 
16737     if (virDomainPMSuspendForDurationEnsureACL(dom->conn, vm->def) < 0)
16738         goto cleanup;
16739 
16740     if (!qemuDomainAgentAvailable(vm, true))
16741         goto cleanup;
16742 
16743     /*
16744      * The case we want to handle here is when QEMU has the API (i.e.
16745      * QEMU_CAPS_QUERY_CURRENT_MACHINE is set). Otherwise, do not interfere
16746      * with the suspend process. This means that existing running domains,
16747      * that don't know about this cap, will keep their old behavior of
16748      * suspending 'in the dark'.
16749      */
16750     if (qemuDomainQueryWakeupSuspendSupport(driver, vm, &wakeupSupported) == 0) {
16751         if (!wakeupSupported) {
16752             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
16753                            _("Domain does not have suspend support"));
16754             goto cleanup;
16755         }
16756     }
16757 
16758     if (vm->def->pm.s3 || vm->def->pm.s4) {
16759         if (vm->def->pm.s3 == VIR_TRISTATE_BOOL_NO &&
16760             (target == VIR_NODE_SUSPEND_TARGET_MEM ||
16761              target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
16762             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
16763                            _("S3 state is disabled for this domain"));
16764             goto cleanup;
16765         }
16766 
16767         if (vm->def->pm.s4 == VIR_TRISTATE_BOOL_NO &&
16768             target == VIR_NODE_SUSPEND_TARGET_DISK) {
16769             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
16770                            _("S4 state is disabled for this domain"));
16771             goto cleanup;
16772         }
16773     }
16774 
16775     ret = qemuDomainPMSuspendAgent(driver, vm, target);
16776 
16777  cleanup:
16778     virDomainObjEndAPI(&vm);
16779     return ret;
16780 }
16781 
16782 static int
qemuDomainPMWakeup(virDomainPtr dom,unsigned int flags)16783 qemuDomainPMWakeup(virDomainPtr dom,
16784                    unsigned int flags)
16785 {
16786     virQEMUDriver *driver = dom->conn->privateData;
16787     virDomainObj *vm;
16788     int ret = -1;
16789     qemuDomainObjPrivate *priv;
16790 
16791     virCheckFlags(0, -1);
16792 
16793     if (!(vm = qemuDomainObjFromDomain(dom)))
16794         goto cleanup;
16795 
16796     if (virDomainPMWakeupEnsureACL(dom->conn, vm->def) < 0)
16797         goto cleanup;
16798 
16799     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
16800         goto cleanup;
16801 
16802     if (virDomainObjCheckActive(vm) < 0)
16803         goto endjob;
16804 
16805     priv = vm->privateData;
16806 
16807     qemuDomainObjEnterMonitor(driver, vm);
16808     ret = qemuMonitorSystemWakeup(priv->mon);
16809     if (qemuDomainObjExitMonitor(driver, vm) < 0)
16810         ret = -1;
16811 
16812  endjob:
16813     qemuDomainObjEndJob(driver, vm);
16814 
16815  cleanup:
16816     virDomainObjEndAPI(&vm);
16817     return ret;
16818 }
16819 
16820 static int
qemuConnectListAllDomains(virConnectPtr conn,virDomainPtr ** domains,unsigned int flags)16821 qemuConnectListAllDomains(virConnectPtr conn,
16822                           virDomainPtr **domains,
16823                           unsigned int flags)
16824 {
16825     virQEMUDriver *driver = conn->privateData;
16826 
16827     virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
16828 
16829     if (virConnectListAllDomainsEnsureACL(conn) < 0)
16830         return -1;
16831 
16832     return virDomainObjListExport(driver->domains, conn, domains,
16833                                   virConnectListAllDomainsCheckACL, flags);
16834 }
16835 
16836 static char *
qemuDomainQemuAgentCommand(virDomainPtr domain,const char * cmd,int timeout,unsigned int flags)16837 qemuDomainQemuAgentCommand(virDomainPtr domain,
16838                            const char *cmd,
16839                            int timeout,
16840                            unsigned int flags)
16841 {
16842     virQEMUDriver *driver = domain->conn->privateData;
16843     virDomainObj *vm;
16844     int ret = -1;
16845     char *result = NULL;
16846     qemuAgent *agent;
16847 
16848     virCheckFlags(0, NULL);
16849 
16850     if (!(vm = qemuDomainObjFromDomain(domain)))
16851         goto cleanup;
16852 
16853     if (virDomainQemuAgentCommandEnsureACL(domain->conn, vm->def) < 0)
16854         goto cleanup;
16855 
16856     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
16857         goto cleanup;
16858 
16859     if (virDomainObjCheckActive(vm) < 0)
16860         goto endjob;
16861 
16862     if (!qemuDomainAgentAvailable(vm, true))
16863         goto endjob;
16864 
16865     qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_GA_COMMAND, NULL);
16866 
16867     agent = qemuDomainObjEnterAgent(vm);
16868     ret = qemuAgentArbitraryCommand(agent, cmd, &result, timeout);
16869     qemuDomainObjExitAgent(vm, agent);
16870     if (ret < 0)
16871         VIR_FREE(result);
16872 
16873  endjob:
16874     qemuDomainObjEndAgentJob(vm);
16875 
16876  cleanup:
16877     virDomainObjEndAPI(&vm);
16878     return result;
16879 }
16880 
16881 
16882 static int
qemuConnectDomainQemuMonitorEventRegister(virConnectPtr conn,virDomainPtr dom,const char * event,virConnectDomainQemuMonitorEventCallback callback,void * opaque,virFreeCallback freecb,unsigned int flags)16883 qemuConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
16884                                           virDomainPtr dom,
16885                                           const char *event,
16886                                           virConnectDomainQemuMonitorEventCallback callback,
16887                                           void *opaque,
16888                                           virFreeCallback freecb,
16889                                           unsigned int flags)
16890 {
16891     virQEMUDriver *driver = conn->privateData;
16892     int ret = -1;
16893 
16894     if (virConnectDomainQemuMonitorEventRegisterEnsureACL(conn) < 0)
16895         return -1;
16896 
16897     if (virDomainQemuMonitorEventStateRegisterID(conn,
16898                                                  driver->domainEventState,
16899                                                  dom, event, callback,
16900                                                  opaque, freecb, flags,
16901                                                  &ret) < 0)
16902         ret = -1;
16903 
16904     return ret;
16905 }
16906 
16907 
16908 static int
qemuConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,int callbackID)16909 qemuConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
16910                                             int callbackID)
16911 {
16912     virQEMUDriver *driver = conn->privateData;
16913 
16914     if (virConnectDomainQemuMonitorEventDeregisterEnsureACL(conn) < 0)
16915         return -1;
16916 
16917     if (virObjectEventStateDeregisterID(conn, driver->domainEventState,
16918                                         callbackID, true) < 0)
16919         return -1;
16920 
16921     return 0;
16922 }
16923 
16924 
16925 static int
qemuDomainFSTrim(virDomainPtr dom,const char * mountPoint,unsigned long long minimum,unsigned int flags)16926 qemuDomainFSTrim(virDomainPtr dom,
16927                  const char *mountPoint,
16928                  unsigned long long minimum,
16929                  unsigned int flags)
16930 {
16931     virQEMUDriver *driver = dom->conn->privateData;
16932     virDomainObj *vm;
16933     qemuAgent *agent;
16934     int ret = -1;
16935 
16936     virCheckFlags(0, -1);
16937 
16938     if (mountPoint) {
16939         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
16940                        _("Specifying mount point "
16941                          "is not supported for now"));
16942         return -1;
16943     }
16944 
16945     if (!(vm = qemuDomainObjFromDomain(dom)))
16946         goto cleanup;
16947 
16948     if (virDomainFSTrimEnsureACL(dom->conn, vm->def) < 0)
16949         goto cleanup;
16950 
16951     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
16952         goto cleanup;
16953 
16954     if (!qemuDomainAgentAvailable(vm, true))
16955         goto endjob;
16956 
16957     if (virDomainObjCheckActive(vm) < 0)
16958         goto endjob;
16959 
16960     agent = qemuDomainObjEnterAgent(vm);
16961     ret = qemuAgentFSTrim(agent, minimum);
16962     qemuDomainObjExitAgent(vm, agent);
16963 
16964  endjob:
16965     qemuDomainObjEndAgentJob(vm);
16966 
16967  cleanup:
16968     virDomainObjEndAPI(&vm);
16969     return ret;
16970 }
16971 
16972 
16973 static int
qemuNodeGetInfo(virConnectPtr conn,virNodeInfoPtr nodeinfo)16974 qemuNodeGetInfo(virConnectPtr conn,
16975                 virNodeInfoPtr nodeinfo)
16976 {
16977     if (virNodeGetInfoEnsureACL(conn) < 0)
16978         return -1;
16979 
16980     return virCapabilitiesGetNodeInfo(nodeinfo);
16981 }
16982 
16983 
16984 static int
qemuNodeGetCPUStats(virConnectPtr conn,int cpuNum,virNodeCPUStatsPtr params,int * nparams,unsigned int flags)16985 qemuNodeGetCPUStats(virConnectPtr conn,
16986                     int cpuNum,
16987                     virNodeCPUStatsPtr params,
16988                     int *nparams,
16989                     unsigned int flags)
16990 {
16991     if (virNodeGetCPUStatsEnsureACL(conn) < 0)
16992         return -1;
16993 
16994     return virHostCPUGetStats(cpuNum, params, nparams, flags);
16995 }
16996 
16997 
16998 static int
qemuNodeGetMemoryStats(virConnectPtr conn,int cellNum,virNodeMemoryStatsPtr params,int * nparams,unsigned int flags)16999 qemuNodeGetMemoryStats(virConnectPtr conn,
17000                        int cellNum,
17001                        virNodeMemoryStatsPtr params,
17002                        int *nparams,
17003                        unsigned int flags)
17004 {
17005     if (virNodeGetMemoryStatsEnsureACL(conn) < 0)
17006         return -1;
17007 
17008     return virHostMemGetStats(cellNum, params, nparams, flags);
17009 }
17010 
17011 
17012 static int
qemuNodeGetCellsFreeMemory(virConnectPtr conn,unsigned long long * freeMems,int startCell,int maxCells)17013 qemuNodeGetCellsFreeMemory(virConnectPtr conn,
17014                            unsigned long long *freeMems,
17015                            int startCell,
17016                            int maxCells)
17017 {
17018     if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
17019         return -1;
17020 
17021     return virHostMemGetCellsFree(freeMems, startCell, maxCells);
17022 }
17023 
17024 
17025 static unsigned long long
qemuNodeGetFreeMemory(virConnectPtr conn)17026 qemuNodeGetFreeMemory(virConnectPtr conn)
17027 {
17028     unsigned long long freeMem;
17029 
17030     if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
17031         return 0;
17032 
17033     if (virHostMemGetInfo(NULL, &freeMem) < 0)
17034         return 0;
17035 
17036     return freeMem;
17037 }
17038 
17039 
17040 static int
qemuNodeGetMemoryParameters(virConnectPtr conn,virTypedParameterPtr params,int * nparams,unsigned int flags)17041 qemuNodeGetMemoryParameters(virConnectPtr conn,
17042                             virTypedParameterPtr params,
17043                             int *nparams,
17044                             unsigned int flags)
17045 {
17046     if (virNodeGetMemoryParametersEnsureACL(conn) < 0)
17047         return -1;
17048 
17049     return virHostMemGetParameters(params, nparams, flags);
17050 }
17051 
17052 
17053 static int
qemuNodeSetMemoryParameters(virConnectPtr conn,virTypedParameterPtr params,int nparams,unsigned int flags)17054 qemuNodeSetMemoryParameters(virConnectPtr conn,
17055                             virTypedParameterPtr params,
17056                             int nparams,
17057                             unsigned int flags)
17058 {
17059     if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
17060         return -1;
17061 
17062     return virHostMemSetParameters(params, nparams, flags);
17063 }
17064 
17065 
17066 static int
qemuNodeGetCPUMap(virConnectPtr conn,unsigned char ** cpumap,unsigned int * online,unsigned int flags)17067 qemuNodeGetCPUMap(virConnectPtr conn,
17068                   unsigned char **cpumap,
17069                   unsigned int *online,
17070                   unsigned int flags)
17071 {
17072     if (virNodeGetCPUMapEnsureACL(conn) < 0)
17073         return -1;
17074 
17075     return virHostCPUGetMap(cpumap, online, flags);
17076 }
17077 
17078 
17079 static int
qemuNodeSuspendForDuration(virConnectPtr conn,unsigned int target,unsigned long long duration,unsigned int flags)17080 qemuNodeSuspendForDuration(virConnectPtr conn,
17081                            unsigned int target,
17082                            unsigned long long duration,
17083                            unsigned int flags)
17084 {
17085     if (virNodeSuspendForDurationEnsureACL(conn) < 0)
17086         return -1;
17087 
17088     return virNodeSuspend(target, duration, flags);
17089 }
17090 
17091 static int
qemuConnectGetCPUModelNames(virConnectPtr conn,const char * archName,char *** models,unsigned int flags)17092 qemuConnectGetCPUModelNames(virConnectPtr conn,
17093                             const char *archName,
17094                             char ***models,
17095                             unsigned int flags)
17096 {
17097     virArch arch;
17098 
17099     virCheckFlags(0, -1);
17100     if (virConnectGetCPUModelNamesEnsureACL(conn) < 0)
17101         return -1;
17102 
17103     if (!(arch = virArchFromString(archName))) {
17104         virReportError(VIR_ERR_INVALID_ARG,
17105                        _("cannot find architecture %s"),
17106                        archName);
17107         return -1;
17108     }
17109 
17110     return virCPUGetModels(arch, models);
17111 }
17112 
17113 
17114 static int
qemuDomainGetHostnameAgent(virQEMUDriver * driver,virDomainObj * vm,char ** hostname)17115 qemuDomainGetHostnameAgent(virQEMUDriver *driver,
17116                            virDomainObj *vm,
17117                            char **hostname)
17118 {
17119     qemuAgent *agent;
17120     int ret = -1;
17121 
17122     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
17123         return -1;
17124 
17125     if (virDomainObjCheckActive(vm) < 0)
17126         goto endjob;
17127 
17128     if (!qemuDomainAgentAvailable(vm, true))
17129         goto endjob;
17130 
17131     agent = qemuDomainObjEnterAgent(vm);
17132     ignore_value(qemuAgentGetHostname(agent, hostname, true));
17133     qemuDomainObjExitAgent(vm, agent);
17134 
17135     ret = 0;
17136  endjob:
17137     qemuDomainObjEndAgentJob(vm);
17138     return ret;
17139 }
17140 
17141 
17142 static int
qemuDomainGetHostnameLease(virQEMUDriver * driver,virDomainObj * vm,char ** hostname)17143 qemuDomainGetHostnameLease(virQEMUDriver *driver,
17144                            virDomainObj *vm,
17145                            char **hostname)
17146 {
17147     char macaddr[VIR_MAC_STRING_BUFLEN];
17148     g_autoptr(virConnect) conn = NULL;
17149     virNetworkDHCPLeasePtr *leases = NULL;
17150     int n_leases;
17151     size_t i, j;
17152     int ret = -1;
17153 
17154     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
17155         return -1;
17156 
17157     if (virDomainObjCheckActive(vm) < 0)
17158         goto endjob;
17159 
17160     if (!(conn = virGetConnectNetwork()))
17161         goto endjob;
17162 
17163     for (i = 0; i < vm->def->nnets; i++) {
17164         g_autoptr(virNetwork) network = NULL;
17165         virDomainNetDef *net = vm->def->nets[i];
17166 
17167         if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK)
17168             continue;
17169 
17170         virMacAddrFormat(&net->mac, macaddr);
17171         network = virNetworkLookupByName(conn, net->data.network.name);
17172 
17173         if (!network)
17174             goto endjob;
17175 
17176         if ((n_leases = virNetworkGetDHCPLeases(network, macaddr,
17177                                                 &leases, 0)) < 0)
17178             goto endjob;
17179 
17180         for (j = 0; j < n_leases; j++) {
17181             virNetworkDHCPLeasePtr lease = leases[j];
17182             if (lease->hostname && !*hostname)
17183                 *hostname = g_strdup(lease->hostname);
17184 
17185             virNetworkDHCPLeaseFree(lease);
17186         }
17187 
17188         VIR_FREE(leases);
17189 
17190         if (*hostname)
17191             goto endjob;
17192     }
17193 
17194     ret = 0;
17195  endjob:
17196     qemuDomainObjEndJob(driver, vm);
17197     return ret;
17198 }
17199 
17200 
17201 static char *
qemuDomainGetHostname(virDomainPtr dom,unsigned int flags)17202 qemuDomainGetHostname(virDomainPtr dom,
17203                       unsigned int flags)
17204 {
17205     virQEMUDriver *driver = dom->conn->privateData;
17206     virDomainObj *vm = NULL;
17207     char *hostname = NULL;
17208 
17209     virCheckFlags(VIR_DOMAIN_GET_HOSTNAME_LEASE |
17210                   VIR_DOMAIN_GET_HOSTNAME_AGENT, NULL);
17211 
17212     VIR_EXCLUSIVE_FLAGS_RET(VIR_DOMAIN_GET_HOSTNAME_LEASE,
17213                             VIR_DOMAIN_GET_HOSTNAME_AGENT,
17214                             NULL);
17215 
17216     if (!(flags & VIR_DOMAIN_GET_HOSTNAME_LEASE))
17217         flags |= VIR_DOMAIN_GET_HOSTNAME_AGENT;
17218 
17219     if (!(vm = qemuDomainObjFromDomain(dom)))
17220         return NULL;
17221 
17222     if (virDomainGetHostnameEnsureACL(dom->conn, vm->def) < 0)
17223         goto cleanup;
17224 
17225     if (flags & VIR_DOMAIN_GET_HOSTNAME_AGENT) {
17226         if (qemuDomainGetHostnameAgent(driver, vm, &hostname) < 0)
17227             goto cleanup;
17228     } else if (flags & VIR_DOMAIN_GET_HOSTNAME_LEASE) {
17229         if (qemuDomainGetHostnameLease(driver, vm, &hostname) < 0)
17230             goto cleanup;
17231     }
17232 
17233     if (!hostname) {
17234         virReportError(VIR_ERR_NO_HOSTNAME,
17235                        _("no hostname found for domain %s"),
17236                        vm->def->name);
17237         goto cleanup;
17238     }
17239 
17240  cleanup:
17241     virDomainObjEndAPI(&vm);
17242     return hostname;
17243 }
17244 
17245 
17246 static int
qemuDomainGetTime(virDomainPtr dom,long long * seconds,unsigned int * nseconds,unsigned int flags)17247 qemuDomainGetTime(virDomainPtr dom,
17248                   long long *seconds,
17249                   unsigned int *nseconds,
17250                   unsigned int flags)
17251 {
17252     virQEMUDriver *driver = dom->conn->privateData;
17253     virDomainObj *vm = NULL;
17254     qemuAgent *agent;
17255     int ret = -1;
17256     int rv;
17257 
17258     virCheckFlags(0, ret);
17259 
17260     if (!(vm = qemuDomainObjFromDomain(dom)))
17261         return ret;
17262 
17263     if (virDomainGetTimeEnsureACL(dom->conn, vm->def) < 0)
17264         goto cleanup;
17265 
17266     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
17267         goto cleanup;
17268 
17269     if (virDomainObjCheckActive(vm) < 0)
17270         goto endjob;
17271 
17272     if (!qemuDomainAgentAvailable(vm, true))
17273         goto endjob;
17274 
17275     agent = qemuDomainObjEnterAgent(vm);
17276     rv = qemuAgentGetTime(agent, seconds, nseconds);
17277     qemuDomainObjExitAgent(vm, agent);
17278 
17279     if (rv < 0)
17280         goto endjob;
17281 
17282     ret = 0;
17283 
17284  endjob:
17285     qemuDomainObjEndAgentJob(vm);
17286 
17287  cleanup:
17288     virDomainObjEndAPI(&vm);
17289     return ret;
17290 }
17291 
17292 
17293 static int
qemuDomainSetTimeAgent(virQEMUDriver * driver,virDomainObj * vm,long long seconds,unsigned int nseconds,bool rtcSync)17294 qemuDomainSetTimeAgent(virQEMUDriver *driver,
17295                        virDomainObj *vm,
17296                        long long seconds,
17297                        unsigned int nseconds,
17298                        bool rtcSync)
17299 {
17300     qemuAgent *agent;
17301     int ret = -1;
17302 
17303     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
17304         return -1;
17305 
17306     if (virDomainObjCheckActive(vm) < 0)
17307         goto endjob;
17308 
17309     if (!qemuDomainAgentAvailable(vm, true))
17310         goto endjob;
17311 
17312     agent = qemuDomainObjEnterAgent(vm);
17313     ret = qemuAgentSetTime(agent, seconds, nseconds, rtcSync);
17314     qemuDomainObjExitAgent(vm, agent);
17315 
17316  endjob:
17317     qemuDomainObjEndAgentJob(vm);
17318     return ret;
17319 }
17320 
17321 
17322 static int
qemuDomainSetTime(virDomainPtr dom,long long seconds,unsigned int nseconds,unsigned int flags)17323 qemuDomainSetTime(virDomainPtr dom,
17324                   long long seconds,
17325                   unsigned int nseconds,
17326                   unsigned int flags)
17327 {
17328     virQEMUDriver *driver = dom->conn->privateData;
17329     qemuDomainObjPrivate *priv;
17330     virDomainObj *vm;
17331     bool rtcSync = flags & VIR_DOMAIN_TIME_SYNC;
17332     int ret = -1;
17333     int rv;
17334 
17335     virCheckFlags(VIR_DOMAIN_TIME_SYNC, ret);
17336 
17337     if (!(vm = qemuDomainObjFromDomain(dom)))
17338         return ret;
17339 
17340     if (virDomainSetTimeEnsureACL(dom->conn, vm->def) < 0)
17341         goto cleanup;
17342 
17343     priv = vm->privateData;
17344 
17345     /* On x86, the rtc-reset-reinjection QMP command must be called after
17346      * setting the time to avoid trouble down the line. If the command is
17347      * not available, don't set the time at all and report an error */
17348     if (ARCH_IS_X86(vm->def->os.arch) &&
17349         !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION))
17350     {
17351         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17352                        _("cannot set time: qemu doesn't support "
17353                          "rtc-reset-reinjection command"));
17354         goto cleanup;
17355     }
17356 
17357     if (qemuDomainSetTimeAgent(driver, vm, seconds, nseconds, rtcSync) < 0)
17358         goto cleanup;
17359 
17360     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17361         goto cleanup;
17362 
17363     if (virDomainObjCheckActive(vm) < 0)
17364         goto endjob;
17365 
17366     /* Don't try to call rtc-reset-reinjection if it's not available */
17367     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) {
17368         qemuDomainObjEnterMonitor(driver, vm);
17369         rv = qemuMonitorRTCResetReinjection(priv->mon);
17370 
17371         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
17372             goto endjob;
17373     }
17374 
17375     ret = 0;
17376 
17377  endjob:
17378     qemuDomainObjEndJob(driver, vm);
17379 
17380  cleanup:
17381     virDomainObjEndAPI(&vm);
17382     return ret;
17383 }
17384 
17385 
17386 static int
qemuDomainFSFreeze(virDomainPtr dom,const char ** mountpoints,unsigned int nmountpoints,unsigned int flags)17387 qemuDomainFSFreeze(virDomainPtr dom,
17388                    const char **mountpoints,
17389                    unsigned int nmountpoints,
17390                    unsigned int flags)
17391 {
17392     virQEMUDriver *driver = dom->conn->privateData;
17393     virDomainObj *vm;
17394     int ret = -1;
17395 
17396     virCheckFlags(0, -1);
17397 
17398     if (!(vm = qemuDomainObjFromDomain(dom)))
17399         goto cleanup;
17400 
17401     if (virDomainFSFreezeEnsureACL(dom->conn, vm->def) < 0)
17402         goto cleanup;
17403 
17404     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
17405         goto cleanup;
17406 
17407     if (virDomainObjCheckActive(vm) < 0)
17408         goto endjob;
17409 
17410     ret = qemuSnapshotFSFreeze(vm, mountpoints, nmountpoints);
17411 
17412  endjob:
17413     qemuDomainObjEndAgentJob(vm);
17414 
17415  cleanup:
17416     virDomainObjEndAPI(&vm);
17417     return ret;
17418 }
17419 
17420 
17421 static int
qemuDomainFSThaw(virDomainPtr dom,const char ** mountpoints,unsigned int nmountpoints,unsigned int flags)17422 qemuDomainFSThaw(virDomainPtr dom,
17423                  const char **mountpoints,
17424                  unsigned int nmountpoints,
17425                  unsigned int flags)
17426 {
17427     virQEMUDriver *driver = dom->conn->privateData;
17428     virDomainObj *vm;
17429     int ret = -1;
17430 
17431     virCheckFlags(0, -1);
17432 
17433     if (mountpoints || nmountpoints) {
17434         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
17435                        _("specifying mountpoints is not supported"));
17436         return ret;
17437     }
17438 
17439     if (!(vm = qemuDomainObjFromDomain(dom)))
17440         goto cleanup;
17441 
17442     if (virDomainFSThawEnsureACL(dom->conn, vm->def) < 0)
17443         goto cleanup;
17444 
17445     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
17446         goto cleanup;
17447 
17448     if (virDomainObjCheckActive(vm) < 0)
17449         goto endjob;
17450 
17451     ret = qemuSnapshotFSThaw(vm, true);
17452 
17453  endjob:
17454     qemuDomainObjEndAgentJob(vm);
17455 
17456  cleanup:
17457     virDomainObjEndAPI(&vm);
17458     return ret;
17459 }
17460 
17461 
17462 static int
qemuNodeGetFreePages(virConnectPtr conn,unsigned int npages,unsigned int * pages,int startCell,unsigned int cellCount,unsigned long long * counts,unsigned int flags)17463 qemuNodeGetFreePages(virConnectPtr conn,
17464                      unsigned int npages,
17465                      unsigned int *pages,
17466                      int startCell,
17467                      unsigned int cellCount,
17468                      unsigned long long *counts,
17469                      unsigned int flags)
17470 {
17471     virQEMUDriver *driver = conn->privateData;
17472     g_autoptr(virCaps) caps = NULL;
17473     int lastCell;
17474 
17475     virCheckFlags(0, -1);
17476 
17477     if (virNodeGetFreePagesEnsureACL(conn) < 0)
17478         return -1;
17479 
17480     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
17481         return -1;
17482 
17483     lastCell = virCapabilitiesHostNUMAGetMaxNode(caps->host.numa);
17484 
17485     return virHostMemGetFreePages(npages, pages, startCell, cellCount,
17486                                   lastCell, counts);
17487 }
17488 
17489 
17490 static char *
qemuConnectGetDomainCapabilities(virConnectPtr conn,const char * emulatorbin,const char * arch_str,const char * machine,const char * virttype_str,unsigned int flags)17491 qemuConnectGetDomainCapabilities(virConnectPtr conn,
17492                                  const char *emulatorbin,
17493                                  const char *arch_str,
17494                                  const char *machine,
17495                                  const char *virttype_str,
17496                                  unsigned int flags)
17497 {
17498     virQEMUDriver *driver = conn->privateData;
17499     g_autoptr(virQEMUCaps) qemuCaps = NULL;
17500     virArch arch;
17501     virDomainVirtType virttype;
17502     g_autoptr(virDomainCaps) domCaps = NULL;
17503 
17504     virCheckFlags(0, NULL);
17505 
17506     if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
17507         return NULL;
17508 
17509     qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
17510                                              emulatorbin,
17511                                              arch_str,
17512                                              virttype_str,
17513                                              machine,
17514                                              &arch, &virttype, &machine);
17515     if (!qemuCaps)
17516         return NULL;
17517 
17518     if (!(domCaps = virQEMUDriverGetDomainCapabilities(driver,
17519                                                        qemuCaps, machine,
17520                                                        arch, virttype)))
17521         return NULL;
17522 
17523     return virDomainCapsFormat(domCaps);
17524 }
17525 
17526 
17527 static int
qemuDomainGetStatsState(virQEMUDriver * driver G_GNUC_UNUSED,virDomainObj * dom,virTypedParamList * params,unsigned int privflags G_GNUC_UNUSED)17528 qemuDomainGetStatsState(virQEMUDriver *driver G_GNUC_UNUSED,
17529                         virDomainObj *dom,
17530                         virTypedParamList *params,
17531                         unsigned int privflags G_GNUC_UNUSED)
17532 {
17533     if (virTypedParamListAddInt(params, dom->state.state, "state.state") < 0)
17534         return -1;
17535 
17536     if (virTypedParamListAddInt(params, dom->state.reason, "state.reason") < 0)
17537         return -1;
17538 
17539     return 0;
17540 }
17541 
17542 
17543 typedef enum {
17544     QEMU_DOMAIN_STATS_HAVE_JOB = 1 << 0, /* job is entered, monitor can be
17545                                             accessed */
17546     QEMU_DOMAIN_STATS_BACKING  = 1 << 1, /* include backing chain in
17547                                             block stats */
17548 } qemuDomainStatsFlags;
17549 
17550 
17551 #define HAVE_JOB(flags) ((flags) & QEMU_DOMAIN_STATS_HAVE_JOB)
17552 
17553 
17554 typedef struct _virQEMUResctrlMonData virQEMUResctrlMonData;
17555 struct _virQEMUResctrlMonData {
17556     char *name;
17557     char *vcpus;
17558     virResctrlMonitorStats **stats;
17559     size_t nstats;
17560 };
17561 
17562 
17563 static void
qemuDomainFreeResctrlMonData(virQEMUResctrlMonData * resdata)17564 qemuDomainFreeResctrlMonData(virQEMUResctrlMonData *resdata)
17565 {
17566     size_t i = 0;
17567 
17568     g_free(resdata->name);
17569     g_free(resdata->vcpus);
17570     for (i = 0; i < resdata->nstats; i++)
17571         virResctrlMonitorStatsFree(resdata->stats[i]);
17572     g_free(resdata->stats);
17573     g_free(resdata);
17574 }
17575 
17576 
17577 /**
17578  * qemuDomainGetResctrlMonData:
17579  * @dom: Pointer for the domain that the resctrl monitors reside in
17580  * @driver: Pointer to qemu driver
17581  * @resdata: Pointer of virQEMUResctrlMonData * pointer for receiving the
17582  *           virQEMUResctrlMonData *array. Caller is responsible for
17583  *           freeing the array.
17584  * @nresdata: Pointer of size_t to report the size virQEMUResctrlMonData *
17585  *            array to caller. If *@nresdata is not 0, even if function
17586  *            returns an error, the caller is also required to call
17587  *            qemuDomainFreeResctrlMonData to free each element in the
17588  *            *@resdata array and then the array itself.
17589  * @tag: Could be VIR_RESCTRL_MONITOR_TYPE_CACHE for getting cache statistics
17590  *       from @dom cache monitors. VIR_RESCTRL_MONITOR_TYPE_MEMBW for
17591  *       getting memory bandwidth statistics from memory bandwidth monitors.
17592  *
17593  * Get cache or memory bandwidth statistics from @dom monitors.
17594  *
17595  * Returns -1 on failure, or 0 on success.
17596  */
17597 static int
qemuDomainGetResctrlMonData(virQEMUDriver * driver,virDomainObj * dom,virQEMUResctrlMonData *** resdata,size_t * nresdata,virResctrlMonitorType tag)17598 qemuDomainGetResctrlMonData(virQEMUDriver *driver,
17599                             virDomainObj *dom,
17600                             virQEMUResctrlMonData ***resdata,
17601                             size_t *nresdata,
17602                             virResctrlMonitorType tag)
17603 {
17604     virDomainResctrlDef *resctrl = NULL;
17605     virQEMUResctrlMonData *res = NULL;
17606     char **features = NULL;
17607     g_autoptr(virCaps) caps = NULL;
17608     size_t i = 0;
17609     size_t j = 0;
17610 
17611     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
17612         return -1;
17613 
17614     switch (tag) {
17615     case VIR_RESCTRL_MONITOR_TYPE_CACHE:
17616         if (caps->host.cache.monitor)
17617             features = caps->host.cache.monitor->features;
17618         break;
17619     case VIR_RESCTRL_MONITOR_TYPE_MEMBW:
17620         if (caps->host.memBW.monitor)
17621             features = caps->host.memBW.monitor->features;
17622         break;
17623     case VIR_RESCTRL_MONITOR_TYPE_UNSUPPORT:
17624     case VIR_RESCTRL_MONITOR_TYPE_LAST:
17625         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
17626                        _("Unsupported resctrl monitor type"));
17627         return -1;
17628     }
17629 
17630     if (!features || !*features)
17631         return 0;
17632 
17633     for (i = 0; i < dom->def->nresctrls; i++) {
17634         resctrl = dom->def->resctrls[i];
17635 
17636         for (j = 0; j < resctrl->nmonitors; j++) {
17637             virDomainResctrlMonDef *domresmon = NULL;
17638             virResctrlMonitor *monitor = NULL;
17639 
17640             domresmon = resctrl->monitors[j];
17641             monitor = domresmon->instance;
17642 
17643             if (domresmon->tag != tag)
17644                 continue;
17645 
17646             res = g_new0(virQEMUResctrlMonData, 1);
17647 
17648             /* If virBitmapFormat successfully returns an vcpu string, then
17649              * res.vcpus is assigned with an memory space holding it,
17650              * let this newly allocated memory buffer to be freed along with
17651              * the free of 'res' */
17652             if (!(res->vcpus = virBitmapFormat(domresmon->vcpus)))
17653                 goto error;
17654 
17655             res->name = g_strdup(virResctrlMonitorGetID(monitor));
17656 
17657             if (virResctrlMonitorGetStats(monitor, (const char **)features,
17658                                           &res->stats, &res->nstats) < 0)
17659                 goto error;
17660 
17661             VIR_APPEND_ELEMENT(*resdata, *nresdata, res);
17662         }
17663     }
17664 
17665     return 0;
17666 
17667  error:
17668     qemuDomainFreeResctrlMonData(res);
17669     return -1;
17670 }
17671 
17672 
17673 static int
qemuDomainGetStatsMemoryBandwidth(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params)17674 qemuDomainGetStatsMemoryBandwidth(virQEMUDriver *driver,
17675                                   virDomainObj *dom,
17676                                   virTypedParamList *params)
17677 {
17678     virQEMUResctrlMonData **resdata = NULL;
17679     char **features = NULL;
17680     size_t nresdata = 0;
17681     size_t i = 0;
17682     size_t j = 0;
17683     size_t k = 0;
17684     int ret = -1;
17685 
17686     if (!virDomainObjIsActive(dom))
17687         return 0;
17688 
17689     if (qemuDomainGetResctrlMonData(driver, dom, &resdata, &nresdata,
17690                                     VIR_RESCTRL_MONITOR_TYPE_MEMBW) < 0)
17691         goto cleanup;
17692 
17693     if (nresdata == 0)
17694         return 0;
17695 
17696     if (virTypedParamListAddUInt(params, nresdata,
17697                                  "memory.bandwidth.monitor.count") < 0)
17698         goto cleanup;
17699 
17700     for (i = 0; i < nresdata; i++) {
17701         if (virTypedParamListAddString(params, resdata[i]->name,
17702                                        "memory.bandwidth.monitor.%zu.name",
17703                                        i) < 0)
17704             goto cleanup;
17705 
17706         if (virTypedParamListAddString(params, resdata[i]->vcpus,
17707                                        "memory.bandwidth.monitor.%zu.vcpus",
17708                                        i) < 0)
17709             goto cleanup;
17710 
17711         if (virTypedParamListAddUInt(params, resdata[i]->nstats,
17712                                      "memory.bandwidth.monitor.%zu.node.count",
17713                                      i) < 0)
17714             goto cleanup;
17715 
17716 
17717         for (j = 0; j < resdata[i]->nstats; j++) {
17718             if (virTypedParamListAddUInt(params, resdata[i]->stats[j]->id,
17719                                          "memory.bandwidth.monitor.%zu."
17720                                          "node.%zu.id",
17721                                          i, j) < 0)
17722                 goto cleanup;
17723 
17724 
17725             features = resdata[i]->stats[j]->features;
17726             for (k = 0; features[k]; k++) {
17727                 if (STREQ(features[k], "mbm_local_bytes")) {
17728                     /* The accumulative data passing through local memory
17729                      * controller is recorded with 64 bit counter. */
17730                     if (virTypedParamListAddULLong(params,
17731                                                    resdata[i]->stats[j]->vals[k],
17732                                                    "memory.bandwidth.monitor."
17733                                                    "%zu.node.%zu.bytes.local",
17734                                                    i, j) < 0)
17735                         goto cleanup;
17736                 }
17737 
17738                 if (STREQ(features[k], "mbm_total_bytes")) {
17739                     /* The accumulative data passing through local and remote
17740                      * memory controller is recorded with 64 bit counter. */
17741                     if (virTypedParamListAddULLong(params,
17742                                                    resdata[i]->stats[j]->vals[k],
17743                                                    "memory.bandwidth.monitor."
17744                                                    "%zu.node.%zu.bytes.total",
17745                                                    i, j) < 0)
17746                         goto cleanup;
17747                 }
17748             }
17749         }
17750     }
17751 
17752     ret = 0;
17753  cleanup:
17754     for (i = 0; i < nresdata; i++)
17755         qemuDomainFreeResctrlMonData(resdata[i]);
17756     VIR_FREE(resdata);
17757     return ret;
17758 }
17759 
17760 
17761 static int
qemuDomainGetStatsCpuCache(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params)17762 qemuDomainGetStatsCpuCache(virQEMUDriver *driver,
17763                            virDomainObj *dom,
17764                            virTypedParamList *params)
17765 {
17766     virQEMUResctrlMonData **resdata = NULL;
17767     size_t nresdata = 0;
17768     size_t i = 0;
17769     size_t j = 0;
17770     int ret = -1;
17771 
17772     if (!virDomainObjIsActive(dom))
17773         return 0;
17774 
17775     if (qemuDomainGetResctrlMonData(driver, dom, &resdata, &nresdata,
17776                                     VIR_RESCTRL_MONITOR_TYPE_CACHE) < 0)
17777         goto cleanup;
17778 
17779     if (virTypedParamListAddUInt(params, nresdata, "cpu.cache.monitor.count") < 0)
17780         goto cleanup;
17781 
17782     for (i = 0; i < nresdata; i++) {
17783         if (virTypedParamListAddString(params, resdata[i]->name,
17784                                        "cpu.cache.monitor.%zu.name", i) < 0)
17785             goto cleanup;
17786 
17787         if (virTypedParamListAddString(params, resdata[i]->vcpus,
17788                                        "cpu.cache.monitor.%zu.vcpus", i) < 0)
17789             goto cleanup;
17790 
17791         if (virTypedParamListAddUInt(params, resdata[i]->nstats,
17792                                      "cpu.cache.monitor.%zu.bank.count", i) < 0)
17793             goto cleanup;
17794 
17795         for (j = 0; j < resdata[i]->nstats; j++) {
17796             if (virTypedParamListAddUInt(params, resdata[i]->stats[j]->id,
17797                                          "cpu.cache.monitor.%zu.bank.%zu.id", i, j) < 0)
17798                 goto cleanup;
17799 
17800             /* 'resdata[i]->stats[j]->vals[0]' keeps the value of how many last
17801              * level cache in bank j currently occupied by the vcpus listed in
17802              * resource monitor i, in bytes. This value is reported through a
17803              * 64 bit hardware counter, so it is better to be arranged with
17804              * data type in 64 bit width, but considering the fact that
17805              * physical cache on a CPU could never be designed to be bigger
17806              * than 4G bytes in size, to keep the 'domstats' interface
17807              * historically consistent, it is safe to report the value with a
17808              * truncated 'UInt' data type here. */
17809             if (virTypedParamListAddUInt(params,
17810                                          (unsigned int)resdata[i]->stats[j]->vals[0],
17811                                          "cpu.cache.monitor.%zu.bank.%zu.bytes",
17812                                          i, j) < 0)
17813                 goto cleanup;
17814         }
17815     }
17816 
17817     ret = 0;
17818  cleanup:
17819     for (i = 0; i < nresdata; i++)
17820         qemuDomainFreeResctrlMonData(resdata[i]);
17821     VIR_FREE(resdata);
17822     return ret;
17823 }
17824 
17825 
17826 static int
qemuDomainGetStatsCpuCgroup(virDomainObj * dom,virTypedParamList * params)17827 qemuDomainGetStatsCpuCgroup(virDomainObj *dom,
17828                             virTypedParamList *params)
17829 {
17830     qemuDomainObjPrivate *priv = dom->privateData;
17831     unsigned long long cpu_time = 0;
17832     unsigned long long user_time = 0;
17833     unsigned long long sys_time = 0;
17834     int err = 0;
17835 
17836     if (!priv->cgroup)
17837         return 0;
17838 
17839     err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time);
17840     if (!err && virTypedParamListAddULLong(params, cpu_time, "cpu.time") < 0)
17841         return -1;
17842 
17843     err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time);
17844     if (!err && virTypedParamListAddULLong(params, user_time, "cpu.user") < 0)
17845         return -1;
17846     if (!err && virTypedParamListAddULLong(params, sys_time, "cpu.system") < 0)
17847         return -1;
17848 
17849     return 0;
17850 }
17851 
17852 static int
qemuDomainGetStatsCpuHaltPollTime(virDomainObj * dom,virTypedParamList * params)17853 qemuDomainGetStatsCpuHaltPollTime(virDomainObj *dom,
17854                                   virTypedParamList *params)
17855 {
17856     unsigned long long haltPollSuccess = 0;
17857     unsigned long long haltPollFail = 0;
17858     pid_t pid = dom->pid;
17859 
17860     if (virHostCPUGetHaltPollTime(pid, &haltPollSuccess, &haltPollFail) < 0)
17861         return 0;
17862 
17863     if (virTypedParamListAddULLong(params, haltPollSuccess, "cpu.haltpoll.success.time") < 0 ||
17864         virTypedParamListAddULLong(params, haltPollFail, "cpu.haltpoll.fail.time") < 0)
17865         return -1;
17866 
17867     return 0;
17868 }
17869 
17870 static int
qemuDomainGetStatsCpu(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags G_GNUC_UNUSED)17871 qemuDomainGetStatsCpu(virQEMUDriver *driver,
17872                       virDomainObj *dom,
17873                       virTypedParamList *params,
17874                       unsigned int privflags G_GNUC_UNUSED)
17875 {
17876     if (qemuDomainGetStatsCpuCgroup(dom, params) < 0)
17877         return -1;
17878 
17879     if (qemuDomainGetStatsCpuCache(driver, dom, params) < 0)
17880         return -1;
17881 
17882     if (qemuDomainGetStatsCpuHaltPollTime(dom, params) < 0)
17883         return -1;
17884 
17885     return 0;
17886 }
17887 
17888 
17889 static int
qemuDomainGetStatsMemory(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags G_GNUC_UNUSED)17890 qemuDomainGetStatsMemory(virQEMUDriver *driver,
17891                          virDomainObj *dom,
17892                          virTypedParamList *params,
17893                          unsigned int privflags G_GNUC_UNUSED)
17894 
17895 {
17896     return qemuDomainGetStatsMemoryBandwidth(driver, dom, params);
17897 }
17898 
17899 
17900 static int
qemuDomainGetStatsBalloon(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags)17901 qemuDomainGetStatsBalloon(virQEMUDriver *driver,
17902                           virDomainObj *dom,
17903                           virTypedParamList *params,
17904                           unsigned int privflags)
17905 {
17906     virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR];
17907     int nr_stats;
17908     unsigned long long cur_balloon = 0;
17909     size_t i;
17910 
17911     if (!virDomainDefHasMemballoon(dom->def)) {
17912         cur_balloon = virDomainDefGetMemoryTotal(dom->def);
17913     } else {
17914         cur_balloon = dom->def->mem.cur_balloon;
17915     }
17916 
17917     if (virTypedParamListAddULLong(params, cur_balloon, "balloon.current") < 0)
17918         return -1;
17919 
17920     if (virTypedParamListAddULLong(params, virDomainDefGetMemoryTotal(dom->def),
17921                                    "balloon.maximum") < 0)
17922         return -1;
17923 
17924     if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom))
17925         return 0;
17926 
17927     nr_stats = qemuDomainMemoryStatsInternal(driver, dom, stats,
17928                                              VIR_DOMAIN_MEMORY_STAT_NR);
17929     if (nr_stats < 0)
17930         return 0;
17931 
17932 #define STORE_MEM_RECORD(TAG, NAME) \
17933     if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ ##TAG) \
17934         if (virTypedParamListAddULLong(params, stats[i].val, "balloon." NAME) < 0) \
17935             return -1;
17936 
17937     for (i = 0; i < nr_stats; i++) {
17938         STORE_MEM_RECORD(SWAP_IN, "swap_in")
17939         STORE_MEM_RECORD(SWAP_OUT, "swap_out")
17940         STORE_MEM_RECORD(MAJOR_FAULT, "major_fault")
17941         STORE_MEM_RECORD(MINOR_FAULT, "minor_fault")
17942         STORE_MEM_RECORD(UNUSED, "unused")
17943         STORE_MEM_RECORD(AVAILABLE, "available")
17944         STORE_MEM_RECORD(RSS, "rss")
17945         STORE_MEM_RECORD(LAST_UPDATE, "last-update")
17946         STORE_MEM_RECORD(USABLE, "usable")
17947         STORE_MEM_RECORD(DISK_CACHES, "disk_caches")
17948         STORE_MEM_RECORD(HUGETLB_PGALLOC, "hugetlb_pgalloc")
17949         STORE_MEM_RECORD(HUGETLB_PGFAIL, "hugetlb_pgfail")
17950     }
17951 
17952 #undef STORE_MEM_RECORD
17953 
17954     return 0;
17955 }
17956 
17957 
17958 static int
qemuDomainGetStatsVcpu(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags)17959 qemuDomainGetStatsVcpu(virQEMUDriver *driver,
17960                        virDomainObj *dom,
17961                        virTypedParamList *params,
17962                        unsigned int privflags)
17963 {
17964     virDomainVcpuDef *vcpu;
17965     qemuDomainVcpuPrivate *vcpupriv;
17966     size_t i;
17967     int ret = -1;
17968     virVcpuInfoPtr cpuinfo = NULL;
17969     g_autofree unsigned long long *cpuwait = NULL;
17970     g_autofree unsigned long long *cpudelay = NULL;
17971 
17972     if (virTypedParamListAddUInt(params, virDomainDefGetVcpus(dom->def),
17973                                  "vcpu.current") < 0)
17974         return -1;
17975 
17976     if (virTypedParamListAddUInt(params, virDomainDefGetVcpusMax(dom->def),
17977                                  "vcpu.maximum") < 0)
17978         return -1;
17979 
17980     cpuinfo = g_new0(virVcpuInfo, virDomainDefGetVcpus(dom->def));
17981     cpuwait = g_new0(unsigned long long, virDomainDefGetVcpus(dom->def));
17982     cpudelay = g_new0(unsigned long long, virDomainDefGetVcpus(dom->def));
17983 
17984     if (HAVE_JOB(privflags) && virDomainObjIsActive(dom) &&
17985         qemuDomainRefreshVcpuHalted(driver, dom, QEMU_ASYNC_JOB_NONE) < 0) {
17986             /* it's ok to be silent and go ahead, because halted vcpu info
17987              * wasn't here from the beginning */
17988             virResetLastError();
17989     }
17990 
17991     if (qemuDomainHelperGetVcpus(dom, cpuinfo, cpuwait, cpudelay,
17992                                  virDomainDefGetVcpus(dom->def),
17993                                  NULL, 0) < 0) {
17994         virResetLastError();
17995         ret = 0; /* it's ok to be silent and go ahead */
17996         goto cleanup;
17997     }
17998 
17999     for (i = 0; i < virDomainDefGetVcpus(dom->def); i++) {
18000         if (virTypedParamListAddInt(params, cpuinfo[i].state,
18001                                     "vcpu.%u.state", cpuinfo[i].number) < 0)
18002             goto cleanup;
18003 
18004         /* stats below are available only if the VM is alive */
18005         if (!virDomainObjIsActive(dom))
18006             continue;
18007 
18008         if (virTypedParamListAddULLong(params, cpuinfo[i].cpuTime,
18009                                        "vcpu.%u.time", cpuinfo[i].number) < 0)
18010             goto cleanup;
18011 
18012         if (virTypedParamListAddULLong(params, cpuwait[i],
18013                                        "vcpu.%u.wait", cpuinfo[i].number) < 0)
18014             goto cleanup;
18015 
18016         if (virTypedParamListAddULLong(params, cpudelay[i],
18017                                         "vcpu.%u.delay", cpuinfo[i].number) < 0)
18018             goto cleanup;
18019 
18020         /* state below is extracted from the individual vcpu structs */
18021         if (!(vcpu = virDomainDefGetVcpu(dom->def, cpuinfo[i].number)))
18022             continue;
18023 
18024         vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
18025 
18026         if (vcpupriv->halted != VIR_TRISTATE_BOOL_ABSENT) {
18027             if (virTypedParamListAddBoolean(params,
18028                                             vcpupriv->halted == VIR_TRISTATE_BOOL_YES,
18029                                             "vcpu.%u.halted",
18030                                             cpuinfo[i].number) < 0)
18031                 goto cleanup;
18032         }
18033     }
18034 
18035     ret = 0;
18036 
18037  cleanup:
18038     VIR_FREE(cpuinfo);
18039     return ret;
18040 }
18041 
18042 #define QEMU_ADD_NET_PARAM(params, num, name, value) \
18043     if (value >= 0 && \
18044         virTypedParamListAddULLong((params), (value), "net.%zu.%s", (num), (name)) < 0) \
18045         return -1;
18046 
18047 static int
qemuDomainGetStatsInterface(virQEMUDriver * driver G_GNUC_UNUSED,virDomainObj * dom,virTypedParamList * params,unsigned int privflags G_GNUC_UNUSED)18048 qemuDomainGetStatsInterface(virQEMUDriver *driver G_GNUC_UNUSED,
18049                             virDomainObj *dom,
18050                             virTypedParamList *params,
18051                             unsigned int privflags G_GNUC_UNUSED)
18052 {
18053     size_t i;
18054     struct _virDomainInterfaceStats tmp;
18055 
18056     if (!virDomainObjIsActive(dom))
18057         return 0;
18058 
18059     if (virTypedParamListAddUInt(params, dom->def->nnets, "net.count") < 0)
18060         return -1;
18061 
18062     /* Check the path is one of the domain's network interfaces. */
18063     for (i = 0; i < dom->def->nnets; i++) {
18064         virDomainNetDef *net = dom->def->nets[i];
18065         virDomainNetType actualType;
18066 
18067         if (!net->ifname)
18068             continue;
18069 
18070         memset(&tmp, 0, sizeof(tmp));
18071 
18072         actualType = virDomainNetGetActualType(net);
18073 
18074         if (virTypedParamListAddString(params, net->ifname, "net.%zu.name", i) < 0)
18075             return -1;
18076 
18077         if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
18078             if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) {
18079                 virResetLastError();
18080                 continue;
18081             }
18082         } else {
18083             if (virNetDevTapInterfaceStats(net->ifname, &tmp,
18084                                            !virDomainNetTypeSharesHostView(net)) < 0) {
18085                 virResetLastError();
18086                 continue;
18087             }
18088         }
18089 
18090         QEMU_ADD_NET_PARAM(params, i,
18091                            "rx.bytes", tmp.rx_bytes);
18092         QEMU_ADD_NET_PARAM(params, i,
18093                            "rx.pkts", tmp.rx_packets);
18094         QEMU_ADD_NET_PARAM(params, i,
18095                            "rx.errs", tmp.rx_errs);
18096         QEMU_ADD_NET_PARAM(params, i,
18097                            "rx.drop", tmp.rx_drop);
18098         QEMU_ADD_NET_PARAM(params, i,
18099                            "tx.bytes", tmp.tx_bytes);
18100         QEMU_ADD_NET_PARAM(params, i,
18101                            "tx.pkts", tmp.tx_packets);
18102         QEMU_ADD_NET_PARAM(params, i,
18103                            "tx.errs", tmp.tx_errs);
18104         QEMU_ADD_NET_PARAM(params, i,
18105                            "tx.drop", tmp.tx_drop);
18106     }
18107 
18108     return 0;
18109 }
18110 
18111 #undef QEMU_ADD_NET_PARAM
18112 
18113 /* refresh information by opening images on the disk */
18114 static int
qemuDomainGetStatsOneBlockFallback(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * dom,virTypedParamList * params,virStorageSource * src,size_t block_idx)18115 qemuDomainGetStatsOneBlockFallback(virQEMUDriver *driver,
18116                                    virQEMUDriverConfig *cfg,
18117                                    virDomainObj *dom,
18118                                    virTypedParamList *params,
18119                                    virStorageSource *src,
18120                                    size_t block_idx)
18121 {
18122     if (virStorageSourceIsEmpty(src))
18123         return 0;
18124 
18125     if (qemuStorageLimitsRefresh(driver, cfg, dom, src, true) <= 0) {
18126         virResetLastError();
18127         return 0;
18128     }
18129 
18130     if (src->allocation &&
18131         virTypedParamListAddULLong(params, src->allocation,
18132                                    "block.%zu.allocation", block_idx) < 0)
18133         return -1;
18134 
18135     if (src->capacity &&
18136         virTypedParamListAddULLong(params, src->capacity,
18137                                    "block.%zu.capacity", block_idx) < 0)
18138         return -1;
18139 
18140     if (src->physical &&
18141         virTypedParamListAddULLong(params, src->physical,
18142                                    "block.%zu.physical", block_idx) < 0)
18143         return -1;
18144 
18145     return 0;
18146 }
18147 
18148 
18149 /**
18150  * qemuDomainGetStatsOneBlockRefreshNamed:
18151  * @src: disk source structure
18152  * @alias: disk alias
18153  * @stats: hash table containing stats for all disks
18154  * @nodedata: reply containing 'query-named-block-nodes' data
18155  *
18156  * Refresh disk block stats data (qemuBlockStats *) which are present only
18157  * in the reply of 'query-named-block-nodes' in cases when the data was gathered
18158  * by using query-block originally.
18159  */
18160 static void
qemuDomainGetStatsOneBlockRefreshNamed(virStorageSource * src,const char * alias,GHashTable * stats,GHashTable * nodedata)18161 qemuDomainGetStatsOneBlockRefreshNamed(virStorageSource *src,
18162                                        const char *alias,
18163                                        GHashTable *stats,
18164                                        GHashTable *nodedata)
18165 {
18166     qemuBlockStats *entry;
18167 
18168     virJSONValue *data;
18169     unsigned long long tmp;
18170 
18171     if (!nodedata || !src->nodestorage)
18172         return;
18173 
18174     if (!(entry = virHashLookup(stats, alias)))
18175         return;
18176 
18177     if (!(data = virHashLookup(nodedata, src->nodestorage)))
18178         return;
18179 
18180     if (virJSONValueObjectGetNumberUlong(data, "write_threshold", &tmp) == 0)
18181         entry->write_threshold = tmp;
18182 }
18183 
18184 
18185 static int
qemuDomainGetStatsOneBlock(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * dom,virTypedParamList * params,const char * entryname,virStorageSource * src,size_t block_idx,GHashTable * stats)18186 qemuDomainGetStatsOneBlock(virQEMUDriver *driver,
18187                            virQEMUDriverConfig *cfg,
18188                            virDomainObj *dom,
18189                            virTypedParamList *params,
18190                            const char *entryname,
18191                            virStorageSource *src,
18192                            size_t block_idx,
18193                            GHashTable *stats)
18194 {
18195     qemuBlockStats *entry;
18196 
18197     /* the VM is offline so we have to go and load the stast from the disk by
18198      * ourselves */
18199     if (!virDomainObjIsActive(dom)) {
18200         return qemuDomainGetStatsOneBlockFallback(driver, cfg, dom, params,
18201                                                   src, block_idx);
18202     }
18203 
18204     /* In case where qemu didn't provide the stats we stop here rather than
18205      * trying to refresh the stats from the disk. Inability to provide stats is
18206      * usually caused by blocked storage so this would make libvirtd hang */
18207     if (!stats || !entryname || !(entry = virHashLookup(stats, entryname)))
18208         return 0;
18209 
18210     if (virTypedParamListAddULLong(params, entry->wr_highest_offset,
18211                                    "block.%zu.allocation", block_idx) < 0)
18212         return -1;
18213 
18214     if (entry->capacity &&
18215         virTypedParamListAddULLong(params, entry->capacity,
18216                                    "block.%zu.capacity", block_idx) < 0)
18217         return -1;
18218 
18219     if (entry->physical) {
18220         if (virTypedParamListAddULLong(params, entry->physical,
18221                                        "block.%zu.physical", block_idx) < 0)
18222             return -1;
18223     } else {
18224         if (qemuDomainStorageUpdatePhysical(driver, cfg, dom, src) == 0) {
18225             if (virTypedParamListAddULLong(params, src->physical,
18226                                            "block.%zu.physical", block_idx) < 0)
18227                 return -1;
18228         }
18229     }
18230 
18231     return 0;
18232 }
18233 
18234 
18235 static int
qemuDomainGetStatsBlockExportBackendStorage(const char * entryname,GHashTable * stats,size_t recordnr,virTypedParamList * params)18236 qemuDomainGetStatsBlockExportBackendStorage(const char *entryname,
18237                                             GHashTable *stats,
18238                                             size_t recordnr,
18239                                             virTypedParamList *params)
18240 {
18241     qemuBlockStats *entry;
18242 
18243     if (!stats || !entryname || !(entry = virHashLookup(stats, entryname)))
18244         return 0;
18245 
18246     if (entry->write_threshold &&
18247         virTypedParamListAddULLong(params, entry->write_threshold,
18248                                    "block.%zu.threshold", recordnr) < 0)
18249         return -1;
18250 
18251     return 0;
18252 }
18253 
18254 
18255 static int
qemuDomainGetStatsBlockExportFrontend(const char * frontendname,GHashTable * stats,size_t idx,virTypedParamList * par)18256 qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
18257                                       GHashTable *stats,
18258                                       size_t idx,
18259                                       virTypedParamList *par)
18260 {
18261     qemuBlockStats *en;
18262 
18263     /* In case where qemu didn't provide the stats we stop here rather than
18264      * trying to refresh the stats from the disk. Inability to provide stats is
18265      * usually caused by blocked storage so this would make libvirtd hang */
18266     if (!stats || !frontendname || !(en = virHashLookup(stats, frontendname)))
18267         return 0;
18268 
18269     if (virTypedParamListAddULLong(par, en->rd_req, "block.%zu.rd.reqs", idx) < 0 ||
18270         virTypedParamListAddULLong(par, en->rd_bytes, "block.%zu.rd.bytes", idx) < 0 ||
18271         virTypedParamListAddULLong(par, en->rd_total_times, "block.%zu.rd.times", idx) < 0 ||
18272         virTypedParamListAddULLong(par, en->wr_req, "block.%zu.wr.reqs", idx) < 0 ||
18273         virTypedParamListAddULLong(par, en->wr_bytes, "block.%zu.wr.bytes", idx) < 0 ||
18274         virTypedParamListAddULLong(par, en->wr_total_times, "block.%zu.wr.times", idx) < 0 ||
18275         virTypedParamListAddULLong(par, en->flush_req, "block.%zu.fl.reqs", idx) < 0 ||
18276         virTypedParamListAddULLong(par, en->flush_total_times, "block.%zu.fl.times", idx) < 0)
18277         return -1;
18278 
18279     return 0;
18280 }
18281 
18282 
18283 static int
qemuDomainGetStatsBlockExportHeader(virDomainDiskDef * disk,virStorageSource * src,size_t recordnr,virTypedParamList * params)18284 qemuDomainGetStatsBlockExportHeader(virDomainDiskDef *disk,
18285                                     virStorageSource *src,
18286                                     size_t recordnr,
18287                                     virTypedParamList *params)
18288 {
18289     if (virTypedParamListAddString(params, disk->dst, "block.%zu.name", recordnr) < 0)
18290         return -1;
18291 
18292     if (virStorageSourceIsLocalStorage(src) && src->path &&
18293         virTypedParamListAddString(params, src->path, "block.%zu.path", recordnr) < 0)
18294         return -1;
18295 
18296     if (src->id &&
18297         virTypedParamListAddUInt(params, src->id, "block.%zu.backingIndex", recordnr) < 0)
18298         return -1;
18299 
18300     return 0;
18301 }
18302 
18303 
18304 static int
qemuDomainGetStatsBlockExportDisk(virDomainDiskDef * disk,GHashTable * stats,GHashTable * nodestats,virTypedParamList * params,size_t * recordnr,bool visitBacking,virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * dom,bool blockdev)18305 qemuDomainGetStatsBlockExportDisk(virDomainDiskDef *disk,
18306                                   GHashTable *stats,
18307                                   GHashTable *nodestats,
18308                                   virTypedParamList *params,
18309                                   size_t *recordnr,
18310                                   bool visitBacking,
18311                                   virQEMUDriver *driver,
18312                                   virQEMUDriverConfig *cfg,
18313                                   virDomainObj *dom,
18314                                   bool blockdev)
18315 
18316 {
18317     virStorageSource *n;
18318     const char *frontendalias;
18319     const char *backendalias;
18320     const char *backendstoragealias;
18321 
18322     /*
18323      * This helps to keep logs clean from error messages on getting stats
18324      * for optional disk with nonexistent source file. We won't get any
18325      * stats for such a disk anyway in below code.
18326      */
18327     if (!virDomainObjIsActive(dom) &&
18328         qemuDomainDiskIsMissingLocalOptional(disk)) {
18329         VIR_INFO("optional disk '%s' source file is missing, "
18330                  "skip getting stats", disk->dst);
18331 
18332         if (qemuDomainGetStatsBlockExportHeader(disk, disk->src, *recordnr,
18333                                                 params) < 0) {
18334             return -1;
18335         }
18336 
18337         (*recordnr)++;
18338 
18339         return 0;
18340     }
18341 
18342     /* vhost-user disk doesn't support getting block stats */
18343     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
18344         if (qemuDomainGetStatsBlockExportHeader(disk, disk->src, *recordnr,
18345                                                 params) < 0) {
18346             return -1;
18347         }
18348 
18349         (*recordnr)++;
18350 
18351         return 0;
18352     }
18353 
18354     for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
18355         g_autofree char *alias = NULL;
18356 
18357         /* for 'sd' disks we won't be displaying stats for the backing chain
18358          * as we don't update the stats correctly */
18359         if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
18360             frontendalias = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
18361             backendalias = n->nodeformat;
18362             backendstoragealias = n->nodestorage;
18363         } else {
18364             /* alias may be NULL if the VM is not running */
18365             if (disk->info.alias &&
18366                 !(alias = qemuDomainStorageAlias(disk->info.alias, n->id)))
18367                 return -1;
18368 
18369             qemuDomainGetStatsOneBlockRefreshNamed(n, alias, stats, nodestats);
18370 
18371             frontendalias = alias;
18372             backendalias = alias;
18373             backendstoragealias = alias;
18374         }
18375 
18376         if (qemuDomainGetStatsBlockExportHeader(disk, n, *recordnr, params) < 0)
18377             return -1;
18378 
18379         /* The following stats make sense only for the frontend device */
18380         if (n == disk->src) {
18381             if (qemuDomainGetStatsBlockExportFrontend(frontendalias, stats, *recordnr,
18382                                                       params) < 0)
18383                 return -1;
18384         }
18385 
18386         if (qemuDomainGetStatsOneBlock(driver, cfg, dom, params,
18387                                        backendalias, n, *recordnr,
18388                                        stats) < 0)
18389             return -1;
18390 
18391         if (qemuDomainGetStatsBlockExportBackendStorage(backendstoragealias,
18392                                                         stats, *recordnr,
18393                                                         params) < 0)
18394             return -1;
18395 
18396         (*recordnr)++;
18397 
18398         if (!visitBacking)
18399             break;
18400     }
18401 
18402     /* in blockdev mode where we can properly and uniquely identify images we
18403      * can also report stats for the mirror target or the scratch image or target
18404      * of a backup operation */
18405     if (visitBacking && blockdev) {
18406         qemuDomainObjPrivate *priv = dom->privateData;
18407 
18408         if (disk->mirror &&
18409             disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
18410             if (qemuDomainGetStatsBlockExportHeader(disk, disk->mirror, *recordnr, params) < 0)
18411                 return -1;
18412 
18413             if (qemuDomainGetStatsOneBlock(driver, cfg, dom, params,
18414                                            disk->mirror->nodeformat,
18415                                            disk->mirror,
18416                                            *recordnr,
18417                                            stats) < 0)
18418                 return -1;
18419 
18420             if (qemuDomainGetStatsBlockExportBackendStorage(disk->mirror->nodestorage,
18421                                                             stats, *recordnr,
18422                                                             params) < 0)
18423                 return -1;
18424 
18425             (*recordnr)++;
18426         }
18427 
18428         if (priv->backup) {
18429             size_t i;
18430 
18431             for (i = 0; i < priv->backup->ndisks; i++) {
18432                 virDomainBackupDiskDef *backupdisk = priv->backup->disks + i;
18433 
18434                 if (STRNEQ(disk->dst, priv->backup->disks[i].name))
18435                     continue;
18436 
18437                 if (backupdisk->store) {
18438                     if (qemuDomainGetStatsBlockExportHeader(disk, backupdisk->store,
18439                                                             *recordnr, params) < 0)
18440                         return -1;
18441 
18442                     if (qemuDomainGetStatsOneBlock(driver, cfg, dom, params,
18443                                                    backupdisk->store->nodeformat,
18444                                                    backupdisk->store,
18445                                                    *recordnr,
18446                                                    stats) < 0)
18447                         return -1;
18448 
18449                     if (qemuDomainGetStatsBlockExportBackendStorage(backupdisk->store->nodestorage,
18450                                                                     stats, *recordnr,
18451                                                                     params) < 0)
18452                         return -1;
18453 
18454                     (*recordnr)++;
18455                 }
18456 
18457                 break;
18458             }
18459         }
18460     }
18461 
18462     return 0;
18463 }
18464 
18465 
18466 static int
qemuDomainGetStatsBlock(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags)18467 qemuDomainGetStatsBlock(virQEMUDriver *driver,
18468                         virDomainObj *dom,
18469                         virTypedParamList *params,
18470                         unsigned int privflags)
18471 {
18472     size_t i;
18473     int rc;
18474     g_autoptr(GHashTable) stats = NULL;
18475     g_autoptr(GHashTable) nodestats = NULL;
18476     g_autoptr(virJSONValue) nodedata = NULL;
18477     qemuDomainObjPrivate *priv = dom->privateData;
18478     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
18479     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
18480     bool fetchnodedata = virQEMUCapsGet(priv->qemuCaps,
18481                                         QEMU_CAPS_QUERY_NAMED_BLOCK_NODES) && !blockdev;
18482     int count_index = -1;
18483     size_t visited = 0;
18484     bool visitBacking = !!(privflags & QEMU_DOMAIN_STATS_BACKING);
18485 
18486     if (HAVE_JOB(privflags) && virDomainObjIsActive(dom)) {
18487         qemuDomainObjEnterMonitor(driver, dom);
18488 
18489         rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats);
18490 
18491         if (rc >= 0) {
18492             if (blockdev)
18493                 rc = qemuMonitorBlockStatsUpdateCapacityBlockdev(priv->mon, stats);
18494             else
18495                 ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats));
18496         }
18497 
18498         if (fetchnodedata)
18499             nodedata = qemuMonitorQueryNamedBlockNodes(priv->mon);
18500 
18501         if (qemuDomainObjExitMonitor(driver, dom) < 0)
18502             return -1;
18503 
18504         /* failure to retrieve stats is fine at this point */
18505         if (rc < 0 || (fetchnodedata && !nodedata))
18506             virResetLastError();
18507     }
18508 
18509     if (nodedata &&
18510         !(nodestats = qemuBlockGetNodeData(nodedata)))
18511         return -1;
18512 
18513     /* When listing backing chains, it's easier to fix up the count
18514      * after the iteration than it is to iterate twice; but we still
18515      * want count listed first.  */
18516     count_index = params->npar;
18517     if (virTypedParamListAddUInt(params, 0, "block.count") < 0)
18518         return -1;
18519 
18520     for (i = 0; i < dom->def->ndisks; i++) {
18521         if (qemuDomainGetStatsBlockExportDisk(dom->def->disks[i], stats, nodestats,
18522                                               params, &visited,
18523                                               visitBacking, driver, cfg, dom,
18524                                               blockdev) < 0)
18525             return -1;
18526     }
18527 
18528     params->par[count_index].value.ui = visited;
18529 
18530     return 0;
18531 }
18532 
18533 
18534 static int
qemuDomainGetStatsIOThread(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags)18535 qemuDomainGetStatsIOThread(virQEMUDriver *driver,
18536                            virDomainObj *dom,
18537                            virTypedParamList *params,
18538                            unsigned int privflags)
18539 {
18540     qemuDomainObjPrivate *priv = dom->privateData;
18541     size_t i;
18542     qemuMonitorIOThreadInfo **iothreads = NULL;
18543     int niothreads = 0;
18544     int ret = -1;
18545 
18546     if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom))
18547         return 0;
18548 
18549     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD))
18550         return 0;
18551 
18552     if (qemuDomainGetIOThreadsMon(driver, dom, &iothreads, &niothreads) < 0)
18553         return -1;
18554 
18555     /* qemuDomainGetIOThreadsMon returns a NULL-terminated list, so we must free
18556      * it even if it returns 0 */
18557     if (niothreads == 0) {
18558         ret = 0;
18559         goto cleanup;
18560     }
18561 
18562     if (virTypedParamListAddUInt(params, niothreads, "iothread.count") < 0)
18563         goto cleanup;
18564 
18565     for (i = 0; i < niothreads; i++) {
18566         if (iothreads[i]->poll_valid) {
18567             if (virTypedParamListAddULLong(params, iothreads[i]->poll_max_ns,
18568                                            "iothread.%u.poll-max-ns",
18569                                            iothreads[i]->iothread_id) < 0)
18570                 goto cleanup;
18571             if (virTypedParamListAddUInt(params, iothreads[i]->poll_grow,
18572                                          "iothread.%u.poll-grow",
18573                                          iothreads[i]->iothread_id) < 0)
18574                 goto cleanup;
18575             if (virTypedParamListAddUInt(params, iothreads[i]->poll_shrink,
18576                                          "iothread.%u.poll-shrink",
18577                                          iothreads[i]->iothread_id) < 0)
18578                 goto cleanup;
18579         }
18580     }
18581 
18582     ret = 0;
18583 
18584  cleanup:
18585     for (i = 0; i < niothreads; i++)
18586         VIR_FREE(iothreads[i]);
18587     VIR_FREE(iothreads);
18588 
18589     return ret;
18590 }
18591 
18592 
18593 static int
qemuDomainGetStatsPerfOneEvent(virPerf * perf,virPerfEventType type,virTypedParamList * params)18594 qemuDomainGetStatsPerfOneEvent(virPerf *perf,
18595                                virPerfEventType type,
18596                                virTypedParamList *params)
18597 {
18598     uint64_t value = 0;
18599 
18600     if (virPerfReadEvent(perf, type, &value) < 0)
18601         return -1;
18602 
18603     if (virTypedParamListAddULLong(params, value, "perf.%s",
18604                                    virPerfEventTypeToString(type)) < 0)
18605         return -1;
18606 
18607     return 0;
18608 }
18609 
18610 static int
qemuDomainGetStatsPerf(virQEMUDriver * driver G_GNUC_UNUSED,virDomainObj * dom,virTypedParamList * params,unsigned int privflags G_GNUC_UNUSED)18611 qemuDomainGetStatsPerf(virQEMUDriver *driver G_GNUC_UNUSED,
18612                        virDomainObj *dom,
18613                        virTypedParamList *params,
18614                        unsigned int privflags G_GNUC_UNUSED)
18615 {
18616     size_t i;
18617     qemuDomainObjPrivate *priv = dom->privateData;
18618 
18619     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
18620         if (!virPerfEventIsEnabled(priv->perf, i))
18621              continue;
18622 
18623         if (qemuDomainGetStatsPerfOneEvent(priv->perf, i, params) < 0)
18624             return -1;
18625     }
18626 
18627     return 0;
18628 }
18629 
18630 static int
qemuDomainGetStatsDirtyRateMon(virQEMUDriver * driver,virDomainObj * vm,qemuMonitorDirtyRateInfo * info)18631 qemuDomainGetStatsDirtyRateMon(virQEMUDriver *driver,
18632                                virDomainObj *vm,
18633                                qemuMonitorDirtyRateInfo *info)
18634 {
18635     qemuDomainObjPrivate *priv = vm->privateData;
18636     int ret;
18637 
18638     qemuDomainObjEnterMonitor(driver, vm);
18639     ret = qemuMonitorQueryDirtyRate(priv->mon, info);
18640     if (qemuDomainObjExitMonitor(driver, vm) < 0)
18641         ret = -1;
18642 
18643     return ret;
18644 }
18645 
18646 static int
qemuDomainGetStatsDirtyRate(virQEMUDriver * driver,virDomainObj * dom,virTypedParamList * params,unsigned int privflags)18647 qemuDomainGetStatsDirtyRate(virQEMUDriver *driver,
18648                             virDomainObj *dom,
18649                             virTypedParamList *params,
18650                             unsigned int privflags)
18651 {
18652     qemuMonitorDirtyRateInfo info;
18653 
18654     if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom))
18655         return 0;
18656 
18657     if (qemuDomainGetStatsDirtyRateMon(driver, dom, &info) < 0)
18658         return -1;
18659 
18660     if (virTypedParamListAddInt(params, info.status,
18661                                 "dirtyrate.calc_status") < 0)
18662         return -1;
18663 
18664     if (virTypedParamListAddLLong(params, info.startTime,
18665                                   "dirtyrate.calc_start_time") < 0)
18666         return -1;
18667 
18668     if (virTypedParamListAddInt(params, info.calcTime,
18669                                 "dirtyrate.calc_period") < 0)
18670         return -1;
18671 
18672     if ((info.status == VIR_DOMAIN_DIRTYRATE_MEASURED) &&
18673         virTypedParamListAddLLong(params, info.dirtyRate,
18674                                   "dirtyrate.megabytes_per_second") < 0)
18675         return -1;
18676 
18677     return 0;
18678 }
18679 
18680 typedef int
18681 (*qemuDomainGetStatsFunc)(virQEMUDriver *driver,
18682                           virDomainObj *dom,
18683                           virTypedParamList *list,
18684                           unsigned int flags);
18685 
18686 struct qemuDomainGetStatsWorker {
18687     qemuDomainGetStatsFunc func;
18688     unsigned int stats;
18689     bool monitor;
18690     virQEMUCapsFlags *requiredCaps;
18691 };
18692 
18693 static virQEMUCapsFlags queryDirtyRateRequired[] = {
18694     QEMU_CAPS_QUERY_DIRTY_RATE,
18695     QEMU_CAPS_LAST,
18696 };
18697 
18698 static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
18699     { qemuDomainGetStatsState, VIR_DOMAIN_STATS_STATE, false, NULL },
18700     { qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, false, NULL },
18701     { qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true, NULL },
18702     { qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, true, NULL },
18703     { qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false, NULL },
18704     { qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true, NULL },
18705     { qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false, NULL },
18706     { qemuDomainGetStatsIOThread, VIR_DOMAIN_STATS_IOTHREAD, true, NULL },
18707     { qemuDomainGetStatsMemory, VIR_DOMAIN_STATS_MEMORY, false, NULL },
18708     { qemuDomainGetStatsDirtyRate, VIR_DOMAIN_STATS_DIRTYRATE, true, queryDirtyRateRequired },
18709     { NULL, 0, false, NULL }
18710 };
18711 
18712 
18713 static int
qemuDomainGetStatsCheckSupport(unsigned int * stats,bool enforce,virDomainObj * vm)18714 qemuDomainGetStatsCheckSupport(unsigned int *stats,
18715                                bool enforce,
18716                                virDomainObj *vm)
18717 {
18718     qemuDomainObjPrivate *priv = vm->privateData;
18719     unsigned int supportedstats = 0;
18720     size_t i;
18721 
18722     for (i = 0; qemuDomainGetStatsWorkers[i].func; i++) {
18723         bool supportedByQemu = true;
18724         virQEMUCapsFlags *requiredCaps = qemuDomainGetStatsWorkers[i].requiredCaps;
18725 
18726         while (requiredCaps && *requiredCaps != QEMU_CAPS_LAST) {
18727             if (!virQEMUCapsGet(priv->qemuCaps, *requiredCaps)) {
18728                 supportedByQemu = false;
18729                 break;
18730             }
18731 
18732             requiredCaps++;
18733         }
18734 
18735         if (supportedByQemu) {
18736             supportedstats |= qemuDomainGetStatsWorkers[i].stats;
18737         }
18738     }
18739 
18740     if (*stats == 0) {
18741         *stats = supportedstats;
18742         return 0;
18743     }
18744 
18745     if (enforce &&
18746         *stats & ~supportedstats) {
18747         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
18748                        _("Stats types bits 0x%x are not supported by this daemon or QEMU"),
18749                        *stats & ~supportedstats);
18750         return -1;
18751     }
18752 
18753     *stats &= supportedstats;
18754     return 0;
18755 }
18756 
18757 
18758 static bool
qemuDomainGetStatsNeedMonitor(unsigned int stats)18759 qemuDomainGetStatsNeedMonitor(unsigned int stats)
18760 {
18761     size_t i;
18762 
18763     for (i = 0; qemuDomainGetStatsWorkers[i].func; i++)
18764         if (stats & qemuDomainGetStatsWorkers[i].stats &&
18765             qemuDomainGetStatsWorkers[i].monitor)
18766             return true;
18767 
18768     return false;
18769 }
18770 
18771 
18772 static int
qemuDomainGetStats(virConnectPtr conn,virDomainObj * dom,unsigned int stats,virDomainStatsRecordPtr * record,unsigned int flags)18773 qemuDomainGetStats(virConnectPtr conn,
18774                    virDomainObj *dom,
18775                    unsigned int stats,
18776                    virDomainStatsRecordPtr *record,
18777                    unsigned int flags)
18778 {
18779     g_autofree virDomainStatsRecordPtr tmp = NULL;
18780     g_autoptr(virTypedParamList) params = NULL;
18781     size_t i;
18782 
18783     params = g_new0(virTypedParamList, 1);
18784 
18785     for (i = 0; qemuDomainGetStatsWorkers[i].func; i++) {
18786         if (stats & qemuDomainGetStatsWorkers[i].stats) {
18787             if (qemuDomainGetStatsWorkers[i].func(conn->privateData, dom, params,
18788                                                   flags) < 0)
18789                 return -1;
18790         }
18791     }
18792 
18793     tmp = g_new0(virDomainStatsRecord, 1);
18794 
18795     if (!(tmp->dom = virGetDomain(conn, dom->def->name,
18796                                   dom->def->uuid, dom->def->id)))
18797         return -1;
18798 
18799     tmp->nparams = virTypedParamListStealParams(params, &tmp->params);
18800     *record = g_steal_pointer(&tmp);
18801     return 0;
18802 }
18803 
18804 
18805 static int
qemuConnectGetAllDomainStats(virConnectPtr conn,virDomainPtr * doms,unsigned int ndoms,unsigned int stats,virDomainStatsRecordPtr ** retStats,unsigned int flags)18806 qemuConnectGetAllDomainStats(virConnectPtr conn,
18807                              virDomainPtr *doms,
18808                              unsigned int ndoms,
18809                              unsigned int stats,
18810                              virDomainStatsRecordPtr **retStats,
18811                              unsigned int flags)
18812 {
18813     virQEMUDriver *driver = conn->privateData;
18814     virErrorPtr orig_err = NULL;
18815     virDomainObj **vms = NULL;
18816     size_t nvms;
18817     virDomainStatsRecordPtr *tmpstats = NULL;
18818     bool enforce = !!(flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS);
18819     int nstats = 0;
18820     size_t i;
18821     int ret = -1;
18822     unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
18823                                    VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
18824                                    VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
18825 
18826     virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
18827                   VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
18828                   VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE |
18829                   VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT |
18830                   VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING |
18831                   VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, -1);
18832 
18833     if (virConnectGetAllDomainStatsEnsureACL(conn) < 0)
18834         return -1;
18835 
18836     if (ndoms) {
18837         if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms,
18838                                     &nvms, virConnectGetAllDomainStatsCheckACL,
18839                                     lflags, true) < 0)
18840             return -1;
18841     } else {
18842         if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms,
18843                                     virConnectGetAllDomainStatsCheckACL,
18844                                     lflags) < 0)
18845             return -1;
18846     }
18847 
18848     tmpstats = g_new0(virDomainStatsRecordPtr, nvms + 1);
18849 
18850     for (i = 0; i < nvms; i++) {
18851         virDomainObj *vm = vms[i];
18852         virDomainStatsRecordPtr tmp = NULL;
18853         unsigned int privflags = 0;
18854         unsigned int requestedStats = stats;
18855         unsigned int domflags = 0;
18856 
18857         virObjectLock(vm);
18858 
18859         if (qemuDomainGetStatsCheckSupport(&requestedStats, enforce, vm) < 0) {
18860             virObjectUnlock(vm);
18861             goto cleanup;
18862         }
18863 
18864         if (qemuDomainGetStatsNeedMonitor(requestedStats))
18865             privflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
18866 
18867         if (HAVE_JOB(privflags)) {
18868             int rv;
18869 
18870             if (flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT)
18871                 rv = qemuDomainObjBeginJobNowait(driver, vm, QEMU_JOB_QUERY);
18872             else
18873                 rv = qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY);
18874 
18875             if (rv == 0)
18876                 domflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
18877         }
18878         /* else: without a job it's still possible to gather some data */
18879 
18880         if (flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING)
18881             domflags |= QEMU_DOMAIN_STATS_BACKING;
18882         if (qemuDomainGetStats(conn, vm, requestedStats, &tmp, domflags) < 0) {
18883             if (HAVE_JOB(domflags) && vm)
18884                 qemuDomainObjEndJob(driver, vm);
18885 
18886             virObjectUnlock(vm);
18887             goto cleanup;
18888         }
18889 
18890         if (tmp)
18891             tmpstats[nstats++] = tmp;
18892 
18893         if (HAVE_JOB(domflags))
18894             qemuDomainObjEndJob(driver, vm);
18895 
18896         virObjectUnlock(vm);
18897     }
18898 
18899     *retStats = g_steal_pointer(&tmpstats);
18900 
18901     ret = nstats;
18902 
18903  cleanup:
18904     virErrorPreserveLast(&orig_err);
18905     virDomainStatsRecordListFree(tmpstats);
18906     virObjectListFreeCount(vms, nvms);
18907     virErrorRestore(&orig_err);
18908 
18909     return ret;
18910 }
18911 
18912 
18913 static int
qemuNodeAllocPages(virConnectPtr conn,unsigned int npages,unsigned int * pageSizes,unsigned long long * pageCounts,int startCell,unsigned int cellCount,unsigned int flags)18914 qemuNodeAllocPages(virConnectPtr conn,
18915                    unsigned int npages,
18916                    unsigned int *pageSizes,
18917                    unsigned long long *pageCounts,
18918                    int startCell,
18919                    unsigned int cellCount,
18920                    unsigned int flags)
18921 {
18922     virQEMUDriver *driver = conn->privateData;
18923     g_autoptr(virCaps) caps = NULL;
18924     int lastCell;
18925     bool add = !(flags & VIR_NODE_ALLOC_PAGES_SET);
18926 
18927     virCheckFlags(VIR_NODE_ALLOC_PAGES_SET, -1);
18928 
18929     if (virNodeAllocPagesEnsureACL(conn) < 0)
18930         return -1;
18931 
18932     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
18933         return -1;
18934 
18935     lastCell = virCapabilitiesHostNUMAGetMaxNode(caps->host.numa);
18936 
18937     return virHostMemAllocPages(npages, pageSizes, pageCounts,
18938                                 startCell, cellCount,
18939                                 lastCell, add);
18940 }
18941 
18942 static int
qemuDomainGetFSInfoAgent(virQEMUDriver * driver,virDomainObj * vm,qemuAgentFSInfo *** info)18943 qemuDomainGetFSInfoAgent(virQEMUDriver *driver,
18944                          virDomainObj *vm,
18945                          qemuAgentFSInfo ***info)
18946 {
18947     int ret = -1;
18948     qemuAgent *agent;
18949 
18950     if (qemuDomainObjBeginAgentJob(driver, vm,
18951                                    QEMU_AGENT_JOB_QUERY) < 0)
18952         return ret;
18953 
18954     if (virDomainObjCheckActive(vm) < 0)
18955         goto endjob;
18956 
18957     if (!qemuDomainAgentAvailable(vm, true))
18958         goto endjob;
18959 
18960     agent = qemuDomainObjEnterAgent(vm);
18961     ret = qemuAgentGetFSInfo(agent, info, true);
18962     qemuDomainObjExitAgent(vm, agent);
18963 
18964  endjob:
18965     qemuDomainObjEndAgentJob(vm);
18966     return ret;
18967 }
18968 
18969 static virDomainFSInfoPtr
qemuAgentFSInfoToPublic(qemuAgentFSInfo * agent,virDomainDef * vmdef)18970 qemuAgentFSInfoToPublic(qemuAgentFSInfo *agent,
18971                         virDomainDef *vmdef)
18972 {
18973     virDomainFSInfoPtr ret = NULL;
18974     size_t i;
18975 
18976     ret = g_new0(virDomainFSInfo, 1);
18977 
18978     ret->mountpoint = g_strdup(agent->mountpoint);
18979     ret->name = g_strdup(agent->name);
18980     ret->fstype = g_strdup(agent->fstype);
18981 
18982     if (agent->disks)
18983         ret->devAlias = g_new0(char *, agent->ndisks);
18984 
18985     for (i = 0; i < agent->ndisks; i++) {
18986         qemuAgentDiskAddress *agentdisk = agent->disks[i];
18987         virDomainDiskDef *diskDef;
18988 
18989         diskDef = virDomainDiskByAddress(vmdef,
18990                                          &agentdisk->pci_controller,
18991                                          agentdisk->ccw_addr,
18992                                          agentdisk->bus,
18993                                          agentdisk->target,
18994                                          agentdisk->unit);
18995         if (diskDef != NULL)
18996             ret->devAlias[ret->ndevAlias++] = g_strdup(diskDef->dst);
18997         else
18998             VIR_DEBUG("Missing target name for '%s'.", ret->mountpoint);
18999     }
19000 
19001     return ret;
19002 }
19003 
19004 /* Returns: 0 on success
19005  *          -1 otherwise
19006  */
19007 static int
virDomainFSInfoFormat(qemuAgentFSInfo ** agentinfo,int nagentinfo,virDomainDef * vmdef,virDomainFSInfoPtr ** info)19008 virDomainFSInfoFormat(qemuAgentFSInfo **agentinfo,
19009                       int nagentinfo,
19010                       virDomainDef *vmdef,
19011                       virDomainFSInfoPtr **info)
19012 {
19013     int ret = -1;
19014     virDomainFSInfoPtr *info_ret = NULL;
19015     size_t i;
19016 
19017     info_ret = g_new0(virDomainFSInfoPtr, nagentinfo);
19018 
19019     for (i = 0; i < nagentinfo; i++) {
19020         if (!(info_ret[i] = qemuAgentFSInfoToPublic(agentinfo[i], vmdef)))
19021             goto cleanup;
19022     }
19023 
19024     *info = g_steal_pointer(&info_ret);
19025     ret = nagentinfo;
19026 
19027  cleanup:
19028     if (info_ret) {
19029         for (i = 0; i < nagentinfo; i++) {
19030             /* if there was an error, free any memory we've allocated for the
19031              * return value */
19032             virDomainFSInfoFree(info_ret[i]);
19033         }
19034         g_free(info_ret);
19035     }
19036     return ret;
19037 }
19038 
19039 static int
qemuDomainGetFSInfo(virDomainPtr dom,virDomainFSInfoPtr ** info,unsigned int flags)19040 qemuDomainGetFSInfo(virDomainPtr dom,
19041                     virDomainFSInfoPtr **info,
19042                     unsigned int flags)
19043 {
19044     virQEMUDriver *driver = dom->conn->privateData;
19045     virDomainObj *vm;
19046     qemuAgentFSInfo **agentinfo = NULL;
19047     int ret = -1;
19048     int nfs = 0;
19049 
19050     virCheckFlags(0, ret);
19051 
19052     if (!(vm = qemuDomainObjFromDomain(dom)))
19053         return ret;
19054 
19055     if (virDomainGetFSInfoEnsureACL(dom->conn, vm->def) < 0)
19056         goto cleanup;
19057 
19058     if ((nfs = qemuDomainGetFSInfoAgent(driver, vm, &agentinfo)) < 0)
19059         goto cleanup;
19060 
19061     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
19062         goto cleanup;
19063 
19064     if (virDomainObjCheckActive(vm) < 0)
19065         goto endjob;
19066 
19067     ret = virDomainFSInfoFormat(agentinfo, nfs, vm->def, info);
19068 
19069  endjob:
19070     qemuDomainObjEndJob(driver, vm);
19071 
19072  cleanup:
19073     if (agentinfo) {
19074         size_t i;
19075         for (i = 0; i < nfs; i++)
19076             qemuAgentFSInfoFree(agentinfo[i]);
19077         g_free(agentinfo);
19078     }
19079     virDomainObjEndAPI(&vm);
19080     return ret;
19081 }
19082 
19083 
19084 static int
qemuDomainInterfaceAddresses(virDomainPtr dom,virDomainInterfacePtr ** ifaces,unsigned int source,unsigned int flags)19085 qemuDomainInterfaceAddresses(virDomainPtr dom,
19086                              virDomainInterfacePtr **ifaces,
19087                              unsigned int source,
19088                              unsigned int flags)
19089 {
19090     virQEMUDriver *driver = dom->conn->privateData;
19091     virDomainObj *vm = NULL;
19092     qemuAgent *agent;
19093     int ret = -1;
19094 
19095     virCheckFlags(0, -1);
19096 
19097     if (!(vm = qemuDomainObjFromDomain(dom)))
19098         goto cleanup;
19099 
19100     if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def, source) < 0)
19101         goto cleanup;
19102 
19103     if (virDomainObjCheckActive(vm) < 0)
19104         goto cleanup;
19105 
19106     switch (source) {
19107     case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE:
19108         ret = virDomainNetDHCPInterfaces(vm->def, ifaces);
19109         break;
19110 
19111     case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT:
19112         if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
19113             goto cleanup;
19114 
19115         if (!qemuDomainAgentAvailable(vm, true))
19116             goto endjob;
19117 
19118         agent = qemuDomainObjEnterAgent(vm);
19119         ret = qemuAgentGetInterfaces(agent, ifaces, true);
19120         qemuDomainObjExitAgent(vm, agent);
19121 
19122     endjob:
19123         qemuDomainObjEndAgentJob(vm);
19124 
19125         break;
19126 
19127     case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP:
19128         ret = virDomainNetARPInterfaces(vm->def, ifaces);
19129         break;
19130 
19131     default:
19132         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
19133                        _("Unknown IP address data source %d"),
19134                        source);
19135         break;
19136     }
19137 
19138  cleanup:
19139     virDomainObjEndAPI(&vm);
19140     return ret;
19141 }
19142 
19143 
19144 static int
qemuDomainSetUserPassword(virDomainPtr dom,const char * user,const char * password,unsigned int flags)19145 qemuDomainSetUserPassword(virDomainPtr dom,
19146                           const char *user,
19147                           const char *password,
19148                           unsigned int flags)
19149 {
19150     virQEMUDriver *driver = dom->conn->privateData;
19151     virDomainObj *vm;
19152     qemuAgent *agent;
19153     int ret = -1;
19154     int rv;
19155 
19156     virCheckFlags(VIR_DOMAIN_PASSWORD_ENCRYPTED, -1);
19157 
19158     if (!(vm = qemuDomainObjFromDomain(dom)))
19159         return ret;
19160 
19161     if (virDomainSetUserPasswordEnsureACL(dom->conn, vm->def) < 0)
19162         goto cleanup;
19163 
19164     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
19165         goto cleanup;
19166 
19167     if (virDomainObjCheckActive(vm) < 0)
19168         goto endjob;
19169 
19170     if (!qemuDomainAgentAvailable(vm, true))
19171         goto endjob;
19172 
19173     agent = qemuDomainObjEnterAgent(vm);
19174     rv = qemuAgentSetUserPassword(agent, user, password,
19175                                   flags & VIR_DOMAIN_PASSWORD_ENCRYPTED);
19176     qemuDomainObjExitAgent(vm, agent);
19177 
19178     if (rv < 0)
19179         goto endjob;
19180 
19181     ret = 0;
19182 
19183  endjob:
19184     qemuDomainObjEndAgentJob(vm);
19185 
19186  cleanup:
19187     virDomainObjEndAPI(&vm);
19188     return ret;
19189 }
19190 
19191 
19192 struct qemuDomainMomentWriteMetadataData {
19193     virQEMUDriver *driver;
19194     virDomainObj *vm;
19195 };
19196 
19197 
19198 static int
qemuDomainSnapshotWriteMetadataIter(void * payload,const char * name G_GNUC_UNUSED,void * opaque)19199 qemuDomainSnapshotWriteMetadataIter(void *payload,
19200                                     const char *name G_GNUC_UNUSED,
19201                                     void *opaque)
19202 {
19203     struct qemuDomainMomentWriteMetadataData *data = opaque;
19204     virQEMUDriverConfig *cfg =  virQEMUDriverGetConfig(data->driver);
19205     int ret;
19206 
19207     ret = qemuDomainSnapshotWriteMetadata(data->vm, payload,
19208                                           data->driver->xmlopt,
19209                                           cfg->snapshotDir);
19210 
19211     virObjectUnref(cfg);
19212     return ret;
19213 }
19214 
19215 
19216 static int
qemuDomainCheckpointWriteMetadataIter(void * payload,const char * name G_GNUC_UNUSED,void * opaque)19217 qemuDomainCheckpointWriteMetadataIter(void *payload,
19218                                       const char *name G_GNUC_UNUSED,
19219                                       void *opaque)
19220 {
19221     struct qemuDomainMomentWriteMetadataData *data = opaque;
19222     virQEMUDriverConfig *cfg =  virQEMUDriverGetConfig(data->driver);
19223     int ret;
19224 
19225     ret = qemuCheckpointWriteMetadata(data->vm, payload,
19226                                       data->driver->xmlopt,
19227                                       cfg->snapshotDir);
19228 
19229     virObjectUnref(cfg);
19230     return ret;
19231 }
19232 
19233 
19234 static int
qemuDomainRenameCallback(virDomainObj * vm,const char * new_name,unsigned int flags,void * opaque)19235 qemuDomainRenameCallback(virDomainObj *vm,
19236                          const char *new_name,
19237                          unsigned int flags,
19238                          void *opaque)
19239 {
19240     virQEMUDriver *driver = opaque;
19241     g_autoptr(virQEMUDriverConfig) cfg = NULL;
19242     virObjectEvent *event_new = NULL;
19243     virObjectEvent *event_old = NULL;
19244     int ret = -1;
19245     virErrorPtr err = NULL;
19246     g_autofree char *new_dom_name = NULL;
19247     g_autofree char *old_dom_name = NULL;
19248     g_autofree char *new_dom_cfg_file = NULL;
19249     g_autofree char *old_dom_cfg_file = NULL;
19250     g_autofree char *new_dom_autostart_link = NULL;
19251     g_autofree char *old_dom_autostart_link = NULL;
19252     struct qemuDomainMomentWriteMetadataData data = {
19253         .driver = driver,
19254         .vm = vm,
19255     };
19256 
19257     virCheckFlags(0, ret);
19258 
19259     if (strchr(new_name, '/')) {
19260         virReportError(VIR_ERR_XML_ERROR,
19261                        _("name %s cannot contain '/'"), new_name);
19262         return -1;
19263     }
19264 
19265     cfg = virQEMUDriverGetConfig(driver);
19266 
19267     new_dom_name = g_strdup(new_name);
19268 
19269     if (!(new_dom_cfg_file = virDomainConfigFile(cfg->configDir,
19270                                                  new_dom_name)) ||
19271         !(old_dom_cfg_file = virDomainConfigFile(cfg->configDir,
19272                                                  vm->def->name)))
19273         return -1;
19274 
19275     if (qemuDomainNamePathsCleanup(cfg, new_name, false) < 0)
19276         goto cleanup;
19277 
19278     if (vm->autostart) {
19279         if (!(new_dom_autostart_link = virDomainConfigFile(cfg->autostartDir,
19280                                                           new_dom_name)) ||
19281             !(old_dom_autostart_link = virDomainConfigFile(cfg->autostartDir,
19282                                                           vm->def->name)))
19283             return -1;
19284 
19285         if (symlink(new_dom_cfg_file, new_dom_autostart_link) < 0) {
19286             virReportSystemError(errno,
19287                                  _("Failed to create symlink '%s to '%s'"),
19288                                  new_dom_autostart_link, new_dom_cfg_file);
19289             return -1;
19290         }
19291     }
19292 
19293     /* Switch name in domain definition. */
19294     old_dom_name = vm->def->name;
19295     vm->def->name = new_dom_name;
19296     new_dom_name = NULL;
19297 
19298     if (virDomainSnapshotForEach(vm->snapshots,
19299                                  qemuDomainSnapshotWriteMetadataIter,
19300                                  &data) < 0)
19301         goto cleanup;
19302 
19303     if (virDomainCheckpointForEach(vm->checkpoints,
19304                                    qemuDomainCheckpointWriteMetadataIter,
19305                                    &data) < 0)
19306         goto cleanup;
19307 
19308     if (virDomainDefSave(vm->def, driver->xmlopt, cfg->configDir) < 0)
19309         goto cleanup;
19310 
19311     event_old = virDomainEventLifecycleNew(vm->def->id, old_dom_name, vm->def->uuid,
19312                                            VIR_DOMAIN_EVENT_UNDEFINED,
19313                                            VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);
19314     event_new = virDomainEventLifecycleNewFromObj(vm,
19315                                               VIR_DOMAIN_EVENT_DEFINED,
19316                                               VIR_DOMAIN_EVENT_DEFINED_RENAMED);
19317     virObjectEventStateQueue(driver->domainEventState, event_old);
19318     virObjectEventStateQueue(driver->domainEventState, event_new);
19319     ret = 0;
19320 
19321  cleanup:
19322     if (old_dom_name && ret < 0) {
19323         new_dom_name = vm->def->name;
19324         vm->def->name = old_dom_name;
19325         old_dom_name = NULL;
19326     }
19327 
19328     if (ret < 0)
19329         virErrorPreserveLast(&err);
19330     qemuDomainNamePathsCleanup(cfg, ret < 0 ? new_dom_name : old_dom_name, true);
19331     virErrorRestore(&err);
19332     return ret;
19333 }
19334 
qemuDomainRename(virDomainPtr dom,const char * new_name,unsigned int flags)19335 static int qemuDomainRename(virDomainPtr dom,
19336                             const char *new_name,
19337                             unsigned int flags)
19338 {
19339     virQEMUDriver *driver = dom->conn->privateData;
19340     virDomainObj *vm = NULL;
19341     int ret = -1;
19342 
19343     virCheckFlags(0, ret);
19344 
19345     if (!(vm = qemuDomainObjFromDomain(dom)))
19346         goto cleanup;
19347 
19348     if (virDomainRenameEnsureACL(dom->conn, vm->def) < 0)
19349         goto cleanup;
19350 
19351     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19352         goto cleanup;
19353 
19354     if (virDomainObjIsActive(vm)) {
19355         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19356                        _("cannot rename active domain"));
19357         goto endjob;
19358     }
19359 
19360     if (!vm->persistent) {
19361         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19362                        _("cannot rename a transient domain"));
19363         goto endjob;
19364     }
19365 
19366     if (vm->hasManagedSave) {
19367         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19368                        _("domain with a managed saved state can't be renamed"));
19369         goto endjob;
19370     }
19371 
19372     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
19373         virReportError(VIR_ERR_OPERATION_INVALID,
19374                        "%s", _("domain has to be shutoff before renaming"));
19375         goto endjob;
19376     }
19377 
19378     if (virDomainObjListRename(driver->domains, vm, new_name, flags,
19379                                qemuDomainRenameCallback, driver) < 0)
19380         goto endjob;
19381 
19382     /* Success, domain has been renamed. */
19383     ret = 0;
19384 
19385  endjob:
19386     qemuDomainObjEndJob(driver, vm);
19387 
19388  cleanup:
19389     virDomainObjEndAPI(&vm);
19390     return ret;
19391 }
19392 
19393 
19394 static int
qemuDomainGetGuestVcpusParams(virTypedParameterPtr * params,unsigned int * nparams,qemuAgentCPUInfo * info,int ninfo)19395 qemuDomainGetGuestVcpusParams(virTypedParameterPtr *params,
19396                               unsigned int *nparams,
19397                               qemuAgentCPUInfo *info,
19398                               int ninfo)
19399 {
19400     virTypedParameterPtr par = NULL;
19401     int npar = 0;
19402     int maxpar = 0;
19403     virBitmap *vcpus = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID);
19404     virBitmap *online = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID);
19405     virBitmap *offlinable = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID);
19406     g_autofree char *tmp = NULL;
19407     size_t i;
19408     int ret = -1;
19409 
19410     for (i = 0; i < ninfo; i++) {
19411         if (virBitmapSetBit(vcpus, info[i].id) < 0) {
19412             virReportError(VIR_ERR_INTERNAL_ERROR,
19413                            _("vcpu id '%u' reported by guest agent is out of "
19414                              "range"), info[i].id);
19415             goto cleanup;
19416         }
19417 
19418         if (info[i].online)
19419             ignore_value(virBitmapSetBit(online, info[i].id));
19420 
19421         if (info[i].offlinable)
19422             ignore_value(virBitmapSetBit(offlinable, info[i].id));
19423     }
19424 
19425 #define ADD_BITMAP(name) \
19426     if (!(tmp = virBitmapFormat(name))) \
19427         goto cleanup; \
19428     if (virTypedParamsAddString(&par, &npar, &maxpar, #name, tmp) < 0) \
19429         goto cleanup; \
19430 
19431     ADD_BITMAP(vcpus);
19432     ADD_BITMAP(online);
19433     ADD_BITMAP(offlinable);
19434 
19435 #undef ADD_BITMAP
19436 
19437     *nparams = npar;
19438     *params = g_steal_pointer(&par);
19439     ret = 0;
19440 
19441  cleanup:
19442     virBitmapFree(vcpus);
19443     virBitmapFree(online);
19444     virBitmapFree(offlinable);
19445     virTypedParamsFree(par, npar);
19446     return ret;
19447 }
19448 
19449 
19450 static int
qemuDomainGetGuestVcpus(virDomainPtr dom,virTypedParameterPtr * params,unsigned int * nparams,unsigned int flags)19451 qemuDomainGetGuestVcpus(virDomainPtr dom,
19452                         virTypedParameterPtr *params,
19453                         unsigned int *nparams,
19454                         unsigned int flags)
19455 {
19456     virQEMUDriver *driver = dom->conn->privateData;
19457     virDomainObj *vm = NULL;
19458     qemuAgent *agent;
19459     qemuAgentCPUInfo *info = NULL;
19460     int ninfo = 0;
19461     int ret = -1;
19462 
19463     virCheckFlags(0, ret);
19464 
19465     if (!(vm = qemuDomainObjFromDomain(dom)))
19466         goto cleanup;
19467 
19468     if (virDomainGetGuestVcpusEnsureACL(dom->conn, vm->def) < 0)
19469         goto cleanup;
19470 
19471     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
19472         goto cleanup;
19473 
19474     if (!qemuDomainAgentAvailable(vm, true))
19475         goto endjob;
19476 
19477     agent = qemuDomainObjEnterAgent(vm);
19478     ninfo = qemuAgentGetVCPUs(agent, &info);
19479     qemuDomainObjExitAgent(vm, agent);
19480 
19481     if (ninfo < 0)
19482         goto endjob;
19483 
19484     if (qemuDomainGetGuestVcpusParams(params, nparams, info, ninfo) < 0)
19485         goto endjob;
19486 
19487     ret = 0;
19488 
19489  endjob:
19490     qemuDomainObjEndAgentJob(vm);
19491 
19492  cleanup:
19493     VIR_FREE(info);
19494     virDomainObjEndAPI(&vm);
19495     return ret;
19496 }
19497 
19498 
19499 static int
qemuDomainSetGuestVcpus(virDomainPtr dom,const char * cpumap,int state,unsigned int flags)19500 qemuDomainSetGuestVcpus(virDomainPtr dom,
19501                         const char *cpumap,
19502                         int state,
19503                         unsigned int flags)
19504 {
19505     virQEMUDriver *driver = dom->conn->privateData;
19506     virDomainObj *vm = NULL;
19507     virBitmap *map = NULL;
19508     qemuAgentCPUInfo *info = NULL;
19509     qemuAgent *agent;
19510     int ninfo = 0;
19511     size_t i;
19512     int ret = -1;
19513 
19514     virCheckFlags(0, -1);
19515 
19516     if (state != 0 && state != 1) {
19517         virReportInvalidArg(state, "%s", _("unsupported state value"));
19518         return -1;
19519     }
19520 
19521     if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0)
19522         goto cleanup;
19523 
19524     if (!(vm = qemuDomainObjFromDomain(dom)))
19525         goto cleanup;
19526 
19527     if (virDomainSetGuestVcpusEnsureACL(dom->conn, vm->def) < 0)
19528         goto cleanup;
19529 
19530     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
19531         goto cleanup;
19532 
19533     if (!qemuDomainAgentAvailable(vm, true))
19534         goto endjob;
19535 
19536     agent = qemuDomainObjEnterAgent(vm);
19537     ninfo = qemuAgentGetVCPUs(agent, &info);
19538     qemuDomainObjExitAgent(vm, agent);
19539     agent = NULL;
19540 
19541     if (ninfo < 0)
19542         goto endjob;
19543 
19544     for (i = 0; i < ninfo; i++) {
19545         if (!virBitmapIsBitSet(map, info[i].id))
19546             continue;
19547 
19548         if (!state && !info[i].offlinable) {
19549             virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
19550                            _("vCPU '%u' is not offlinable"), info[i].id);
19551             goto endjob;
19552         }
19553 
19554         info[i].online = !!state;
19555         info[i].modified = true;
19556 
19557         ignore_value(virBitmapClearBit(map, info[i].id));
19558     }
19559 
19560     if (!virBitmapIsAllClear(map)) {
19561         char *tmp = virBitmapFormat(map);
19562         virReportError(VIR_ERR_INVALID_ARG,
19563                        _("guest is missing vCPUs '%s'"), NULLSTR(tmp));
19564         VIR_FREE(tmp);
19565         goto endjob;
19566     }
19567 
19568     if (!qemuDomainAgentAvailable(vm, true))
19569         goto endjob;
19570 
19571     agent = qemuDomainObjEnterAgent(vm);
19572     ret = qemuAgentSetVCPUs(agent, info, ninfo);
19573     qemuDomainObjExitAgent(vm, agent);
19574 
19575  endjob:
19576     qemuDomainObjEndAgentJob(vm);
19577 
19578  cleanup:
19579     VIR_FREE(info);
19580     virBitmapFree(map);
19581     virDomainObjEndAPI(&vm);
19582     return ret;
19583 }
19584 
19585 
19586 static int
qemuDomainSetVcpu(virDomainPtr dom,const char * cpumap,int state,unsigned int flags)19587 qemuDomainSetVcpu(virDomainPtr dom,
19588                   const char *cpumap,
19589                   int state,
19590                   unsigned int flags)
19591 {
19592     virQEMUDriver *driver = dom->conn->privateData;
19593     virDomainObj *vm = NULL;
19594     virDomainDef *def = NULL;
19595     virDomainDef *persistentDef = NULL;
19596     virBitmap *map = NULL;
19597     ssize_t lastvcpu;
19598     int ret = -1;
19599 
19600     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
19601                   VIR_DOMAIN_AFFECT_CONFIG, -1);
19602 
19603     if (state != 0 && state != 1) {
19604         virReportInvalidArg(state, "%s", _("unsupported state value"));
19605         return -1;
19606     }
19607 
19608     if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0)
19609         goto cleanup;
19610 
19611     if ((lastvcpu = virBitmapLastSetBit(map)) < 0) {
19612         virReportError(VIR_ERR_INVALID_ARG, "%s",
19613                        _("no vcpus selected for modification"));
19614         goto cleanup;
19615     }
19616 
19617     if (!(vm = qemuDomainObjFromDomain(dom)))
19618         goto cleanup;
19619 
19620     if (virDomainSetVcpuEnsureACL(dom->conn, vm->def, flags) < 0)
19621         goto cleanup;
19622 
19623     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19624         goto cleanup;
19625 
19626     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
19627         goto endjob;
19628 
19629     if (persistentDef) {
19630         if (lastvcpu >= virDomainDefGetVcpusMax(persistentDef)) {
19631             virReportError(VIR_ERR_INVALID_ARG,
19632                            _("vcpu %zd is not present in persistent config"),
19633                            lastvcpu);
19634             goto endjob;
19635         }
19636     }
19637 
19638     if (def) {
19639         if (lastvcpu >= virDomainDefGetVcpusMax(def)) {
19640             virReportError(VIR_ERR_INVALID_ARG,
19641                            _("vcpu %zd is not present in live config"),
19642                            lastvcpu);
19643             goto endjob;
19644         }
19645     }
19646 
19647     ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map, !!state);
19648 
19649  endjob:
19650     qemuDomainObjEndJob(driver, vm);
19651 
19652  cleanup:
19653     virBitmapFree(map);
19654     virDomainObjEndAPI(&vm);
19655     return ret;
19656 }
19657 
19658 
19659 static int
qemuDomainSetBlockThreshold(virDomainPtr dom,const char * dev,unsigned long long threshold,unsigned int flags)19660 qemuDomainSetBlockThreshold(virDomainPtr dom,
19661                             const char *dev,
19662                             unsigned long long threshold,
19663                             unsigned int flags)
19664 {
19665     virQEMUDriver *driver = dom->conn->privateData;
19666     qemuDomainObjPrivate *priv;
19667     virDomainObj *vm = NULL;
19668     virStorageSource *src;
19669     g_autofree char *nodename = NULL;
19670     int rc;
19671     int ret = -1;
19672 
19673     virCheckFlags(0, -1);
19674 
19675     if (!(vm = qemuDomainObjFromDomain(dom)))
19676         goto cleanup;
19677 
19678     priv = vm->privateData;
19679 
19680     if (virDomainSetBlockThresholdEnsureACL(dom->conn, vm->def) < 0)
19681         goto cleanup;
19682 
19683     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19684         goto cleanup;
19685 
19686     if (virDomainObjCheckActive(vm) < 0)
19687         goto endjob;
19688 
19689     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_WRITE_THRESHOLD)) {
19690         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
19691                        _("this qemu does not support setting device threshold"));
19692         goto endjob;
19693     }
19694 
19695     if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def, priv->backup)))
19696         goto endjob;
19697 
19698     if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_VHOST_USER) {
19699         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
19700                        _("setting device threshold is not supported for vhostuser disk"));
19701         goto endjob;
19702     }
19703 
19704     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
19705         !src->nodestorage &&
19706         qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
19707         goto endjob;
19708 
19709     if (!src->nodestorage) {
19710         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
19711                        _("threshold currently can't be set for block device '%s'"),
19712                        dev);
19713         goto endjob;
19714     }
19715 
19716     nodename = g_strdup(src->nodestorage);
19717 
19718     qemuDomainObjEnterMonitor(driver, vm);
19719     rc = qemuMonitorSetBlockThreshold(priv->mon, nodename, threshold);
19720     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
19721         goto endjob;
19722 
19723     /* we need to remember whether the threshold was registered with an explicit
19724      * index to fire the correct event */
19725     src->thresholdEventWithIndex = !!strchr(dev, '[');
19726 
19727     ret = 0;
19728 
19729  endjob:
19730     qemuDomainObjEndJob(driver, vm);
19731 
19732  cleanup:
19733     virDomainObjEndAPI(&vm);
19734     return ret;
19735 }
19736 
19737 
19738 static int
qemuDomainSetLifecycleActionValidate(virDomainDef * def,virDomainLifecycle type,virDomainLifecycleAction action)19739 qemuDomainSetLifecycleActionValidate(virDomainDef *def,
19740                                      virDomainLifecycle type,
19741                                      virDomainLifecycleAction action)
19742 {
19743     virDomainLifecycleAction onPoweroff = def->onPoweroff;
19744     virDomainLifecycleAction onReboot = def->onReboot;
19745     virDomainLifecycleAction onCrash = def->onCrash;
19746 
19747     switch (type) {
19748     case VIR_DOMAIN_LIFECYCLE_POWEROFF:
19749         onPoweroff = action;
19750         break;
19751     case VIR_DOMAIN_LIFECYCLE_REBOOT:
19752         onReboot = action;
19753         break;
19754     case VIR_DOMAIN_LIFECYCLE_CRASH:
19755         onCrash = action;
19756         break;
19757     case VIR_DOMAIN_LIFECYCLE_LAST:
19758         break;
19759     }
19760 
19761     if (qemuValidateLifecycleAction(onPoweroff, onReboot, onCrash) < 0)
19762         return -1;
19763 
19764     return 0;
19765 }
19766 
19767 
19768 static void
qemuDomainModifyLifecycleAction(virDomainDef * def,virDomainLifecycle type,virDomainLifecycleAction action)19769 qemuDomainModifyLifecycleAction(virDomainDef *def,
19770                                 virDomainLifecycle type,
19771                                 virDomainLifecycleAction action)
19772 {
19773     switch (type) {
19774     case VIR_DOMAIN_LIFECYCLE_POWEROFF:
19775         def->onPoweroff = action;
19776         break;
19777     case VIR_DOMAIN_LIFECYCLE_REBOOT:
19778         def->onReboot = action;
19779         break;
19780     case VIR_DOMAIN_LIFECYCLE_CRASH:
19781         def->onCrash = action;
19782         break;
19783     case VIR_DOMAIN_LIFECYCLE_LAST:
19784         break;
19785     }
19786 }
19787 
19788 
19789 static int
qemuDomainModifyLifecycleActionLive(virDomainObj * vm,virDomainLifecycle type,virDomainLifecycleAction action)19790 qemuDomainModifyLifecycleActionLive(virDomainObj *vm,
19791                                     virDomainLifecycle type,
19792                                     virDomainLifecycleAction action)
19793 {
19794     qemuMonitorActionReboot monReboot = QEMU_MONITOR_ACTION_REBOOT_KEEP;
19795     qemuDomainObjPrivate *priv = vm->privateData;
19796     virQEMUDriver *driver = priv->driver;
19797     int rc;
19798 
19799     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION))
19800         return 0;
19801 
19802     /* For now we only update 'reboot' action here as we want to keep the
19803      * shutdown action as is (we're emulating the outcome anyways)) */
19804     if (type != VIR_DOMAIN_LIFECYCLE_REBOOT ||
19805         vm->def->onReboot == action)
19806         return 0;
19807 
19808 
19809     switch (action) {
19810     case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
19811         monReboot = QEMU_MONITOR_ACTION_REBOOT_SHUTDOWN;
19812         break;
19813 
19814     case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
19815         monReboot = QEMU_MONITOR_ACTION_REBOOT_RESET;
19816         break;
19817 
19818     case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
19819     case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME:
19820     case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY:
19821     case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_RESTART:
19822     case VIR_DOMAIN_LIFECYCLE_ACTION_LAST:
19823         return 0;
19824     }
19825 
19826 
19827     qemuDomainObjEnterMonitor(driver, vm);
19828 
19829     rc = qemuMonitorSetAction(priv->mon,
19830                               QEMU_MONITOR_ACTION_SHUTDOWN_KEEP,
19831                               monReboot,
19832                               QEMU_MONITOR_ACTION_WATCHDOG_KEEP,
19833                               QEMU_MONITOR_ACTION_PANIC_KEEP);
19834 
19835     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
19836         return -1;
19837 
19838     return 0;
19839 }
19840 
19841 
19842 static int
qemuDomainSetLifecycleAction(virDomainPtr dom,unsigned int type,unsigned int action,unsigned int flags)19843 qemuDomainSetLifecycleAction(virDomainPtr dom,
19844                              unsigned int type,
19845                              unsigned int action,
19846                              unsigned int flags)
19847 {
19848     virQEMUDriver *driver = dom->conn->privateData;
19849     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
19850     qemuDomainObjPrivate *priv;
19851     virDomainObj *vm = NULL;
19852     virDomainDef *def = NULL;
19853     virDomainDef *persistentDef = NULL;
19854     int ret = -1;
19855 
19856     /* note that 'action' and 'type' are range-checked in the public API wrapper */
19857 
19858     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
19859                   VIR_DOMAIN_AFFECT_CONFIG, -1);
19860 
19861     if (!virDomainDefLifecycleActionAllowed(type, action))
19862         goto cleanup;
19863 
19864     if (!(vm = qemuDomainObjFromDomain(dom)))
19865         goto cleanup;
19866 
19867     priv = vm->privateData;
19868 
19869     if (virDomainSetLifecycleActionEnsureACL(dom->conn, vm->def) < 0)
19870         goto cleanup;
19871 
19872     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19873         goto cleanup;
19874 
19875     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
19876         goto endjob;
19877 
19878     if ((def && qemuDomainSetLifecycleActionValidate(def, type, action) < 0) ||
19879          (persistentDef && qemuDomainSetLifecycleActionValidate(persistentDef, type, action) < 0))
19880         goto endjob;
19881 
19882     if (def) {
19883         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) {
19884             if (priv->allowReboot == VIR_TRISTATE_BOOL_NO ||
19885                 (type == VIR_DOMAIN_LIFECYCLE_REBOOT &&
19886                  def->onReboot != action)) {
19887                 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
19888                                _("cannot update lifecycle action because QEMU was started with incompatible -no-reboot setting"));
19889                 goto endjob;
19890             }
19891         }
19892 
19893         if (qemuDomainModifyLifecycleActionLive(vm, type, action) < 0)
19894             goto endjob;
19895 
19896         qemuDomainModifyLifecycleAction(def, type, action);
19897 
19898         qemuDomainSaveStatus(vm);
19899     }
19900 
19901     if (persistentDef) {
19902         qemuDomainModifyLifecycleAction(persistentDef, type, action);
19903 
19904         if (virDomainDefSave(persistentDef, driver->xmlopt,
19905                              cfg->configDir) < 0)
19906             goto endjob;
19907     }
19908 
19909     ret = 0;
19910 
19911  endjob:
19912     qemuDomainObjEndJob(driver, vm);
19913 
19914  cleanup:
19915     virDomainObjEndAPI(&vm);
19916     return ret;
19917 }
19918 
19919 
19920 static int
qemuGetSEVInfoToParams(virQEMUCaps * qemuCaps,virTypedParameterPtr * params,int * nparams,unsigned int flags)19921 qemuGetSEVInfoToParams(virQEMUCaps *qemuCaps,
19922                        virTypedParameterPtr *params,
19923                        int *nparams,
19924                        unsigned int flags)
19925 {
19926     int maxpar = 0;
19927     int n = 0;
19928     virSEVCapability *sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
19929     virTypedParameterPtr sevParams = NULL;
19930 
19931     virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
19932 
19933     if (virTypedParamsAddString(&sevParams, &n, &maxpar,
19934                     VIR_NODE_SEV_PDH, sev->pdh) < 0)
19935         return -1;
19936 
19937     if (virTypedParamsAddString(&sevParams, &n, &maxpar,
19938                     VIR_NODE_SEV_CERT_CHAIN, sev->cert_chain) < 0)
19939         goto cleanup;
19940 
19941     if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
19942                     VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
19943         goto cleanup;
19944 
19945     if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
19946                     VIR_NODE_SEV_REDUCED_PHYS_BITS,
19947                     sev->reduced_phys_bits) < 0)
19948         goto cleanup;
19949 
19950     *params = g_steal_pointer(&sevParams);
19951     *nparams = n;
19952     return 0;
19953 
19954  cleanup:
19955     virTypedParamsFree(sevParams, n);
19956     return -1;
19957 }
19958 
19959 
19960 static int
qemuNodeGetSEVInfo(virConnectPtr conn,virTypedParameterPtr * params,int * nparams,unsigned int flags)19961 qemuNodeGetSEVInfo(virConnectPtr conn,
19962                    virTypedParameterPtr *params,
19963                    int *nparams,
19964                    unsigned int flags)
19965 {
19966     virQEMUDriver *driver = conn->privateData;
19967     g_autoptr(virQEMUCaps) qemucaps = NULL;
19968 
19969     if (virNodeGetSevInfoEnsureACL(conn) < 0)
19970         return -1;
19971 
19972     qemucaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
19973                                              NULL, NULL, NULL, NULL,
19974                                              NULL, NULL, NULL);
19975 
19976     if (!qemucaps)
19977         return -1;
19978 
19979     if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
19980         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
19981                        _("QEMU does not support SEV guest"));
19982         return -1;
19983     }
19984 
19985     if (qemuGetSEVInfoToParams(qemucaps, params, nparams, flags) < 0)
19986         return -1;
19987 
19988     return 0;
19989 }
19990 
19991 
19992 static int
qemuDomainGetSEVMeasurement(virQEMUDriver * driver,virDomainObj * vm,virTypedParameterPtr * params,int * nparams,unsigned int flags)19993 qemuDomainGetSEVMeasurement(virQEMUDriver *driver,
19994                             virDomainObj *vm,
19995                             virTypedParameterPtr *params,
19996                             int *nparams,
19997                             unsigned int flags)
19998 {
19999     int ret = -1;
20000     g_autofree char *tmp = NULL;
20001     int maxpar = 0;
20002 
20003     virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
20004 
20005     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
20006         return -1;
20007 
20008     qemuDomainObjEnterMonitor(driver, vm);
20009     tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
20010 
20011     if (qemuDomainObjExitMonitor(driver, vm) < 0)
20012         goto endjob;
20013 
20014     if (!tmp)
20015         goto endjob;
20016 
20017     if (virTypedParamsAddString(params, nparams, &maxpar,
20018                                 VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
20019                                 tmp) < 0)
20020         goto endjob;
20021 
20022     ret = 0;
20023 
20024  endjob:
20025     qemuDomainObjEndJob(driver, vm);
20026     return ret;
20027 }
20028 
20029 
20030 static int
qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,virTypedParameterPtr * params,int * nparams,unsigned int flags)20031 qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
20032                                 virTypedParameterPtr *params,
20033                                 int *nparams,
20034                                 unsigned int flags)
20035 {
20036     virQEMUDriver *driver = domain->conn->privateData;
20037     virDomainObj *vm;
20038     int ret = -1;
20039 
20040     if (!(vm = qemuDomainObjFromDomain(domain)))
20041         goto cleanup;
20042 
20043     if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
20044         goto cleanup;
20045 
20046     if (vm->def->sec &&
20047         vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) {
20048         if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 0)
20049             goto cleanup;
20050     }
20051 
20052     ret = 0;
20053 
20054  cleanup:
20055     virDomainObjEndAPI(&vm);
20056     return ret;
20057 }
20058 
20059 static const unsigned int qemuDomainGetGuestInfoSupportedTypes =
20060     VIR_DOMAIN_GUEST_INFO_USERS |
20061     VIR_DOMAIN_GUEST_INFO_OS |
20062     VIR_DOMAIN_GUEST_INFO_TIMEZONE |
20063     VIR_DOMAIN_GUEST_INFO_HOSTNAME |
20064     VIR_DOMAIN_GUEST_INFO_FILESYSTEM |
20065     VIR_DOMAIN_GUEST_INFO_DISKS |
20066     VIR_DOMAIN_GUEST_INFO_INTERFACES;
20067 
20068 static int
qemuDomainGetGuestInfoCheckSupport(unsigned int types,unsigned int * supportedTypes)20069 qemuDomainGetGuestInfoCheckSupport(unsigned int types,
20070                                    unsigned int *supportedTypes)
20071 {
20072     if (types == 0) {
20073         *supportedTypes = qemuDomainGetGuestInfoSupportedTypes;
20074         return 0;
20075     }
20076 
20077     *supportedTypes = types & qemuDomainGetGuestInfoSupportedTypes;
20078 
20079     if (types != *supportedTypes) {
20080         virReportError(VIR_ERR_INVALID_ARG,
20081                        _("unsupported guest information types '0x%x'"),
20082                        types & ~qemuDomainGetGuestInfoSupportedTypes);
20083         return -1;
20084     }
20085 
20086     return 0;
20087 }
20088 
20089 
20090 static void
qemuAgentDiskInfoFormatParams(qemuAgentDiskInfo ** info,int ndisks,virDomainDef * vmdef,virTypedParameterPtr * params,int * nparams,int * maxparams)20091 qemuAgentDiskInfoFormatParams(qemuAgentDiskInfo **info,
20092                               int ndisks,
20093                               virDomainDef *vmdef,
20094                               virTypedParameterPtr *params,
20095                               int *nparams, int *maxparams)
20096 {
20097     size_t i, j, ndeps;
20098 
20099     if (virTypedParamsAddUInt(params, nparams, maxparams,
20100                               "disk.count", ndisks) < 0)
20101         return;
20102 
20103     for (i = 0; i < ndisks; i++) {
20104         char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
20105 
20106         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20107                    "disk.%zu.name", i);
20108         if (virTypedParamsAddString(params, nparams, maxparams,
20109                                     param_name, info[i]->name) < 0)
20110             return;
20111 
20112         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20113                    "disk.%zu.partition", i);
20114         if (virTypedParamsAddBoolean(params, nparams, maxparams,
20115                                      param_name, info[i]->partition) < 0)
20116             return;
20117 
20118         if (info[i]->dependencies) {
20119             ndeps = g_strv_length(info[i]->dependencies);
20120             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20121                        "disk.%zu.dependency.count", i);
20122             if (ndeps &&
20123                 virTypedParamsAddUInt(params, nparams, maxparams,
20124                                       param_name, ndeps) < 0)
20125                 return;
20126             for (j = 0; j < ndeps; j++) {
20127                 g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20128                            "disk.%zu.dependency.%zu.name", i, j);
20129                 if (virTypedParamsAddString(params, nparams, maxparams,
20130                                             param_name, info[i]->dependencies[j]) < 0)
20131                     return;
20132             }
20133         }
20134 
20135         if (info[i]->address) {
20136             qemuAgentDiskAddress *address = info[i]->address;
20137             virDomainDiskDef *diskdef = NULL;
20138 
20139             if (address->serial) {
20140                 g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20141                            "disk.%zu.serial", i);
20142                 if (virTypedParamsAddString(params, nparams, maxparams,
20143                                             param_name, address->serial) < 0)
20144                     return;
20145             }
20146 
20147             /* match the disk to the target in the vm definition */
20148             diskdef = virDomainDiskByAddress(vmdef,
20149                                              &address->pci_controller,
20150                                              address->ccw_addr,
20151                                              address->bus,
20152                                              address->target,
20153                                              address->unit);
20154             if (diskdef) {
20155                 g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20156                            "disk.%zu.alias", i);
20157                 if (diskdef->dst &&
20158                     virTypedParamsAddString(params, nparams, maxparams,
20159                                             param_name, diskdef->dst) < 0)
20160                     return;
20161             }
20162         }
20163 
20164         if (info[i]->alias) {
20165             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20166                        "disk.%zu.guest_alias", i);
20167             if (virTypedParamsAddString(params, nparams, maxparams,
20168                                         param_name, info[i]->alias) < 0)
20169                 return;
20170         }
20171     }
20172 }
20173 
20174 
20175 static void
qemuAgentFSInfoFormatParams(qemuAgentFSInfo ** fsinfo,int nfs,virDomainDef * vmdef,virTypedParameterPtr * params,int * nparams,int * maxparams)20176 qemuAgentFSInfoFormatParams(qemuAgentFSInfo **fsinfo,
20177                             int nfs,
20178                             virDomainDef *vmdef,
20179                             virTypedParameterPtr *params,
20180                             int *nparams, int *maxparams)
20181 {
20182     size_t i, j;
20183 
20184     /* FIXME: get disk target */
20185 
20186     if (virTypedParamsAddUInt(params, nparams, maxparams,
20187                               "fs.count", nfs) < 0)
20188         return;
20189 
20190     for (i = 0; i < nfs; i++) {
20191         char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
20192         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20193                    "fs.%zu.name", i);
20194         if (virTypedParamsAddString(params, nparams, maxparams,
20195                                     param_name, fsinfo[i]->name) < 0)
20196             return;
20197         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20198                    "fs.%zu.mountpoint", i);
20199         if (virTypedParamsAddString(params, nparams, maxparams,
20200                                     param_name, fsinfo[i]->mountpoint) < 0)
20201             return;
20202         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20203                    "fs.%zu.fstype", i);
20204         if (virTypedParamsAddString(params, nparams, maxparams,
20205                                     param_name, fsinfo[i]->fstype) < 0)
20206             return;
20207 
20208         /* disk usage values are not returned by older guest agents, so
20209          * only add the params if the value is set */
20210         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20211                    "fs.%zu.total-bytes", i);
20212         if (fsinfo[i]->total_bytes != -1 &&
20213             virTypedParamsAddULLong(params, nparams, maxparams,
20214                                     param_name, fsinfo[i]->total_bytes) < 0)
20215             return;
20216 
20217         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20218                    "fs.%zu.used-bytes", i);
20219         if (fsinfo[i]->used_bytes != -1 &&
20220             virTypedParamsAddULLong(params, nparams, maxparams,
20221                                     param_name, fsinfo[i]->used_bytes) < 0)
20222             return;
20223 
20224         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20225                    "fs.%zu.disk.count", i);
20226         if (virTypedParamsAddUInt(params, nparams, maxparams,
20227                                   param_name, fsinfo[i]->ndisks) < 0)
20228             return;
20229         for (j = 0; j < fsinfo[i]->ndisks; j++) {
20230             virDomainDiskDef *diskdef = NULL;
20231             qemuAgentDiskAddress *d = fsinfo[i]->disks[j];
20232             /* match the disk to the target in the vm definition */
20233             diskdef = virDomainDiskByAddress(vmdef,
20234                                              &d->pci_controller,
20235                                              d->ccw_addr,
20236                                              d->bus,
20237                                              d->target,
20238                                              d->unit);
20239             if (diskdef) {
20240                 g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20241                            "fs.%zu.disk.%zu.alias", i, j);
20242                 if (diskdef->dst &&
20243                     virTypedParamsAddString(params, nparams, maxparams,
20244                                             param_name, diskdef->dst) < 0)
20245                     return;
20246             }
20247 
20248             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20249                        "fs.%zu.disk.%zu.serial", i, j);
20250             if (d->serial &&
20251                 virTypedParamsAddString(params, nparams, maxparams,
20252                                         param_name, d->serial) < 0)
20253                 return;
20254 
20255             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20256                        "fs.%zu.disk.%zu.device", i, j);
20257             if (d->devnode &&
20258                 virTypedParamsAddString(params, nparams, maxparams,
20259                                         param_name, d->devnode) < 0)
20260                 return;
20261         }
20262     }
20263 }
20264 
20265 static void
virDomainInterfaceFormatParams(virDomainInterfacePtr * ifaces,int nifaces,virTypedParameterPtr * params,int * nparams,int * maxparams)20266 virDomainInterfaceFormatParams(virDomainInterfacePtr *ifaces,
20267                                int nifaces,
20268                                virTypedParameterPtr *params,
20269                                int *nparams, int *maxparams)
20270 {
20271     size_t i;
20272     size_t j;
20273 
20274     if (virTypedParamsAddUInt(params, nparams, maxparams,
20275                              "if.count", nifaces) < 0)
20276         return;
20277 
20278     for (i = 0; i < nifaces; i++) {
20279         char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
20280 
20281         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20282                    "if.%zu.name", i);
20283         if (virTypedParamsAddString(params, nparams, maxparams,
20284                                     param_name, ifaces[i]->name) < 0)
20285             return;
20286 
20287         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20288                    "if.%zu.hwaddr", i);
20289         if (virTypedParamsAddString(params, nparams, maxparams,
20290                                     param_name, ifaces[i]->hwaddr) < 0)
20291             return;
20292 
20293         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20294                    "if.%zu.addr.count", i);
20295         if (virTypedParamsAddUInt(params, nparams, maxparams,
20296                                   param_name, ifaces[i]->naddrs) < 0)
20297             return;
20298 
20299         for (j = 0; j < ifaces[i]->naddrs; j++) {
20300             const char *type = NULL;
20301 
20302             switch (ifaces[i]->addrs[j].type) {
20303                 case VIR_IP_ADDR_TYPE_IPV4:
20304                     type = "ipv4";
20305                     break;
20306                 case VIR_IP_ADDR_TYPE_IPV6:
20307                     type = "ipv6";
20308                     break;
20309             }
20310 
20311             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20312                        "if.%zu.addr.%zu.type", i, j);
20313             if (virTypedParamsAddString(params, nparams, maxparams,
20314                                         param_name, type) < 0)
20315             return;
20316 
20317             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20318                        "if.%zu.addr.%zu.addr", i, j);
20319             if (virTypedParamsAddString(params, nparams, maxparams,
20320                                         param_name, ifaces[i]->addrs[j].addr) < 0)
20321             return;
20322 
20323             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
20324                        "if.%zu.addr.%zu.prefix", i, j);
20325             if (virTypedParamsAddUInt(params, nparams, maxparams,
20326                                       param_name, ifaces[i]->addrs[j].prefix) < 0)
20327             return;
20328         }
20329     }
20330 }
20331 
20332 static int
qemuDomainGetGuestInfo(virDomainPtr dom,unsigned int types,virTypedParameterPtr * params,int * nparams,unsigned int flags)20333 qemuDomainGetGuestInfo(virDomainPtr dom,
20334                        unsigned int types,
20335                        virTypedParameterPtr *params,
20336                        int *nparams,
20337                        unsigned int flags)
20338 {
20339     virQEMUDriver *driver = dom->conn->privateData;
20340     virDomainObj *vm = NULL;
20341     qemuAgent *agent;
20342     int ret = -1;
20343     int maxparams = 0;
20344     g_autofree char *hostname = NULL;
20345     unsigned int supportedTypes;
20346     bool report_unsupported = types != 0;
20347     int rc;
20348     size_t nfs = 0;
20349     qemuAgentFSInfo **agentfsinfo = NULL;
20350     size_t ndisks = 0;
20351     qemuAgentDiskInfo **agentdiskinfo = NULL;
20352     virDomainInterfacePtr *ifaces = NULL;
20353     size_t nifaces = 0;
20354     size_t i;
20355 
20356     virCheckFlags(0, -1);
20357 
20358     if (qemuDomainGetGuestInfoCheckSupport(types, &supportedTypes) < 0)
20359         return -1;
20360 
20361     if (!(vm = qemuDomainObjFromDomain(dom)))
20362         goto cleanup;
20363 
20364     if (virDomainGetGuestInfoEnsureACL(dom->conn, vm->def) < 0)
20365         goto cleanup;
20366 
20367     if (qemuDomainObjBeginAgentJob(driver, vm,
20368                                    QEMU_AGENT_JOB_QUERY) < 0)
20369         goto cleanup;
20370 
20371     if (!qemuDomainAgentAvailable(vm, true))
20372         goto endagentjob;
20373 
20374     agent = qemuDomainObjEnterAgent(vm);
20375 
20376     /* The agent info commands will return -2 for any commands that are not
20377      * supported by the agent, or -1 for all other errors. In the case where no
20378      * categories were explicitly requested (i.e. 'types' is 0), ignore
20379      * 'unsupported' errors and gather as much information as we can. In all
20380      * other cases, abort on error. */
20381     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_USERS &&
20382         qemuAgentGetUsers(agent, params, nparams, &maxparams, report_unsupported) == -1)
20383         goto exitagent;
20384 
20385     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_OS &&
20386         qemuAgentGetOSInfo(agent, params, nparams, &maxparams, report_unsupported) == -1)
20387         goto exitagent;
20388 
20389     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_TIMEZONE &&
20390         qemuAgentGetTimezone(agent, params, nparams, &maxparams, report_unsupported) == -1)
20391         goto exitagent;
20392 
20393     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_HOSTNAME &&
20394         qemuAgentGetHostname(agent, &hostname, report_unsupported) == -1)
20395         goto exitagent;
20396 
20397     if (hostname &&
20398         virTypedParamsAddString(params, nparams, &maxparams, "hostname", hostname) < 0)
20399         goto exitagent;
20400 
20401     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_FILESYSTEM) {
20402         rc = qemuAgentGetFSInfo(agent, &agentfsinfo, report_unsupported);
20403         if (rc == -1)
20404             goto exitagent;
20405         if (rc >= 0)
20406             nfs = rc;
20407     }
20408 
20409     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_DISKS) {
20410         rc = qemuAgentGetDisks(agent, &agentdiskinfo, report_unsupported);
20411         if (rc == -1)
20412             goto exitagent;
20413         if (rc >= 0)
20414             ndisks = rc;
20415     }
20416 
20417     if (supportedTypes & VIR_DOMAIN_GUEST_INFO_INTERFACES) {
20418         rc = qemuAgentGetInterfaces(agent, &ifaces, report_unsupported);
20419         if (rc == -1)
20420             goto exitagent;
20421         if (rc >= 0)
20422             nifaces = rc;
20423     }
20424 
20425     qemuDomainObjExitAgent(vm, agent);
20426     qemuDomainObjEndAgentJob(vm);
20427 
20428     if (nfs > 0 || ndisks > 0) {
20429         if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
20430             goto cleanup;
20431 
20432         if (virDomainObjCheckActive(vm) < 0)
20433             goto endjob;
20434 
20435         /* we need to convert the agent fsinfo struct to parameters and match
20436          * it to the vm disk target */
20437         if (nfs > 0)
20438             qemuAgentFSInfoFormatParams(agentfsinfo, nfs, vm->def, params, nparams, &maxparams);
20439 
20440         if (ndisks > 0)
20441             qemuAgentDiskInfoFormatParams(agentdiskinfo, ndisks, vm->def, params, nparams, &maxparams);
20442 
20443  endjob:
20444         qemuDomainObjEndJob(driver, vm);
20445     }
20446 
20447     if (nifaces > 0) {
20448         virDomainInterfaceFormatParams(ifaces, nifaces, params, nparams, &maxparams);
20449     }
20450 
20451     ret = 0;
20452 
20453  cleanup:
20454     for (i = 0; i < nfs; i++)
20455         qemuAgentFSInfoFree(agentfsinfo[i]);
20456     g_free(agentfsinfo);
20457     for (i = 0; i < ndisks; i++)
20458         qemuAgentDiskInfoFree(agentdiskinfo[i]);
20459     g_free(agentdiskinfo);
20460     if (ifaces && nifaces > 0) {
20461         for (i = 0; i < nifaces; i++)
20462             virDomainInterfaceFree(ifaces[i]);
20463     }
20464     g_free(ifaces);
20465 
20466     virDomainObjEndAPI(&vm);
20467     return ret;
20468 
20469  exitagent:
20470     qemuDomainObjExitAgent(vm, agent);
20471 
20472  endagentjob:
20473     qemuDomainObjEndAgentJob(vm);
20474     goto cleanup;
20475 }
20476 
20477 
20478 static int
qemuDomainAgentSetResponseTimeout(virDomainPtr dom,int timeout,unsigned int flags)20479 qemuDomainAgentSetResponseTimeout(virDomainPtr dom,
20480                                   int timeout,
20481                                   unsigned int flags)
20482 {
20483     virDomainObj *vm = NULL;
20484     int ret = -1;
20485 
20486     virCheckFlags(0, -1);
20487 
20488     if (timeout < VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN) {
20489         virReportError(VIR_ERR_INVALID_ARG,
20490                        _("guest agent timeout '%d' is "
20491                          "less than the minimum '%d'"),
20492                        timeout, VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN);
20493         return -1;
20494     }
20495 
20496     if (!(vm = qemuDomainObjFromDomain(dom)))
20497         return -1;
20498 
20499     if (virDomainAgentSetResponseTimeoutEnsureACL(dom->conn, vm->def) < 0)
20500         goto cleanup;
20501 
20502     /* If domain has an agent, change its timeout. Otherwise just save the
20503      * request so that we can set the timeout when the agent appears */
20504     if (qemuDomainAgentAvailable(vm, false)) {
20505         /* We don't need to acquire a job since we're not interacting with the
20506          * agent or the qemu monitor. We're only setting a struct member, so
20507          * just acquire the mutex lock. Worst case, any in-process agent
20508          * commands will use the newly-set agent timeout. */
20509         virObjectLock(QEMU_DOMAIN_PRIVATE(vm)->agent);
20510         qemuAgentSetResponseTimeout(QEMU_DOMAIN_PRIVATE(vm)->agent, timeout);
20511         virObjectUnlock(QEMU_DOMAIN_PRIVATE(vm)->agent);
20512     }
20513 
20514     QEMU_DOMAIN_PRIVATE(vm)->agentTimeout = timeout;
20515 
20516     qemuDomainSaveStatus(vm);
20517 
20518     ret = 0;
20519 
20520  cleanup:
20521     virDomainObjEndAPI(&vm);
20522     return ret;
20523 }
20524 
20525 
20526 static int
qemuDomainAuthorizedSSHKeysGet(virDomainPtr dom,const char * user,char *** keys,unsigned int flags)20527 qemuDomainAuthorizedSSHKeysGet(virDomainPtr dom,
20528                                const char *user,
20529                                char ***keys,
20530                                unsigned int flags)
20531 {
20532     virQEMUDriver *driver = dom->conn->privateData;
20533     virDomainObj *vm = NULL;
20534     qemuAgent *agent;
20535     int rv = -1;
20536 
20537     virCheckFlags(0, -1);
20538 
20539     if (!(vm = qemuDomainObjFromDomain(dom)))
20540         return -1;
20541 
20542     if (virDomainAuthorizedSshKeysGetEnsureACL(dom->conn, vm->def) < 0)
20543         goto cleanup;
20544 
20545     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
20546         goto cleanup;
20547 
20548     if (!qemuDomainAgentAvailable(vm, true))
20549         goto endagentjob;
20550 
20551     agent = qemuDomainObjEnterAgent(vm);
20552     rv = qemuAgentSSHGetAuthorizedKeys(agent, user, keys);
20553     qemuDomainObjExitAgent(vm, agent);
20554 
20555  endagentjob:
20556     qemuDomainObjEndAgentJob(vm);
20557  cleanup:
20558     virDomainObjEndAPI(&vm);
20559     return rv;
20560 }
20561 
20562 
20563 static int
qemuDomainAuthorizedSSHKeysSet(virDomainPtr dom,const char * user,const char ** keys,unsigned int nkeys,unsigned int flags)20564 qemuDomainAuthorizedSSHKeysSet(virDomainPtr dom,
20565                                const char *user,
20566                                const char **keys,
20567                                unsigned int nkeys,
20568                                unsigned int flags)
20569 {
20570     virQEMUDriver *driver = dom->conn->privateData;
20571     virDomainObj *vm = NULL;
20572     qemuAgent *agent;
20573     const bool append = flags & VIR_DOMAIN_AUTHORIZED_SSH_KEYS_SET_APPEND;
20574     const bool remove = flags & VIR_DOMAIN_AUTHORIZED_SSH_KEYS_SET_REMOVE;
20575     int rv = -1;
20576 
20577     virCheckFlags(VIR_DOMAIN_AUTHORIZED_SSH_KEYS_SET_APPEND |
20578                   VIR_DOMAIN_AUTHORIZED_SSH_KEYS_SET_REMOVE, -1);
20579 
20580     if (!(vm = qemuDomainObjFromDomain(dom)))
20581         return -1;
20582 
20583     if (virDomainAuthorizedSshKeysSetEnsureACL(dom->conn, vm->def) < 0)
20584         goto cleanup;
20585 
20586     if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
20587         goto cleanup;
20588 
20589     if (!qemuDomainAgentAvailable(vm, true))
20590         goto endagentjob;
20591 
20592     agent = qemuDomainObjEnterAgent(vm);
20593     if (remove)
20594         rv = qemuAgentSSHRemoveAuthorizedKeys(agent, user, keys, nkeys);
20595     else
20596         rv = qemuAgentSSHAddAuthorizedKeys(agent, user, keys, nkeys, !append);
20597     qemuDomainObjExitAgent(vm, agent);
20598 
20599  endagentjob:
20600     qemuDomainObjEndAgentJob(vm);
20601  cleanup:
20602     virDomainObjEndAPI(&vm);
20603     return rv;
20604 }
20605 
20606 
20607 static int
qemuDomainGetMessages(virDomainPtr dom,char *** msgs,unsigned int flags)20608 qemuDomainGetMessages(virDomainPtr dom,
20609                       char ***msgs,
20610                       unsigned int flags)
20611 {
20612     virDomainObj *vm = NULL;
20613     int rv = -1;
20614 
20615     virCheckFlags(VIR_DOMAIN_MESSAGE_DEPRECATION |
20616                   VIR_DOMAIN_MESSAGE_TAINTING, -1);
20617 
20618     if (!(vm = qemuDomainObjFromDomain(dom)))
20619         return -1;
20620 
20621     if (virDomainGetMessagesEnsureACL(dom->conn, vm->def) < 0)
20622         goto cleanup;
20623 
20624     rv = virDomainObjGetMessages(vm, msgs, flags);
20625 
20626  cleanup:
20627     virDomainObjEndAPI(&vm);
20628     return rv;
20629 }
20630 
20631 
20632 #define MIN_DIRTYRATE_CALC_PERIOD 1  /* supported min dirtyrate calculating time: 1s */
20633 #define MAX_DIRTYRATE_CALC_PERIOD 60 /* supported max dirtyrate calculating time: 60s */
20634 
20635 static int
qemuDomainStartDirtyRateCalc(virDomainPtr dom,int seconds,unsigned int flags)20636 qemuDomainStartDirtyRateCalc(virDomainPtr dom,
20637                              int seconds,
20638                              unsigned int flags)
20639 {
20640     virQEMUDriver *driver = dom->conn->privateData;
20641     virDomainObj *vm = NULL;
20642     qemuDomainObjPrivate *priv;
20643     int ret = -1;
20644 
20645     virCheckFlags(0, -1);
20646 
20647     if (seconds < MIN_DIRTYRATE_CALC_PERIOD ||
20648         seconds > MAX_DIRTYRATE_CALC_PERIOD) {
20649         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20650                        _("seconds=%d is invalid, please choose value within [%d, %d]."),
20651                        seconds,
20652                        MIN_DIRTYRATE_CALC_PERIOD,
20653                        MAX_DIRTYRATE_CALC_PERIOD);
20654         return -1;
20655     }
20656 
20657     if (!(vm = qemuDomainObjFromDomain(dom)))
20658         return -1;
20659 
20660     if (virDomainStartDirtyRateCalcEnsureACL(dom->conn, vm->def) < 0)
20661         goto cleanup;
20662 
20663     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20664         goto cleanup;
20665 
20666     if (!virDomainObjIsActive(vm)) {
20667         virReportError(VIR_ERR_OPERATION_INVALID,
20668                        "%s", _("domain is not running"));
20669         goto endjob;
20670     }
20671 
20672     VIR_DEBUG("Calculate dirty rate in next %d seconds", seconds);
20673 
20674     priv = vm->privateData;
20675     qemuDomainObjEnterMonitor(driver, vm);
20676     ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds);
20677 
20678     if (qemuDomainObjExitMonitor(driver, vm) < 0)
20679         ret = -1;
20680 
20681  endjob:
20682     qemuDomainObjEndJob(driver, vm);
20683 
20684  cleanup:
20685     virDomainObjEndAPI(&vm);
20686     return ret;
20687 }
20688 
20689 
20690 static virHypervisorDriver qemuHypervisorDriver = {
20691     .name = QEMU_DRIVER_NAME,
20692     .connectURIProbe = qemuConnectURIProbe,
20693     .connectOpen = qemuConnectOpen, /* 0.2.0 */
20694     .connectClose = qemuConnectClose, /* 0.2.0 */
20695     .connectSupportsFeature = qemuConnectSupportsFeature, /* 0.5.0 */
20696     .connectGetType = qemuConnectGetType, /* 0.2.0 */
20697     .connectGetVersion = qemuConnectGetVersion, /* 0.2.0 */
20698     .connectGetHostname = qemuConnectGetHostname, /* 0.3.3 */
20699     .connectGetSysinfo = qemuConnectGetSysinfo, /* 0.8.8 */
20700     .connectGetMaxVcpus = qemuConnectGetMaxVcpus, /* 0.2.1 */
20701     .nodeGetInfo = qemuNodeGetInfo, /* 0.2.0 */
20702     .connectGetCapabilities = qemuConnectGetCapabilities, /* 0.2.1 */
20703     .connectListDomains = qemuConnectListDomains, /* 0.2.0 */
20704     .connectNumOfDomains = qemuConnectNumOfDomains, /* 0.2.0 */
20705     .connectListAllDomains = qemuConnectListAllDomains, /* 0.9.13 */
20706     .domainCreateXML = qemuDomainCreateXML, /* 0.2.0 */
20707     .domainLookupByID = qemuDomainLookupByID, /* 0.2.0 */
20708     .domainLookupByUUID = qemuDomainLookupByUUID, /* 0.2.0 */
20709     .domainLookupByName = qemuDomainLookupByName, /* 0.2.0 */
20710     .domainSuspend = qemuDomainSuspend, /* 0.2.0 */
20711     .domainResume = qemuDomainResume, /* 0.2.0 */
20712     .domainShutdown = qemuDomainShutdown, /* 0.2.0 */
20713     .domainShutdownFlags = qemuDomainShutdownFlags, /* 0.9.10 */
20714     .domainReboot = qemuDomainReboot, /* 0.9.3 */
20715     .domainReset = qemuDomainReset, /* 0.9.7 */
20716     .domainDestroy = qemuDomainDestroy, /* 0.2.0 */
20717     .domainDestroyFlags = qemuDomainDestroyFlags, /* 0.9.4 */
20718     .domainGetOSType = qemuDomainGetOSType, /* 0.2.2 */
20719     .domainGetMaxMemory = qemuDomainGetMaxMemory, /* 0.4.2 */
20720     .domainSetMaxMemory = qemuDomainSetMaxMemory, /* 0.4.2 */
20721     .domainSetMemory = qemuDomainSetMemory, /* 0.4.2 */
20722     .domainSetMemoryFlags = qemuDomainSetMemoryFlags, /* 0.9.0 */
20723     .domainSetMemoryParameters = qemuDomainSetMemoryParameters, /* 0.8.5 */
20724     .domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
20725     .domainSetMemoryStatsPeriod = qemuDomainSetMemoryStatsPeriod, /* 1.1.1 */
20726     .domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
20727     .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
20728     .domainGetInfo = qemuDomainGetInfo, /* 0.2.0 */
20729     .domainGetState = qemuDomainGetState, /* 0.9.2 */
20730     .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
20731     .domainSave = qemuDomainSave, /* 0.2.0 */
20732     .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
20733     .domainRestore = qemuDomainRestore, /* 0.2.0 */
20734     .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
20735     .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
20736     .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
20737     .domainCoreDump = qemuDomainCoreDump, /* 0.7.0 */
20738     .domainCoreDumpWithFormat = qemuDomainCoreDumpWithFormat, /* 1.2.3 */
20739     .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
20740     .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
20741     .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */
20742     .domainGetVcpusFlags = qemuDomainGetVcpusFlags, /* 0.8.5 */
20743     .domainPinVcpu = qemuDomainPinVcpu, /* 0.4.4 */
20744     .domainPinVcpuFlags = qemuDomainPinVcpuFlags, /* 0.9.3 */
20745     .domainGetVcpuPinInfo = qemuDomainGetVcpuPinInfo, /* 0.9.3 */
20746     .domainPinEmulator = qemuDomainPinEmulator, /* 0.10.0 */
20747     .domainGetEmulatorPinInfo = qemuDomainGetEmulatorPinInfo, /* 0.10.0 */
20748     .domainGetVcpus = qemuDomainGetVcpus, /* 0.4.4 */
20749     .domainGetMaxVcpus = qemuDomainGetMaxVcpus, /* 0.4.4 */
20750     .domainGetIOThreadInfo = qemuDomainGetIOThreadInfo, /* 1.2.14 */
20751     .domainPinIOThread = qemuDomainPinIOThread, /* 1.2.14 */
20752     .domainAddIOThread = qemuDomainAddIOThread, /* 1.2.15 */
20753     .domainDelIOThread = qemuDomainDelIOThread, /* 1.2.15 */
20754     .domainSetIOThreadParams = qemuDomainSetIOThreadParams, /* 4.10.0 */
20755     .domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
20756     .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
20757     .nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
20758     .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
20759     .connectDomainXMLFromNative = NULL, /* 0.6.4 - 5.5.0 */
20760     .connectDomainXMLToNative = qemuConnectDomainXMLToNative, /* 0.6.4 */
20761     .connectListDefinedDomains = qemuConnectListDefinedDomains, /* 0.2.0 */
20762     .connectNumOfDefinedDomains = qemuConnectNumOfDefinedDomains, /* 0.2.0 */
20763     .domainCreate = qemuDomainCreate, /* 0.2.0 */
20764     .domainCreateWithFlags = qemuDomainCreateWithFlags, /* 0.8.2 */
20765     .domainDefineXML = qemuDomainDefineXML, /* 0.2.0 */
20766     .domainDefineXMLFlags = qemuDomainDefineXMLFlags, /* 1.2.12 */
20767     .domainUndefine = qemuDomainUndefine, /* 0.2.0 */
20768     .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */
20769     .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */
20770     .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */
20771     .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */
20772     .domainDetachDeviceFlags = qemuDomainDetachDeviceFlags, /* 0.7.7 */
20773     .domainUpdateDeviceFlags = qemuDomainUpdateDeviceFlags, /* 0.8.0 */
20774     .domainDetachDeviceAlias = qemuDomainDetachDeviceAlias, /* 4.4.0 */
20775     .domainGetAutostart = qemuDomainGetAutostart, /* 0.2.1 */
20776     .domainSetAutostart = qemuDomainSetAutostart, /* 0.2.1 */
20777     .domainGetSchedulerType = qemuDomainGetSchedulerType, /* 0.7.0 */
20778     .domainGetSchedulerParameters = qemuDomainGetSchedulerParameters, /* 0.7.0 */
20779     .domainGetSchedulerParametersFlags = qemuDomainGetSchedulerParametersFlags, /* 0.9.2 */
20780     .domainSetSchedulerParameters = qemuDomainSetSchedulerParameters, /* 0.7.0 */
20781     .domainSetSchedulerParametersFlags = qemuDomainSetSchedulerParametersFlags, /* 0.9.2 */
20782     .domainMigratePerform = qemuDomainMigratePerform, /* 0.5.0 */
20783     .domainBlockResize = qemuDomainBlockResize, /* 0.9.8 */
20784     .domainBlockStats = qemuDomainBlockStats, /* 0.4.1 */
20785     .domainBlockStatsFlags = qemuDomainBlockStatsFlags, /* 0.9.5 */
20786     .domainInterfaceStats = qemuDomainInterfaceStats, /* 0.4.1 */
20787     .domainMemoryStats = qemuDomainMemoryStats, /* 0.7.5 */
20788     .domainBlockPeek = qemuDomainBlockPeek, /* 0.4.4 */
20789     .domainMemoryPeek = qemuDomainMemoryPeek, /* 0.4.4 */
20790     .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
20791     .nodeGetCPUStats = qemuNodeGetCPUStats, /* 0.9.3 */
20792     .nodeGetMemoryStats = qemuNodeGetMemoryStats, /* 0.9.3 */
20793     .nodeGetCellsFreeMemory = qemuNodeGetCellsFreeMemory, /* 0.4.4 */
20794     .nodeGetFreeMemory = qemuNodeGetFreeMemory, /* 0.4.4 */
20795     .connectDomainEventRegister = qemuConnectDomainEventRegister, /* 0.5.0 */
20796     .connectDomainEventDeregister = qemuConnectDomainEventDeregister, /* 0.5.0 */
20797     .domainMigratePrepare2 = qemuDomainMigratePrepare2, /* 0.5.0 */
20798     .domainMigrateFinish2 = qemuDomainMigrateFinish2, /* 0.5.0 */
20799     .nodeDeviceDettach = qemuNodeDeviceDettach, /* 0.6.1 */
20800     .nodeDeviceDetachFlags = qemuNodeDeviceDetachFlags, /* 1.0.5 */
20801     .nodeDeviceReAttach = qemuNodeDeviceReAttach, /* 0.6.1 */
20802     .nodeDeviceReset = qemuNodeDeviceReset, /* 0.6.1 */
20803     .domainMigratePrepareTunnel = qemuDomainMigratePrepareTunnel, /* 0.7.2 */
20804     .connectIsEncrypted = qemuConnectIsEncrypted, /* 0.7.3 */
20805     .connectIsSecure = qemuConnectIsSecure, /* 0.7.3 */
20806     .domainIsActive = qemuDomainIsActive, /* 0.7.3 */
20807     .domainIsPersistent = qemuDomainIsPersistent, /* 0.7.3 */
20808     .domainIsUpdated = qemuDomainIsUpdated, /* 0.8.6 */
20809     .connectCompareCPU = qemuConnectCompareCPU, /* 0.7.5 */
20810     .connectBaselineCPU = qemuConnectBaselineCPU, /* 0.7.7 */
20811     .domainGetJobInfo = qemuDomainGetJobInfo, /* 0.7.7 */
20812     .domainGetJobStats = qemuDomainGetJobStats, /* 1.0.3 */
20813     .domainAbortJob = qemuDomainAbortJob, /* 0.7.7 */
20814     .domainMigrateGetMaxDowntime = qemuDomainMigrateGetMaxDowntime, /* 3.7.0 */
20815     .domainMigrateSetMaxDowntime = qemuDomainMigrateSetMaxDowntime, /* 0.8.0 */
20816     .domainMigrateGetCompressionCache = qemuDomainMigrateGetCompressionCache, /* 1.0.3 */
20817     .domainMigrateSetCompressionCache = qemuDomainMigrateSetCompressionCache, /* 1.0.3 */
20818     .domainMigrateSetMaxSpeed = qemuDomainMigrateSetMaxSpeed, /* 0.9.0 */
20819     .domainMigrateGetMaxSpeed = qemuDomainMigrateGetMaxSpeed, /* 0.9.5 */
20820     .connectDomainEventRegisterAny = qemuConnectDomainEventRegisterAny, /* 0.8.0 */
20821     .connectDomainEventDeregisterAny = qemuConnectDomainEventDeregisterAny, /* 0.8.0 */
20822     .domainManagedSave = qemuDomainManagedSave, /* 0.8.0 */
20823     .domainHasManagedSaveImage = qemuDomainHasManagedSaveImage, /* 0.8.0 */
20824     .domainManagedSaveRemove = qemuDomainManagedSaveRemove, /* 0.8.0 */
20825     .domainManagedSaveGetXMLDesc = qemuDomainManagedSaveGetXMLDesc, /* 3.7.0 */
20826     .domainManagedSaveDefineXML = qemuDomainManagedSaveDefineXML, /* 3.7.0 */
20827     .domainSnapshotCreateXML = qemuDomainSnapshotCreateXML, /* 0.8.0 */
20828     .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */
20829     .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */
20830     .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */
20831     .domainListAllSnapshots = qemuDomainListAllSnapshots, /* 0.9.13 */
20832     .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
20833     .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
20834     .domainSnapshotListAllChildren = qemuDomainSnapshotListAllChildren, /* 0.9.13 */
20835     .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
20836     .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
20837     .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */
20838     .domainSnapshotCurrent = qemuDomainSnapshotCurrent, /* 0.8.0 */
20839     .domainSnapshotIsCurrent = qemuDomainSnapshotIsCurrent, /* 0.9.13 */
20840     .domainSnapshotHasMetadata = qemuDomainSnapshotHasMetadata, /* 0.9.13 */
20841     .domainRevertToSnapshot = qemuDomainRevertToSnapshot, /* 0.8.0 */
20842     .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
20843     .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
20844     .domainQemuAttach = NULL, /* 0.9.4 - 5.5.0 */
20845     .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
20846     .connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
20847     .connectDomainQemuMonitorEventDeregister = qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
20848     .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
20849     .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
20850     .domainOpenGraphicsFD = qemuDomainOpenGraphicsFD, /* 1.2.8 */
20851     .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
20852     .domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
20853     .domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
20854     .domainMigratePrepareTunnel3 = qemuDomainMigratePrepareTunnel3, /* 0.9.2 */
20855     .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
20856     .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
20857     .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
20858     .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
20859     .domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.3 */
20860     .domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.3 */
20861     .domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
20862     .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
20863     .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
20864     .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
20865     .domainBlockRebase = qemuDomainBlockRebase, /* 0.9.10 */
20866     .domainBlockCopy = qemuDomainBlockCopy, /* 1.2.9 */
20867     .domainBlockCommit = qemuDomainBlockCommit, /* 1.0.0 */
20868     .connectIsAlive = qemuConnectIsAlive, /* 0.9.8 */
20869     .nodeSuspendForDuration = qemuNodeSuspendForDuration, /* 0.9.8 */
20870     .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
20871     .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
20872     .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
20873     .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
20874     .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
20875     .domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
20876     .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
20877     .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */
20878     .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */
20879     .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
20880     .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
20881     .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
20882     .nodeGetMemoryParameters = qemuNodeGetMemoryParameters, /* 0.10.2 */
20883     .nodeSetMemoryParameters = qemuNodeSetMemoryParameters, /* 0.10.2 */
20884     .nodeGetCPUMap = qemuNodeGetCPUMap, /* 1.0.0 */
20885     .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */
20886     .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */
20887     .domainMigrateBegin3Params = qemuDomainMigrateBegin3Params, /* 1.1.0 */
20888     .domainMigratePrepare3Params = qemuDomainMigratePrepare3Params, /* 1.1.0 */
20889     .domainMigratePrepareTunnel3Params = qemuDomainMigratePrepareTunnel3Params, /* 1.1.0 */
20890     .domainMigratePerform3Params = qemuDomainMigratePerform3Params, /* 1.1.0 */
20891     .domainMigrateFinish3Params = qemuDomainMigrateFinish3Params, /* 1.1.0 */
20892     .domainMigrateConfirm3Params = qemuDomainMigrateConfirm3Params, /* 1.1.0 */
20893     .connectGetCPUModelNames = qemuConnectGetCPUModelNames, /* 1.1.3 */
20894     .domainFSFreeze = qemuDomainFSFreeze, /* 1.2.5 */
20895     .domainFSThaw = qemuDomainFSThaw, /* 1.2.5 */
20896     .domainGetHostname = qemuDomainGetHostname, /* 4.8.0 */
20897     .domainGetTime = qemuDomainGetTime, /* 1.2.5 */
20898     .domainSetTime = qemuDomainSetTime, /* 1.2.5 */
20899     .nodeGetFreePages = qemuNodeGetFreePages, /* 1.2.6 */
20900     .connectGetDomainCapabilities = qemuConnectGetDomainCapabilities, /* 1.2.7 */
20901     .connectGetAllDomainStats = qemuConnectGetAllDomainStats, /* 1.2.8 */
20902     .nodeAllocPages = qemuNodeAllocPages, /* 1.2.9 */
20903     .domainGetFSInfo = qemuDomainGetFSInfo, /* 1.2.11 */
20904     .domainInterfaceAddresses = qemuDomainInterfaceAddresses, /* 1.2.14 */
20905     .domainSetUserPassword = qemuDomainSetUserPassword, /* 1.2.16 */
20906     .domainRename = qemuDomainRename, /* 1.2.19 */
20907     .domainMigrateStartPostCopy = qemuDomainMigrateStartPostCopy, /* 1.3.3 */
20908     .domainGetGuestVcpus = qemuDomainGetGuestVcpus, /* 2.0.0 */
20909     .domainSetGuestVcpus = qemuDomainSetGuestVcpus, /* 2.0.0 */
20910     .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
20911     .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
20912     .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
20913     .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
20914     .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */
20915     .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
20916     .domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
20917     .domainCheckpointCreateXML = qemuDomainCheckpointCreateXML, /* 5.6.0 */
20918     .domainCheckpointGetXMLDesc = qemuDomainCheckpointGetXMLDesc, /* 5.6.0 */
20919 
20920     .domainListAllCheckpoints = qemuDomainListAllCheckpoints, /* 5.6.0 */
20921     .domainCheckpointListAllChildren = qemuDomainCheckpointListAllChildren, /* 5.6.0 */
20922     .domainCheckpointLookupByName = qemuDomainCheckpointLookupByName, /* 5.6.0 */
20923     .domainCheckpointGetParent = qemuDomainCheckpointGetParent, /* 5.6.0 */
20924     .domainCheckpointDelete = qemuDomainCheckpointDelete, /* 5.6.0 */
20925     .domainGetGuestInfo = qemuDomainGetGuestInfo, /* 5.7.0 */
20926     .domainAgentSetResponseTimeout = qemuDomainAgentSetResponseTimeout, /* 5.10.0 */
20927     .domainBackupBegin = qemuDomainBackupBegin, /* 6.0.0 */
20928     .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */
20929     .domainAuthorizedSSHKeysGet = qemuDomainAuthorizedSSHKeysGet, /* 6.10.0 */
20930     .domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */
20931     .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
20932     .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
20933 };
20934 
20935 
20936 static virConnectDriver qemuConnectDriver = {
20937     .localOnly = true,
20938     .uriSchemes = (const char *[]){ "qemu", NULL },
20939     .embeddable = true,
20940     .hypervisorDriver = &qemuHypervisorDriver,
20941 };
20942 
20943 static virStateDriver qemuStateDriver = {
20944     .name = QEMU_DRIVER_NAME,
20945     .stateInitialize = qemuStateInitialize,
20946     .stateCleanup = qemuStateCleanup,
20947     .stateReload = qemuStateReload,
20948     .stateStop = qemuStateStop,
20949     .stateShutdownPrepare = qemuStateShutdownPrepare,
20950     .stateShutdownWait = qemuStateShutdownWait,
20951 };
20952 
qemuRegister(void)20953 int qemuRegister(void)
20954 {
20955     if (virRegisterConnectDriver(&qemuConnectDriver,
20956                                  true) < 0)
20957         return -1;
20958     if (virRegisterStateDriver(&qemuStateDriver) < 0)
20959         return -1;
20960     return 0;
20961 }
20962