1 /*
2  * qemu_hotplug.c: QEMU device hotplug management
3  *
4  * Copyright (C) 2006-2016 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 
23 #include <config.h>
24 
25 #include "qemu_hotplug.h"
26 #include "qemu_alias.h"
27 #include "qemu_capabilities.h"
28 #include "qemu_domain.h"
29 #include "qemu_domain_address.h"
30 #include "qemu_namespace.h"
31 #include "qemu_command.h"
32 #include "qemu_hostdev.h"
33 #include "qemu_interface.h"
34 #include "qemu_process.h"
35 #include "qemu_security.h"
36 #include "qemu_block.h"
37 #include "qemu_snapshot.h"
38 #include "qemu_virtiofs.h"
39 #include "domain_audit.h"
40 #include "netdev_bandwidth_conf.h"
41 #include "domain_nwfilter.h"
42 #include "virlog.h"
43 #include "datatypes.h"
44 #include "virerror.h"
45 #include "viralloc.h"
46 #include "virpci.h"
47 #include "virfile.h"
48 #include "virprocess.h"
49 #include "qemu_cgroup.h"
50 #include "locking/domain_lock.h"
51 #include "virnetdev.h"
52 #include "virnetdevbridge.h"
53 #include "virnetdevtap.h"
54 #include "virnetdevopenvswitch.h"
55 #include "virnetdevmidonet.h"
56 #include "device_conf.h"
57 #include "storage_source.h"
58 #include "storage_source_conf.h"
59 #include "virstring.h"
60 #include "virtime.h"
61 #include "virqemu.h"
62 
63 #define VIR_FROM_THIS VIR_FROM_QEMU
64 
65 VIR_LOG_INIT("qemu.qemu_hotplug");
66 
67 #define CHANGE_MEDIA_TIMEOUT 5000
68 
69 /* Timeout in milliseconds for device removal. PPC64 domains
70  * can experience a bigger delay in unplug operations during
71  * heavy guest activity (vcpu being the most notable case), thus
72  * the timeout for PPC64 is also bigger. */
73 #define QEMU_UNPLUG_TIMEOUT 1000ull * 5
74 #define QEMU_UNPLUG_TIMEOUT_PPC64 1000ull * 10
75 
76 
77 static void
78 qemuDomainResetDeviceRemoval(virDomainObj *vm);
79 
80 /**
81  * qemuDomainDeleteDevice:
82  * @vm: domain object
83  * @alias: device to remove
84  *
85  * This is a wrapper over qemuMonitorDelDevice() plus enter/exit
86  * monitor calls.  This function MUST be used instead of plain
87  * qemuMonitorDelDevice() in all places where @alias represents a
88  * device from domain XML, i.e. caller marks the device for
89  * removal and then calls qemuDomainWaitForDeviceRemoval()
90  * followed by qemuDomainRemove*Device().
91  *
92  * For collateral devices (e.g. extension devices like zPCI) it
93  * is safe to use plain qemuMonitorDelDevice().
94  *
95  * Upon entry, @vm must be locked.
96  *
97  * Returns: 0 on success,
98  *         -1 otherwise.
99  */
100 static int
qemuDomainDeleteDevice(virDomainObj * vm,const char * alias)101 qemuDomainDeleteDevice(virDomainObj *vm,
102                        const char *alias)
103 {
104     qemuDomainObjPrivate *priv = vm->privateData;
105     virQEMUDriver *driver = priv->driver;
106     int rc;
107 
108     qemuDomainObjEnterMonitor(driver, vm);
109 
110     rc = qemuMonitorDelDevice(priv->mon, alias);
111 
112     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
113         /* Domain is no longer running. No cleanup needed. */
114         return -1;
115     }
116 
117     if (rc < 0) {
118         /* Deleting device failed. Let's check if DEVICE_DELETED
119          * even arrived. If it did, we need to claim success to
120          * make the caller remove device from domain XML. */
121 
122         if (priv->unplug.eventSeen) {
123             /* The event arrived. Return success. */
124             VIR_DEBUG("Detaching of device %s failed, but event arrived", alias);
125             qemuDomainResetDeviceRemoval(vm);
126             rc = 0;
127         } else if (rc == -2) {
128             /* The device does not exist in qemu, but it still
129              * exists in libvirt. Claim success to make caller
130              * qemuDomainWaitForDeviceRemoval(). Otherwise if
131              * domain XML is queried right after detach API the
132              * device would still be there.  */
133             VIR_DEBUG("Detaching of device %s failed and no event arrived", alias);
134             rc = 0;
135         }
136     }
137 
138     return rc;
139 }
140 
141 
142 static int
qemuDomainDetachZPCIDevice(qemuMonitor * mon,virDomainDeviceInfo * info)143 qemuDomainDetachZPCIDevice(qemuMonitor *mon,
144                            virDomainDeviceInfo *info)
145 {
146     g_autofree char *zpciAlias = NULL;
147 
148     zpciAlias = g_strdup_printf("zpci%d", info->addr.pci.zpci.uid.value);
149 
150     if (qemuMonitorDelDevice(mon, zpciAlias) < 0)
151         return -1;
152 
153     return 0;
154 }
155 
156 
157 static int
qemuDomainAttachExtensionDevice(qemuMonitor * mon,virDomainDeviceInfo * info)158 qemuDomainAttachExtensionDevice(qemuMonitor *mon,
159                                 virDomainDeviceInfo *info)
160 {
161     if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
162         info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
163         return 0;
164     }
165 
166     if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
167         g_autoptr(virJSONValue) devprops = NULL;
168 
169         if (!(devprops = qemuBuildZPCIDevProps(info)))
170             return -1;
171 
172         if (qemuMonitorAddDeviceProps(mon, &devprops) < 0)
173             return -1;
174     }
175 
176     return 0;
177 }
178 
179 
180 static int
qemuDomainDetachExtensionDevice(qemuMonitor * mon,virDomainDeviceInfo * info)181 qemuDomainDetachExtensionDevice(qemuMonitor *mon,
182                                 virDomainDeviceInfo *info)
183 {
184     if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
185         info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
186         return 0;
187     }
188 
189     if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
190         return qemuDomainDetachZPCIDevice(mon, info);
191 
192     return 0;
193 }
194 
195 
196 static int
qemuHotplugChardevAttach(qemuMonitor * mon,const char * alias,virDomainChrSourceDef * def)197 qemuHotplugChardevAttach(qemuMonitor *mon,
198                          const char *alias,
199                          virDomainChrSourceDef *def)
200 {
201     return qemuMonitorAttachCharDev(mon, alias, def);
202 }
203 
204 
205 static int
qemuHotplugWaitForTrayEject(virDomainObj * vm,virDomainDiskDef * disk)206 qemuHotplugWaitForTrayEject(virDomainObj *vm,
207                             virDomainDiskDef *disk)
208 {
209     unsigned long long now;
210     int rc;
211 
212     if (virTimeMillisNow(&now) < 0)
213         return -1;
214 
215     while (disk->tray_status != VIR_DOMAIN_DISK_TRAY_OPEN) {
216         if ((rc = virDomainObjWaitUntil(vm, now + CHANGE_MEDIA_TIMEOUT)) < 0)
217             return -1;
218 
219         if (rc > 0) {
220             /* the caller called qemuMonitorEjectMedia which usually reports an
221              * error. Report the failure in an off-chance that it didn't. */
222             if (virGetLastErrorCode() == VIR_ERR_OK) {
223                 virReportError(VIR_ERR_OPERATION_FAILED,
224                                _("timed out waiting to open tray of '%s'"),
225                                disk->dst);
226             }
227             return -1;
228         }
229     }
230 
231     return 0;
232 }
233 
234 
235 /**
236  * qemuDomainChangeMediaLegacy:
237  * @driver: qemu driver structure
238  * @vm: domain definition
239  * @disk: disk definition to change the source of
240  * @newsrc: new disk source to change to
241  * @force: force the change of media
242  *
243  * Change the media in an ejectable device to the one described by
244  * @newsrc. This function also removes the old source from the
245  * shared device table if appropriate. Note that newsrc is consumed
246  * on success and the old source is freed on success.
247  *
248  * Returns 0 on success, -1 on error and reports libvirt error
249  */
250 static int
qemuDomainChangeMediaLegacy(virQEMUDriver * driver,virDomainObj * vm,virDomainDiskDef * disk,virStorageSource * newsrc,bool force)251 qemuDomainChangeMediaLegacy(virQEMUDriver *driver,
252                             virDomainObj *vm,
253                             virDomainDiskDef *disk,
254                             virStorageSource *newsrc,
255                             bool force)
256 {
257     int rc;
258     g_autofree char *driveAlias = NULL;
259     qemuDomainObjPrivate *priv = vm->privateData;
260     qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
261     const char *format = NULL;
262     g_autofree char *sourcestr = NULL;
263 
264     if (!disk->info.alias) {
265         virReportError(VIR_ERR_INTERNAL_ERROR,
266                        _("missing disk device alias name for %s"), disk->dst);
267         return -1;
268     }
269 
270     if (!(driveAlias = qemuAliasDiskDriveFromDisk(disk)))
271         return -1;
272 
273     qemuDomainObjEnterMonitor(driver, vm);
274     rc = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
275     if (qemuDomainObjExitMonitor(driver, vm) < 0)
276         return -1;
277 
278     /* If the tray is present wait for it to open. */
279     if (!force && diskPriv->tray) {
280         rc = qemuHotplugWaitForTrayEject(vm, disk);
281         if (rc < 0)
282             return -1;
283 
284         /* re-issue ejection command to pop out the media */
285         qemuDomainObjEnterMonitor(driver, vm);
286         rc = qemuMonitorEjectMedia(priv->mon, driveAlias, false);
287         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
288             return -1;
289 
290     } else  {
291         /* otherwise report possible errors from the attempt to eject the media */
292         if (rc < 0)
293             return -1;
294     }
295 
296     if (!virStorageSourceIsEmpty(newsrc)) {
297         if (qemuGetDriveSourceString(newsrc, NULL, &sourcestr) < 0)
298             return -1;
299 
300         if (virStorageSourceGetActualType(newsrc) != VIR_STORAGE_TYPE_DIR)
301             format = virStorageFileFormatTypeToString(newsrc->format);
302 
303         qemuDomainObjEnterMonitor(driver, vm);
304         rc = qemuMonitorChangeMedia(priv->mon,
305                                     driveAlias,
306                                     sourcestr,
307                                     format);
308         if (qemuDomainObjExitMonitor(driver, vm) < 0)
309             return -1;
310     }
311 
312     if (rc < 0)
313         return -1;
314 
315     return 0;
316 }
317 
318 
319 /**
320  * qemuHotplugAttachDBusVMState:
321  * @driver: QEMU driver object
322  * @vm: domain object
323  * @asyncJob: asynchronous job identifier
324  *
325  * Add -object dbus-vmstate if necessary.
326  *
327  * Returns: 0 on success, -1 on error.
328  */
329 int
qemuHotplugAttachDBusVMState(virQEMUDriver * driver,virDomainObj * vm,qemuDomainAsyncJob asyncJob)330 qemuHotplugAttachDBusVMState(virQEMUDriver *driver,
331                              virDomainObj *vm,
332                              qemuDomainAsyncJob asyncJob)
333 {
334     qemuDomainObjPrivate *priv = vm->privateData;
335     g_autoptr(virJSONValue) props = NULL;
336     int ret;
337 
338     if (priv->dbusVMState)
339         return 0;
340 
341     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
342         VIR_DEBUG("dbus-vmstate object is not supported by this QEMU binary");
343         return 0;
344     }
345 
346     if (!(props = qemuBuildDBusVMStateInfoProps(driver, vm)))
347         return -1;
348 
349     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
350         return -1;
351 
352     ret = qemuMonitorAddObject(priv->mon, &props, NULL);
353 
354     if (ret == 0)
355         priv->dbusVMState = true;
356 
357     if (qemuDomainObjExitMonitor(driver, vm) < 0)
358         return -1;
359 
360     return ret;
361 }
362 
363 
364 /**
365  * qemuHotplugRemoveDBusVMState:
366  * @driver: QEMU driver object
367  * @vm: domain object
368  * @asyncJob: asynchronous job identifier
369  *
370  * Remove -object dbus-vmstate from @vm if the configuration does not require
371  * it any more.
372  *
373  * Returns: 0 on success, -1 on error.
374  */
375 int
qemuHotplugRemoveDBusVMState(virQEMUDriver * driver,virDomainObj * vm,qemuDomainAsyncJob asyncJob)376 qemuHotplugRemoveDBusVMState(virQEMUDriver *driver,
377                              virDomainObj *vm,
378                              qemuDomainAsyncJob asyncJob)
379 {
380     qemuDomainObjPrivate *priv = vm->privateData;
381     int ret;
382 
383     if (!priv->dbusVMState)
384         return 0;
385 
386     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
387         return -1;
388 
389     ret = qemuMonitorDelObject(priv->mon, qemuDomainGetDBusVMStateAlias(), true);
390 
391     if (ret == 0)
392         priv->dbusVMState = false;
393 
394     if (qemuDomainObjExitMonitor(driver, vm) < 0)
395         return -1;
396 
397     return ret;
398 }
399 
400 
401 /**
402  * qemuHotplugAttachManagedPR:
403  * @driver: QEMU driver object
404  * @vm: domain object
405  * @src: new disk source to be attached to @vm
406  * @asyncJob: asynchronous job identifier
407  *
408  * Checks if it's needed to start qemu-pr-helper and add the corresponding
409  * pr-manager-helper object.
410  *
411  * Returns: 0 on success, -1 on error.
412  */
413 static int
qemuHotplugAttachManagedPR(virQEMUDriver * driver,virDomainObj * vm,virStorageSource * src,qemuDomainAsyncJob asyncJob)414 qemuHotplugAttachManagedPR(virQEMUDriver *driver,
415                            virDomainObj *vm,
416                            virStorageSource *src,
417                            qemuDomainAsyncJob asyncJob)
418 {
419     qemuDomainObjPrivate *priv = vm->privateData;
420     virJSONValue *props = NULL;
421     bool daemonStarted = false;
422     int ret = -1;
423     int rc;
424 
425     if (priv->prDaemonRunning ||
426         !virStorageSourceChainHasManagedPR(src))
427         return 0;
428 
429     if (!(props = qemuBuildPRManagedManagerInfoProps(priv)))
430         return -1;
431 
432     if (qemuProcessStartManagedPRDaemon(vm) < 0)
433         goto cleanup;
434 
435     daemonStarted = true;
436 
437     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
438         goto cleanup;
439 
440     rc = qemuMonitorAddObject(priv->mon, &props, NULL);
441 
442     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
443         goto cleanup;
444 
445     ret = 0;
446 
447  cleanup:
448     if (ret < 0 && daemonStarted)
449         qemuProcessKillManagedPRDaemon(vm);
450     virJSONValueFree(props);
451     return ret;
452 }
453 
454 
455 /**
456  * qemuHotplugRemoveManagedPR:
457  * @driver: QEMU driver object
458  * @vm: domain object
459  * @asyncJob: asynchronous job identifier
460  *
461  * Removes the managed PR object from @vm if the configuration does not require
462  * it any more.
463  */
464 static int
qemuHotplugRemoveManagedPR(virQEMUDriver * driver,virDomainObj * vm,qemuDomainAsyncJob asyncJob)465 qemuHotplugRemoveManagedPR(virQEMUDriver *driver,
466                            virDomainObj *vm,
467                            qemuDomainAsyncJob asyncJob)
468 {
469     qemuDomainObjPrivate *priv = vm->privateData;
470     virErrorPtr orig_err;
471     int ret = -1;
472 
473     if (qemuDomainDefHasManagedPR(vm))
474         return 0;
475 
476     virErrorPreserveLast(&orig_err);
477 
478     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
479         goto cleanup;
480     ignore_value(qemuMonitorDelObject(priv->mon, qemuDomainGetManagedPRAlias(),
481                                       false));
482     if (qemuDomainObjExitMonitor(driver, vm) < 0)
483         goto cleanup;
484 
485     qemuProcessKillManagedPRDaemon(vm);
486 
487     ret = 0;
488  cleanup:
489     virErrorRestore(&orig_err);
490     return ret;
491 }
492 
493 
494 /**
495  * qemuDomainChangeMediaBlockdev:
496  * @driver: qemu driver structure
497  * @vm: domain definition
498  * @disk: disk definition to change the source of
499  * @oldsrc: old source definition
500  * @newsrc: new disk source to change to
501  * @force: force the change of media
502  *
503  * Change the media in an ejectable device to the one described by
504  * @newsrc. This function also removes the old source from the
505  * shared device table if appropriate. Note that newsrc is consumed
506  * on success and the old source is freed on success.
507  *
508  * Returns 0 on success, -1 on error and reports libvirt error
509  */
510 static int
qemuDomainChangeMediaBlockdev(virQEMUDriver * driver,virDomainObj * vm,virDomainDiskDef * disk,virStorageSource * oldsrc,virStorageSource * newsrc,bool force)511 qemuDomainChangeMediaBlockdev(virQEMUDriver *driver,
512                               virDomainObj *vm,
513                               virDomainDiskDef *disk,
514                               virStorageSource *oldsrc,
515                               virStorageSource *newsrc,
516                               bool force)
517 {
518     qemuDomainObjPrivate *priv = vm->privateData;
519     qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
520     g_autoptr(qemuBlockStorageSourceChainData) newbackend = NULL;
521     g_autoptr(qemuBlockStorageSourceChainData) oldbackend = NULL;
522     g_autofree char *nodename = NULL;
523     int rc;
524 
525     if (!virStorageSourceIsEmpty(oldsrc) &&
526         !(oldbackend = qemuBlockStorageSourceChainDetachPrepareBlockdev(oldsrc)))
527         return -1;
528 
529     if (!virStorageSourceIsEmpty(newsrc)) {
530         if (!(newbackend = qemuBuildStorageSourceChainAttachPrepareBlockdev(newsrc)))
531             return -1;
532 
533         if (qemuDomainDiskGetBackendAlias(disk, priv->qemuCaps, &nodename) < 0)
534             return -1;
535     }
536 
537     if (diskPriv->tray && disk->tray_status != VIR_DOMAIN_DISK_TRAY_OPEN) {
538         qemuDomainObjEnterMonitor(driver, vm);
539         rc = qemuMonitorBlockdevTrayOpen(priv->mon, diskPriv->qomName, force);
540         if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
541             return -1;
542 
543         if (!force && qemuHotplugWaitForTrayEject(vm, disk) < 0)
544             return -1;
545     }
546 
547     qemuDomainObjEnterMonitor(driver, vm);
548 
549     rc = qemuMonitorBlockdevMediumRemove(priv->mon, diskPriv->qomName);
550 
551     if (rc == 0 && oldbackend)
552         qemuBlockStorageSourceChainDetach(priv->mon, oldbackend);
553 
554     if (newbackend && nodename) {
555         if (rc == 0)
556             rc = qemuBlockStorageSourceChainAttach(priv->mon, newbackend);
557 
558         if (rc == 0)
559             rc = qemuMonitorBlockdevMediumInsert(priv->mon, diskPriv->qomName,
560                                                  nodename);
561     }
562 
563     /* set throttling for the new image */
564     if (rc == 0 &&
565         !virStorageSourceIsEmpty(newsrc) &&
566         qemuDiskConfigBlkdeviotuneEnabled(disk)) {
567         rc = qemuMonitorSetBlockIoThrottle(priv->mon, NULL,
568                                            diskPriv->qomName,
569                                            &disk->blkdeviotune);
570     }
571 
572     if (rc == 0)
573         rc = qemuMonitorBlockdevTrayClose(priv->mon, diskPriv->qomName);
574 
575     if (rc < 0 && newbackend)
576         qemuBlockStorageSourceChainDetach(priv->mon, newbackend);
577 
578     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
579         return -1;
580 
581     return 0;
582 }
583 
584 
585 /**
586  * qemuDomainChangeEjectableMedia:
587  * @driver: qemu driver structure
588  * @vm: domain definition
589  * @disk: disk definition to change the source of
590  * @newsrc: new disk source to change to
591  * @force: force the change of media
592  *
593  * Change the media in an ejectable device to the one described by
594  * @newsrc. This function also removes the old source from the
595  * shared device table if appropriate. Note that newsrc is consumed
596  * on success and the old source is freed on success.
597  *
598  * Returns 0 on success, -1 on error and reports libvirt error
599  */
600 int
qemuDomainChangeEjectableMedia(virQEMUDriver * driver,virDomainObj * vm,virDomainDiskDef * disk,virStorageSource * newsrc,bool force)601 qemuDomainChangeEjectableMedia(virQEMUDriver *driver,
602                                virDomainObj *vm,
603                                virDomainDiskDef *disk,
604                                virStorageSource *newsrc,
605                                bool force)
606 {
607     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
608     qemuDomainObjPrivate *priv = vm->privateData;
609     virStorageSource *oldsrc = disk->src;
610     qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
611     bool sharedAdded = false;
612     bool managedpr = virStorageSourceChainHasManagedPR(oldsrc) ||
613                      virStorageSourceChainHasManagedPR(newsrc);
614     int ret = -1;
615     int rc;
616 
617     if (diskPriv->blockjob && qemuBlockJobIsRunning(diskPriv->blockjob)) {
618         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
619                        _("can't change media while a block job is running on the device"));
620         return -1;
621     }
622 
623     disk->src = newsrc;
624 
625     if (virDomainDiskTranslateSourcePool(disk) < 0)
626         goto cleanup;
627 
628     if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
629         goto cleanup;
630 
631     sharedAdded = true;
632 
633     if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0)
634         goto cleanup;
635 
636     if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
637         goto cleanup;
638 
639     if (qemuDomainStorageSourceChainAccessAllow(driver, vm, newsrc) < 0)
640         goto cleanup;
641 
642     if (qemuHotplugAttachManagedPR(driver, vm, newsrc, QEMU_ASYNC_JOB_NONE) < 0)
643         goto cleanup;
644 
645     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV))
646         rc = qemuDomainChangeMediaBlockdev(driver, vm, disk, oldsrc, newsrc, force);
647     else
648         rc = qemuDomainChangeMediaLegacy(driver, vm, disk, newsrc, force);
649 
650     virDomainAuditDisk(vm, oldsrc, newsrc, "update", rc >= 0);
651 
652     if (rc < 0)
653         goto cleanup;
654 
655     /* remove the old source from shared device list */
656     disk->src = oldsrc;
657     ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
658     ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, oldsrc));
659 
660     /* media was changed, so we can remove the old media definition now */
661     virObjectUnref(oldsrc);
662     oldsrc = NULL;
663     disk->src = newsrc;
664 
665     ret = 0;
666 
667  cleanup:
668     /* undo changes to the new disk */
669     if (ret < 0) {
670         if (sharedAdded)
671             ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
672 
673         ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, newsrc));
674     }
675 
676     /* remove PR manager object if unneeded */
677     if (managedpr)
678         ignore_value(qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE));
679 
680     /* revert old image do the disk definition */
681     if (oldsrc)
682         disk->src = oldsrc;
683 
684     return ret;
685 }
686 
687 
688 static qemuSnapshotDiskContext *
qemuDomainAttachDiskGenericTransient(virDomainObj * vm,virDomainDiskDef * disk,GHashTable * blockNamedNodeData,qemuDomainAsyncJob asyncJob)689 qemuDomainAttachDiskGenericTransient(virDomainObj *vm,
690                                      virDomainDiskDef *disk,
691                                      GHashTable *blockNamedNodeData,
692                                      qemuDomainAsyncJob asyncJob)
693 {
694     g_autoptr(qemuSnapshotDiskContext) snapctxt = NULL;
695     g_autoptr(virDomainSnapshotDiskDef) snapdiskdef = NULL;
696 
697     if (!(snapdiskdef = qemuSnapshotGetTransientDiskDef(disk, vm->def->name)))
698         return NULL;
699 
700     snapctxt = qemuSnapshotDiskContextNew(1, vm, asyncJob);
701 
702     if (qemuSnapshotDiskPrepareOne(snapctxt, disk, snapdiskdef,
703                                    blockNamedNodeData, false, false) < 0)
704         return NULL;
705 
706     return g_steal_pointer(&snapctxt);
707 }
708 
709 
710 /**
711  * qemuDomainAttachDiskGeneric:
712  *
713  * Attaches disk to a VM. This function aggregates common code for all bus types.
714  * In cases when the VM crashed while adding the disk, -2 is returned. */
715 int
qemuDomainAttachDiskGeneric(virQEMUDriver * driver,virDomainObj * vm,virDomainDiskDef * disk,qemuDomainAsyncJob asyncJob)716 qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
717                             virDomainObj *vm,
718                             virDomainDiskDef *disk,
719                             qemuDomainAsyncJob asyncJob)
720 {
721     g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
722     qemuDomainObjPrivate *priv = vm->privateData;
723     g_autoptr(virJSONValue) devprops = NULL;
724     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
725     bool extensionDeviceAttached = false;
726     int rc;
727     g_autoptr(qemuSnapshotDiskContext) transientDiskSnapshotCtxt = NULL;
728     bool origReadonly = disk->src->readonly;
729 
730     if (disk->transient)
731         disk->src->readonly = true;
732 
733     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
734         if (!(data = qemuBuildStorageSourceChainAttachPrepareChardev(disk)))
735             return -1;
736     } else if (blockdev) {
737         if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->src)))
738             return -1;
739 
740         if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON) {
741             if (!(data->copyOnReadProps = qemuBlockStorageGetCopyOnReadProps(disk)))
742                 return -1;
743 
744             data->copyOnReadNodename = g_strdup(QEMU_DOMAIN_DISK_PRIVATE(disk)->nodeCopyOnRead);
745         }
746 
747     } else {
748         if (!(data = qemuBuildStorageSourceChainAttachPrepareDrive(disk,
749                                                                    priv->qemuCaps)))
750             return -1;
751     }
752 
753     disk->src->readonly = origReadonly;
754 
755     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
756         return -1;
757 
758     rc = qemuBlockStorageSourceChainAttach(priv->mon, data);
759 
760     if (qemuDomainObjExitMonitor(driver, vm) < 0)
761         return -2;
762 
763     if (rc < 0)
764         goto rollback;
765 
766     if (disk->transient) {
767         g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL;
768         g_autoptr(GHashTable) blockNamedNodeData = NULL;
769 
770         if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob)))
771             goto rollback;
772 
773         if (!(transientDiskSnapshotCtxt = qemuDomainAttachDiskGenericTransient(vm, disk, blockNamedNodeData, asyncJob)))
774             goto rollback;
775 
776 
777         if (qemuSnapshotDiskCreate(transientDiskSnapshotCtxt) < 0)
778             goto rollback;
779 
780         QEMU_DOMAIN_DISK_PRIVATE(disk)->transientOverlayCreated = true;
781         backend = qemuBlockStorageSourceDetachPrepare(disk->src, NULL);
782         ignore_value(VIR_INSERT_ELEMENT(data->srcdata, 0, data->nsrcdata, backend));
783     }
784 
785     if (!(devprops = qemuBuildDiskDeviceProps(vm->def, disk, priv->qemuCaps)))
786         goto rollback;
787 
788     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
789         goto rollback;
790 
791     if ((rc = qemuDomainAttachExtensionDevice(priv->mon, &disk->info)) == 0)
792         extensionDeviceAttached = true;
793 
794     if (rc == 0)
795         rc = qemuMonitorAddDeviceProps(priv->mon, &devprops);
796 
797     /* Setup throttling of disk via block_set_io_throttle QMP command. This
798      * is a hack until the 'throttle' blockdev driver will support modification
799      * of the trhottle group. See also qemuProcessSetupDiskThrottlingBlockdev.
800      * As there isn't anything sane to do if this fails, let's just return
801      * success.
802      */
803     if (blockdev && rc == 0 &&
804         qemuDiskConfigBlkdeviotuneEnabled(disk)) {
805         qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
806         if (qemuMonitorSetBlockIoThrottle(priv->mon, NULL, diskPriv->qomName,
807                                           &disk->blkdeviotune) < 0)
808             VIR_WARN("failed to set blkdeviotune for '%s' of '%s'", disk->dst, vm->def->name);
809     }
810 
811     if (qemuDomainObjExitMonitor(driver, vm) < 0)
812         return -2;
813 
814     if (rc < 0)
815         goto rollback;
816 
817     return 0;
818 
819  rollback:
820     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
821         return -1;
822 
823     if (extensionDeviceAttached)
824         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info));
825 
826     qemuBlockStorageSourceChainDetach(priv->mon, data);
827 
828     if (qemuDomainObjExitMonitor(driver, vm) < 0)
829         return -2;
830 
831     return -1;
832 }
833 
834 
qemuDomainAttachControllerDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainControllerDef * controller)835 int qemuDomainAttachControllerDevice(virQEMUDriver *driver,
836                                      virDomainObj *vm,
837                                      virDomainControllerDef *controller)
838 {
839     int ret = -1;
840     const char* type = virDomainControllerTypeToString(controller->type);
841     g_autoptr(virJSONValue) devprops = NULL;
842     qemuDomainObjPrivate *priv = vm->privateData;
843     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CONTROLLER,
844                                { .controller = controller } };
845     bool releaseaddr = false;
846 
847     if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
848         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
849                        _("'%s' controller cannot be hot plugged."),
850                        virDomainControllerTypeToString(controller->type));
851         return -1;
852     }
853 
854     /* default idx would normally be set by virDomainDefPostParse(),
855      * which isn't called in the case of live attach of a single
856      * device.
857      */
858     if (controller->idx == -1)
859        controller->idx = virDomainControllerFindUnusedIndex(vm->def,
860                                                             controller->type);
861 
862     if (virDomainControllerFind(vm->def, controller->type, controller->idx) >= 0) {
863         virReportError(VIR_ERR_OPERATION_FAILED,
864                        _("target %s:%d already exists"),
865                        type, controller->idx);
866         return -1;
867     }
868 
869     if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
870         return -1;
871 
872     qemuAssignDeviceControllerAlias(vm->def, controller);
873 
874     if (qemuBuildControllerDevProps(vm->def, controller, priv->qemuCaps, &devprops) < 0)
875         goto cleanup;
876 
877     if (!devprops)
878         goto cleanup;
879 
880     VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1);
881 
882     qemuDomainObjEnterMonitor(driver, vm);
883 
884     if ((ret = qemuDomainAttachExtensionDevice(priv->mon,
885                                                &controller->info)) < 0) {
886         goto exit_monitor;
887     }
888 
889     if ((ret = qemuMonitorAddDeviceProps(priv->mon, &devprops)) < 0)
890         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &controller->info));
891 
892  exit_monitor:
893     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
894         releaseaddr = false;
895         ret = -1;
896         goto cleanup;
897     }
898 
899     if (ret == 0)
900         virDomainControllerInsertPreAlloced(vm->def, controller);
901 
902  cleanup:
903     if (ret != 0 && releaseaddr)
904         qemuDomainReleaseDeviceAddress(vm, &controller->info);
905 
906     return ret;
907 }
908 
909 static virDomainControllerDef *
qemuDomainFindOrCreateSCSIDiskController(virQEMUDriver * driver,virDomainObj * vm,int controller)910 qemuDomainFindOrCreateSCSIDiskController(virQEMUDriver *driver,
911                                          virDomainObj *vm,
912                                          int controller)
913 {
914     size_t i;
915     virDomainControllerDef *cont;
916     qemuDomainObjPrivate *priv = vm->privateData;
917     int model = -1;
918 
919     for (i = 0; i < vm->def->ncontrollers; i++) {
920         cont = vm->def->controllers[i];
921 
922         if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
923             continue;
924 
925         if (cont->idx == controller)
926             return cont;
927 
928         /* Because virDomainHostdevAssignAddress called during
929          * virDomainHostdevDefPostParse cannot add a new controller
930          * it will assign a controller index to a controller that doesn't
931          * exist leaving this code to perform the magic of adding the
932          * controller. Because that code would be attempting to add a
933          * SCSI disk to an existing controller, let's save the model
934          * of the "last" SCSI controller we find so that if we end up
935          * creating a controller below it uses the same controller model. */
936         model = cont->model;
937     }
938 
939     /* No SCSI controller present, for backward compatibility we
940      * now hotplug a controller */
941     cont = g_new0(virDomainControllerDef, 1);
942     cont->type = VIR_DOMAIN_CONTROLLER_TYPE_SCSI;
943     cont->idx = controller;
944     if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT)
945         cont->model = qemuDomainGetSCSIControllerModel(vm->def, cont, priv->qemuCaps);
946     else
947         cont->model = model;
948 
949     VIR_INFO("No SCSI controller present, hotplugging one model=%s",
950              virDomainControllerModelSCSITypeToString(cont->model));
951     if (qemuDomainAttachControllerDevice(driver, vm, cont) < 0) {
952         VIR_FREE(cont);
953         return NULL;
954     }
955 
956     if (!virDomainObjIsActive(vm)) {
957         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
958                        _("guest unexpectedly quit"));
959         /* cont doesn't need freeing here, since the reference
960          * now held in def->controllers */
961         return NULL;
962     }
963 
964     return cont;
965 }
966 
967 
968 static int
qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver * driver,virDomainObj * vm,virDomainDeviceDef * dev)969 qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver *driver,
970                                        virDomainObj *vm,
971                                        virDomainDeviceDef *dev)
972 {
973     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
974     qemuDomainObjPrivate *priv = vm->privateData;
975     size_t i;
976     virDomainDiskDef *disk = dev->data.disk;
977     bool releaseUSB = false;
978     bool releaseVirtio = false;
979     bool releaseSeclabel = false;
980     int ret = -1;
981 
982     if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
983         disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
984         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
985                        _("cdrom/floppy device hotplug isn't supported"));
986         return -1;
987     }
988 
989     if (virDomainDiskTranslateSourcePool(disk) < 0)
990         goto cleanup;
991 
992     if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
993         goto cleanup;
994 
995     if (qemuSetUnprivSGIO(dev) < 0)
996         goto cleanup;
997 
998     if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0)
999         goto cleanup;
1000 
1001     for (i = 0; i < vm->def->ndisks; i++) {
1002         if (virDomainDiskDefCheckDuplicateInfo(vm->def->disks[i], disk) < 0)
1003             goto cleanup;
1004     }
1005 
1006     switch ((virDomainDiskBus) disk->bus) {
1007     case VIR_DOMAIN_DISK_BUS_USB:
1008         if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
1009             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1010                            _("disk device='lun' is not supported for usb bus"));
1011             break;
1012         }
1013 
1014         if (virDomainUSBAddressEnsure(priv->usbaddrs, &disk->info) < 0)
1015             goto cleanup;
1016 
1017         releaseUSB = true;
1018         break;
1019 
1020     case VIR_DOMAIN_DISK_BUS_VIRTIO:
1021         if (qemuDomainEnsureVirtioAddress(&releaseVirtio, vm, dev) < 0)
1022             goto cleanup;
1023         break;
1024 
1025     case VIR_DOMAIN_DISK_BUS_SCSI:
1026         /* We should have an address already, so make sure */
1027         if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
1028             virReportError(VIR_ERR_INTERNAL_ERROR,
1029                            _("unexpected disk address type %s"),
1030                            virDomainDeviceAddressTypeToString(disk->info.type));
1031             goto cleanup;
1032         }
1033 
1034         if (virDomainSCSIDriveAddressIsUsed(vm->def, &disk->info.addr.drive)) {
1035             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1036                            _("Domain already contains a disk with that address"));
1037             goto cleanup;
1038         }
1039 
1040         /* Let's make sure the disk has a controller defined and loaded before
1041          * trying to add it. The controller used by the disk must exist before a
1042          * qemu command line string is generated.
1043          *
1044          * Ensure that the given controller and all controllers with a smaller index
1045          * exist; there must not be any missing index in between.
1046          */
1047         for (i = 0; i <= disk->info.addr.drive.controller; i++) {
1048             if (!qemuDomainFindOrCreateSCSIDiskController(driver, vm, i))
1049                 goto cleanup;
1050         }
1051         break;
1052 
1053     case VIR_DOMAIN_DISK_BUS_IDE:
1054     case VIR_DOMAIN_DISK_BUS_FDC:
1055     case VIR_DOMAIN_DISK_BUS_XEN:
1056     case VIR_DOMAIN_DISK_BUS_UML:
1057     case VIR_DOMAIN_DISK_BUS_SATA:
1058     case VIR_DOMAIN_DISK_BUS_SD:
1059         /* Note that SD card hotplug support should be added only once
1060          * they support '-device' (don't require -drive only).
1061          * See also: qemuDiskBusIsSD */
1062     case VIR_DOMAIN_DISK_BUS_NONE:
1063     case VIR_DOMAIN_DISK_BUS_LAST:
1064         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
1065                        _("disk bus '%s' cannot be hotplugged."),
1066                        virDomainDiskBusTypeToString(disk->bus));
1067     }
1068 
1069     if (qemuDomainStorageSourceChainAccessAllow(driver, vm, disk->src) < 0)
1070         goto cleanup;
1071 
1072     releaseSeclabel = true;
1073 
1074     if (qemuAssignDeviceDiskAlias(vm->def, disk, priv->qemuCaps) < 0)
1075         goto cleanup;
1076 
1077     if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
1078         goto cleanup;
1079 
1080     if (qemuHotplugAttachManagedPR(driver, vm, disk->src, QEMU_ASYNC_JOB_NONE) < 0)
1081         goto cleanup;
1082 
1083     ret = qemuDomainAttachDiskGeneric(driver, vm, disk, QEMU_ASYNC_JOB_NONE);
1084 
1085     virDomainAuditDisk(vm, NULL, disk->src, "attach", ret == 0);
1086 
1087     if (ret < 0)
1088         goto cleanup;
1089 
1090     virDomainDiskInsert(vm->def, disk);
1091 
1092  cleanup:
1093     if (ret < 0) {
1094         ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
1095 
1096         if (releaseUSB)
1097             virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
1098 
1099         if (releaseVirtio && ret == -1)
1100             qemuDomainReleaseDeviceAddress(vm, &disk->info);
1101 
1102         if (releaseSeclabel)
1103             ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, disk->src));
1104 
1105         if (virStorageSourceChainHasManagedPR(disk->src))
1106             ignore_value(qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE));
1107     }
1108     qemuDomainSecretDiskDestroy(disk);
1109 
1110     return ret;
1111 }
1112 
1113 
1114 /**
1115  * qemuDomainAttachDeviceDiskLive:
1116  * @driver: qemu driver struct
1117  * @vm: domain object
1118  * @dev: device to attach (expected type is DISK)
1119  *
1120  * Attach a new disk or in case of cdroms/floppies change the media in the drive.
1121  * This function handles all the necessary steps to attach a new storage source
1122  * to the VM.
1123  */
1124 int
qemuDomainAttachDeviceDiskLive(virQEMUDriver * driver,virDomainObj * vm,virDomainDeviceDef * dev)1125 qemuDomainAttachDeviceDiskLive(virQEMUDriver *driver,
1126                                virDomainObj *vm,
1127                                virDomainDeviceDef *dev)
1128 {
1129     virDomainDiskDef *disk = dev->data.disk;
1130     virDomainDiskDef *orig_disk = NULL;
1131 
1132     /* this API overloads media change semantics on disk hotplug
1133      * for devices supporting media changes */
1134     if ((disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
1135          disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) &&
1136         (orig_disk = virDomainDiskByTarget(vm->def, disk->dst))) {
1137         if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
1138                                            disk->src, false) < 0)
1139             return -1;
1140 
1141         disk->src = NULL;
1142         virDomainDiskDefFree(disk);
1143         return 0;
1144     }
1145 
1146     return qemuDomainAttachDeviceDiskLiveInternal(driver, vm, dev);
1147 }
1148 
1149 
1150 static void
qemuDomainNetDeviceVportRemove(virDomainNetDef * net)1151 qemuDomainNetDeviceVportRemove(virDomainNetDef *net)
1152 {
1153     const virNetDevVPortProfile *vport = virDomainNetGetActualVirtPortProfile(net);
1154     const char *brname;
1155 
1156     if (!vport)
1157         return;
1158 
1159     if (vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_MIDONET) {
1160         ignore_value(virNetDevMidonetUnbindPort(vport));
1161     } else if (vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
1162         brname = virDomainNetGetActualBridgeName(net);
1163         ignore_value(virNetDevOpenvswitchRemovePort(brname, net->ifname));
1164     }
1165 }
1166 
1167 
1168 int
qemuDomainAttachNetDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainNetDef * net)1169 qemuDomainAttachNetDevice(virQEMUDriver *driver,
1170                           virDomainObj *vm,
1171                           virDomainNetDef *net)
1172 {
1173     qemuDomainObjPrivate *priv = vm->privateData;
1174     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_NET, { .net = net } };
1175     virErrorPtr originalError = NULL;
1176     g_autofree char *slirpfdName = NULL;
1177     int slirpfd = -1;
1178     g_autofree char *vdpafdName = NULL;
1179     int vdpafd = -1;
1180     char **tapfdName = NULL;
1181     int *tapfd = NULL;
1182     size_t tapfdSize = 0;
1183     char **vhostfdName = NULL;
1184     int *vhostfd = NULL;
1185     size_t vhostfdSize = 0;
1186     size_t queueSize = 0;
1187     g_autoptr(virJSONValue) nicprops = NULL;
1188     g_autoptr(virJSONValue) netprops = NULL;
1189     int ret = -1;
1190     bool releaseaddr = false;
1191     bool iface_connected = false;
1192     bool adjustmemlock = false;
1193     virDomainNetType actualType;
1194     const virNetDevBandwidth *actualBandwidth;
1195     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
1196     virDomainCCWAddressSet *ccwaddrs = NULL;
1197     size_t i;
1198     g_autofree char *charDevAlias = NULL;
1199     bool charDevPlugged = false;
1200     bool netdevPlugged = false;
1201     g_autofree char *netdev_name = NULL;
1202     g_autoptr(virConnect) conn = NULL;
1203     virErrorPtr save_err = NULL;
1204     bool teardownlabel = false;
1205 
1206     /* If appropriate, grab a physical device from the configured
1207      * network's pool of devices, or resolve bridge device name
1208      * to the one defined in the network definition.
1209      */
1210     if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
1211         if (!(conn = virGetConnectNetwork()))
1212             goto cleanup;
1213         if (virDomainNetAllocateActualDevice(conn, vm->def, net) < 0)
1214             goto cleanup;
1215     }
1216 
1217     /* final validation now that we have full info on the type */
1218     if (qemuDomainValidateActualNetDef(net, priv->qemuCaps) < 0)
1219         goto cleanup;
1220 
1221     actualType = virDomainNetGetActualType(net);
1222 
1223     qemuAssignDeviceNetAlias(vm->def, net, -1);
1224 
1225     if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
1226         /* This is really a "smart hostdev", so it should be attached
1227          * as a hostdev (the hostdev code will reach over into the
1228          * netdev-specific code as appropriate), then also added to
1229          * the nets list if successful.
1230          */
1231         if (qemuDomainAttachHostDevice(driver, vm,
1232                                        virDomainNetGetActualHostdev(net)) < 0) {
1233             goto cleanup;
1234         }
1235         VIR_APPEND_ELEMENT_COPY(vm->def->nets, vm->def->nnets, net);
1236 
1237         /* the rest of the setup doesn't apply to hostdev interfaces, so
1238          * we can skip straight to the cleanup (nothing there applies to
1239          * hostdev interfaces either, but it might in the future, so we
1240          * may as well be consistent)
1241          */
1242         ret = 0;
1243         goto cleanup;
1244     }
1245 
1246     if (qemuDomainIsS390CCW(vm->def) &&
1247         net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
1248         virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CCW)) {
1249         net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
1250         if (!(ccwaddrs = virDomainCCWAddressSetCreateFromDomain(vm->def)))
1251             goto cleanup;
1252         if (virDomainCCWAddressAssign(&net->info, ccwaddrs,
1253                                       !net->info.addr.ccw.assigned) < 0)
1254             goto cleanup;
1255     } else if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) {
1256         goto cleanup;
1257     }
1258 
1259     releaseaddr = true;
1260 
1261     /* We've completed all examinations of the full domain definition
1262      * that require the new device to *not* be present (e.g. PCI
1263      * address allocation and alias name assignment) so it is now safe
1264      * to add the new device to the domain's nets list (in order for
1265      * it to be in place for checks that *do* need it present in the
1266      * domain definition, e.g. checking if we need to adjust the
1267      * locked memory limit). This means we will need to remove it if
1268      * there is a failure.
1269      */
1270     VIR_APPEND_ELEMENT_COPY(vm->def->nets, vm->def->nnets, net);
1271 
1272     switch (actualType) {
1273     case VIR_DOMAIN_NET_TYPE_BRIDGE:
1274     case VIR_DOMAIN_NET_TYPE_NETWORK:
1275         tapfdSize = vhostfdSize = net->driver.virtio.queues;
1276         if (!tapfdSize)
1277             tapfdSize = vhostfdSize = 1;
1278         queueSize = tapfdSize;
1279         tapfd = g_new0(int, tapfdSize);
1280         memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
1281         vhostfd = g_new0(int, vhostfdSize);
1282         memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
1283         if (qemuInterfaceBridgeConnect(vm->def, driver, net,
1284                                        tapfd, &tapfdSize) < 0)
1285             goto cleanup;
1286         iface_connected = true;
1287         if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
1288             goto cleanup;
1289         break;
1290 
1291     case VIR_DOMAIN_NET_TYPE_DIRECT:
1292         tapfdSize = vhostfdSize = net->driver.virtio.queues;
1293         if (!tapfdSize)
1294             tapfdSize = vhostfdSize = 1;
1295         queueSize = tapfdSize;
1296         tapfd = g_new0(int, tapfdSize);
1297         memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
1298         vhostfd = g_new0(int, vhostfdSize);
1299         memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
1300         if (qemuInterfaceDirectConnect(vm->def, driver, net,
1301                                        tapfd, tapfdSize,
1302                                        VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0)
1303             goto cleanup;
1304         iface_connected = true;
1305         if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
1306             goto cleanup;
1307         break;
1308 
1309     case VIR_DOMAIN_NET_TYPE_ETHERNET:
1310         tapfdSize = vhostfdSize = net->driver.virtio.queues;
1311         if (!tapfdSize)
1312             tapfdSize = vhostfdSize = 1;
1313         queueSize = tapfdSize;
1314         tapfd = g_new0(int, tapfdSize);
1315         memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
1316         vhostfd = g_new0(int, vhostfdSize);
1317         memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
1318         if (qemuInterfaceEthernetConnect(vm->def, driver, net,
1319                                          tapfd, tapfdSize) < 0)
1320             goto cleanup;
1321         iface_connected = true;
1322         if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
1323             goto cleanup;
1324         break;
1325 
1326     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
1327         queueSize = net->driver.virtio.queues;
1328         if (!queueSize)
1329             queueSize = 1;
1330         if (!qemuDomainSupportsNicdev(vm->def, net)) {
1331             virReportError(VIR_ERR_INTERNAL_ERROR,
1332                            "%s", _("Nicdev support unavailable"));
1333             goto cleanup;
1334         }
1335 
1336         if (!(charDevAlias = qemuAliasChardevFromDevAlias(net->info.alias)))
1337             goto cleanup;
1338 
1339         if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
1340                                                    net->data.vhostuser->data.nix.listen,
1341                                                    &net->ifname) < 0)
1342             goto cleanup;
1343 
1344         if (qemuSecuritySetNetdevLabel(driver, vm, net) < 0)
1345             goto cleanup;
1346         teardownlabel = true;
1347         break;
1348 
1349     case VIR_DOMAIN_NET_TYPE_USER:
1350         if (!priv->disableSlirp &&
1351             virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
1352             qemuSlirp *slirp = NULL;
1353             int rv = qemuInterfacePrepareSlirp(driver, net, &slirp);
1354 
1355             if (rv == -1)
1356                 goto cleanup;
1357             if (rv == 0)
1358                 break;
1359 
1360             QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp = slirp;
1361 
1362             if (qemuSlirpOpen(slirp, driver, vm->def) < 0 ||
1363                 qemuSlirpStart(slirp, vm, driver, net, NULL) < 0) {
1364                 virReportError(VIR_ERR_INTERNAL_ERROR,
1365                                "%s", _("Failed to start slirp"));
1366                 goto cleanup;
1367             }
1368 
1369             slirpfd = qemuSlirpGetFD(slirp);
1370             slirpfdName = g_strdup_printf("slirpfd-%s", net->info.alias);
1371         }
1372         break;
1373 
1374     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
1375         /* hostdev interfaces were handled earlier in this function */
1376         break;
1377 
1378     case VIR_DOMAIN_NET_TYPE_VDPA:
1379         if (qemuDomainAdjustMaxMemLock(vm, false) < 0)
1380             goto cleanup;
1381         adjustmemlock = true;
1382 
1383         if ((vdpafd = qemuInterfaceVDPAConnect(net)) < 0)
1384             goto cleanup;
1385         break;
1386 
1387     case VIR_DOMAIN_NET_TYPE_SERVER:
1388     case VIR_DOMAIN_NET_TYPE_CLIENT:
1389     case VIR_DOMAIN_NET_TYPE_MCAST:
1390     case VIR_DOMAIN_NET_TYPE_INTERNAL:
1391     case VIR_DOMAIN_NET_TYPE_UDP:
1392     case VIR_DOMAIN_NET_TYPE_LAST:
1393         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
1394                        _("hotplug of interface type of %s is not implemented yet"),
1395                        virDomainNetTypeToString(actualType));
1396         goto cleanup;
1397     }
1398 
1399     /* Set device online immediately */
1400     if (qemuInterfaceStartDevice(net) < 0)
1401         goto cleanup;
1402 
1403     qemuDomainInterfaceSetDefaultQDisc(driver, net);
1404 
1405     /* Set bandwidth or warn if requested and not supported. */
1406     actualBandwidth = virDomainNetGetActualBandwidth(net);
1407     if (actualBandwidth) {
1408         if (virNetDevSupportsBandwidth(actualType)) {
1409             if (virDomainNetDefIsOvsport(net)) {
1410                 if (virNetDevOpenvswitchInterfaceSetQos(net->ifname, actualBandwidth,
1411                                                         vm->def->uuid,
1412                                                         !virDomainNetTypeSharesHostView(net)) < 0)
1413                     goto cleanup;
1414             } else if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false,
1415                                              !virDomainNetTypeSharesHostView(net)) < 0) {
1416                 goto cleanup;
1417             }
1418         } else {
1419             VIR_WARN("setting bandwidth on interfaces of "
1420                      "type '%s' is not implemented yet",
1421                      virDomainNetTypeToString(actualType));
1422         }
1423     }
1424 
1425     if (net->mtu && net->managed_tap != VIR_TRISTATE_BOOL_NO &&
1426         virNetDevSetMTU(net->ifname, net->mtu) < 0)
1427         goto cleanup;
1428 
1429     for (i = 0; i < tapfdSize; i++) {
1430         if (qemuSecuritySetTapFDLabel(driver->securityManager,
1431                                       vm->def, tapfd[i]) < 0)
1432             goto cleanup;
1433     }
1434 
1435     tapfdName = g_new0(char *, tapfdSize);
1436     vhostfdName = g_new0(char *, vhostfdSize);
1437 
1438     for (i = 0; i < tapfdSize; i++)
1439         tapfdName[i] = g_strdup_printf("fd-%s%zu", net->info.alias, i);
1440 
1441     for (i = 0; i < vhostfdSize; i++)
1442         vhostfdName[i] = g_strdup_printf("vhostfd-%s%zu", net->info.alias, i);
1443 
1444     qemuDomainObjEnterMonitor(driver, vm);
1445 
1446     if (vdpafd > 0) {
1447         /* vhost-vdpa only accepts a filename. We can pass an open fd by
1448          * filename if we add the fd to an fdset and then pass a filename of
1449          * /dev/fdset/$FDSETID. */
1450         qemuMonitorAddFdInfo fdinfo;
1451         if (qemuMonitorAddFileHandleToSet(priv->mon, vdpafd, -1,
1452                                           net->data.vdpa.devicepath,
1453                                           &fdinfo) < 0) {
1454             ignore_value(qemuDomainObjExitMonitor(driver, vm));
1455             goto cleanup;
1456         }
1457         vdpafdName = g_strdup_printf("/dev/fdset/%d", fdinfo.fdset);
1458     }
1459 
1460     if (!(netprops = qemuBuildHostNetProps(net,
1461                                            tapfdName, tapfdSize,
1462                                            vhostfdName, vhostfdSize,
1463                                            slirpfdName, vdpafdName))) {
1464         ignore_value(qemuDomainObjExitMonitor(driver, vm));
1465         goto cleanup;
1466     }
1467 
1468     if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
1469         if (qemuHotplugChardevAttach(priv->mon, charDevAlias, net->data.vhostuser) < 0) {
1470             ignore_value(qemuDomainObjExitMonitor(driver, vm));
1471             virDomainAuditNet(vm, NULL, net, "attach", false);
1472             goto cleanup;
1473         }
1474         charDevPlugged = true;
1475     }
1476 
1477     if (qemuMonitorAddNetdev(priv->mon, &netprops,
1478                              tapfd, tapfdName, tapfdSize,
1479                              vhostfd, vhostfdName, vhostfdSize,
1480                              slirpfd, slirpfdName) < 0) {
1481         ignore_value(qemuDomainObjExitMonitor(driver, vm));
1482         virDomainAuditNet(vm, NULL, net, "attach", false);
1483         goto try_remove;
1484     }
1485     netdevPlugged = true;
1486 
1487     if (qemuDomainObjExitMonitor(driver, vm) < 0)
1488         goto cleanup;
1489 
1490     for (i = 0; i < tapfdSize; i++)
1491         VIR_FORCE_CLOSE(tapfd[i]);
1492     for (i = 0; i < vhostfdSize; i++)
1493         VIR_FORCE_CLOSE(vhostfd[i]);
1494 
1495     if (!(nicprops = qemuBuildNicDevProps(vm->def, net, queueSize, priv->qemuCaps)))
1496         goto try_remove;
1497 
1498     qemuDomainObjEnterMonitor(driver, vm);
1499 
1500     if (qemuDomainAttachExtensionDevice(priv->mon, &net->info) < 0) {
1501         ignore_value(qemuDomainObjExitMonitor(driver, vm));
1502         virDomainAuditNet(vm, NULL, net, "attach", false);
1503         goto try_remove;
1504     }
1505 
1506     if (qemuMonitorAddDeviceProps(priv->mon, &nicprops) < 0) {
1507         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &net->info));
1508         ignore_value(qemuDomainObjExitMonitor(driver, vm));
1509         virDomainAuditNet(vm, NULL, net, "attach", false);
1510         goto try_remove;
1511     }
1512     if (qemuDomainObjExitMonitor(driver, vm) < 0)
1513         goto cleanup;
1514 
1515     /* set link state */
1516     if (net->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
1517         if (!net->info.alias) {
1518             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1519                            _("device alias not found: cannot set link state to down"));
1520         } else {
1521             qemuDomainObjEnterMonitor(driver, vm);
1522 
1523             if (qemuMonitorSetLink(priv->mon, net->info.alias, VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) < 0) {
1524                 ignore_value(qemuDomainObjExitMonitor(driver, vm));
1525                 virDomainAuditNet(vm, NULL, net, "attach", false);
1526                 goto try_remove;
1527             }
1528 
1529             if (qemuDomainObjExitMonitor(driver, vm) < 0)
1530                 goto cleanup;
1531         }
1532         /* link set to down */
1533     }
1534 
1535     virDomainAuditNet(vm, NULL, net, "attach", true);
1536 
1537     ret = 0;
1538 
1539  cleanup:
1540     if (ret < 0) {
1541         virErrorPreserveLast(&save_err);
1542         if (releaseaddr)
1543             qemuDomainReleaseDeviceAddress(vm, &net->info);
1544 
1545         if (iface_connected) {
1546             virErrorPreserveLast(&originalError);
1547             virDomainConfNWFilterTeardown(net);
1548             virErrorRestore(&originalError);
1549 
1550             if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
1551                 ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
1552                                  net->ifname, &net->mac,
1553                                  virDomainNetGetActualDirectDev(net),
1554                                  virDomainNetGetActualDirectMode(net),
1555                                  virDomainNetGetActualVirtPortProfile(net),
1556                                  cfg->stateDir));
1557             }
1558 
1559             qemuDomainNetDeviceVportRemove(net);
1560         }
1561 
1562         if (teardownlabel &&
1563             qemuSecurityRestoreNetdevLabel(driver, vm, net) < 0)
1564             VIR_WARN("Unable to restore network device labelling on hotplug fail");
1565 
1566         /* we had potentially pre-added the device to the domain
1567          * device lists, if so we need to remove it (from def->nets
1568          * and/or def->hostdevs) on failure
1569          */
1570         virDomainNetRemoveByObj(vm->def, net);
1571 
1572         /* if we adjusted the memlock limit (for a vDPA device) then
1573          * we need to re-adjust since we won't be using the device
1574          * after all
1575          */
1576         if (adjustmemlock)
1577             qemuDomainAdjustMaxMemLock(vm, false);
1578 
1579         if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
1580             if (conn)
1581                 virDomainNetReleaseActualDevice(conn, vm->def, net);
1582             else
1583                 VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
1584         }
1585         virErrorRestore(&save_err);
1586     }
1587 
1588     for (i = 0; tapfd && i < tapfdSize; i++) {
1589         VIR_FORCE_CLOSE(tapfd[i]);
1590         if (tapfdName)
1591             VIR_FREE(tapfdName[i]);
1592     }
1593     VIR_FREE(tapfd);
1594     VIR_FREE(tapfdName);
1595     for (i = 0; vhostfd && i < vhostfdSize; i++) {
1596         VIR_FORCE_CLOSE(vhostfd[i]);
1597         if (vhostfdName)
1598             VIR_FREE(vhostfdName[i]);
1599     }
1600     VIR_FREE(vhostfd);
1601     VIR_FREE(vhostfdName);
1602     virDomainCCWAddressSetFree(ccwaddrs);
1603     VIR_FORCE_CLOSE(slirpfd);
1604     VIR_FORCE_CLOSE(vdpafd);
1605 
1606     return ret;
1607 
1608  try_remove:
1609     if (!virDomainObjIsActive(vm))
1610         goto cleanup;
1611 
1612     virErrorPreserveLast(&originalError);
1613     netdev_name = g_strdup_printf("host%s", net->info.alias);
1614     if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
1615         qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net);
1616     qemuDomainObjEnterMonitor(driver, vm);
1617     if (charDevPlugged &&
1618         qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
1619         VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
1620     if (netdevPlugged &&
1621         qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
1622         VIR_WARN("Failed to remove network backend for netdev %s",
1623                  netdev_name);
1624     ignore_value(qemuDomainObjExitMonitor(driver, vm));
1625     virErrorRestore(&originalError);
1626     goto cleanup;
1627 }
1628 
1629 
1630 static int
qemuDomainAttachHostPCIDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)1631 qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
1632                               virDomainObj *vm,
1633                               virDomainHostdevDef *hostdev)
1634 {
1635     qemuDomainObjPrivate *priv = vm->privateData;
1636     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
1637                                { .hostdev = hostdev } };
1638     virDomainDeviceInfo *info = hostdev->info;
1639     int ret;
1640     g_autoptr(virJSONValue) devprops = NULL;
1641     bool releaseaddr = false;
1642     bool teardowncgroup = false;
1643     bool teardownlabel = false;
1644     bool teardowndevice = false;
1645     bool teardownmemlock = false;
1646     int backend;
1647     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
1648     unsigned int flags = 0;
1649 
1650     VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
1651 
1652     if (!cfg->relaxedACS)
1653         flags |= VIR_HOSTDEV_STRICT_ACS_CHECK;
1654     if (qemuHostdevPreparePCIDevices(driver, vm->def->name, vm->def->uuid,
1655                                      &hostdev, 1, priv->qemuCaps, flags) < 0)
1656         return -1;
1657 
1658     /* this could have been changed by qemuHostdevPreparePCIDevices */
1659     backend = hostdev->source.subsys.u.pci.backend;
1660 
1661     switch ((virDomainHostdevSubsysPCIBackendType)backend) {
1662     case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
1663         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
1664             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1665                            _("VFIO PCI device assignment is not "
1666                              "supported by this version of qemu"));
1667             goto error;
1668         }
1669         break;
1670 
1671     case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
1672     case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
1673         break;
1674 
1675     case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
1676     case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
1677         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1678                        _("QEMU does not support device assignment mode '%s'"),
1679                        virDomainHostdevSubsysPCIBackendTypeToString(backend));
1680         goto error;
1681         break;
1682     }
1683 
1684     if (qemuDomainAdjustMaxMemLockHostdev(vm, hostdev) < 0)
1685         goto error;
1686     teardownmemlock = true;
1687 
1688     if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
1689         goto error;
1690 
1691     if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
1692         goto error;
1693     teardowncgroup = true;
1694 
1695     if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
1696         goto error;
1697     if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO)
1698         teardownlabel = true;
1699 
1700     qemuAssignDeviceHostdevAlias(vm->def, &info->alias, -1);
1701 
1702     if (qemuDomainIsPSeries(vm->def))
1703         /* Isolation groups are only relevant for pSeries guests */
1704         qemuDomainFillDeviceIsolationGroup(vm->def, &dev);
1705 
1706     if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
1707         goto error;
1708     releaseaddr = true;
1709 
1710     if (!virDomainObjIsActive(vm)) {
1711         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1712                        _("guest unexpectedly quit during hotplug"));
1713         goto error;
1714     }
1715 
1716     if (!(devprops = qemuBuildPCIHostdevDevProps(vm->def, hostdev)))
1717         goto error;
1718 
1719     qemuDomainObjEnterMonitor(driver, vm);
1720 
1721     if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
1722         goto exit_monitor;
1723 
1724     if ((ret = qemuMonitorAddDeviceProps(priv->mon, &devprops)) < 0)
1725         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
1726 
1727  exit_monitor:
1728     if (qemuDomainObjExitMonitor(driver, vm) < 0)
1729         goto error;
1730 
1731     virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
1732     if (ret < 0)
1733         goto error;
1734 
1735     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
1736 
1737     return 0;
1738 
1739  error:
1740     if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
1741         VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
1742     if (teardownlabel &&
1743         qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
1744         VIR_WARN("Unable to restore host device labelling on hotplug fail");
1745     if (teardowndevice &&
1746         qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
1747         VIR_WARN("Unable to remove host device from /dev");
1748     if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm, false) < 0)
1749         VIR_WARN("Unable to reset maximum locked memory on hotplug fail");
1750 
1751     if (releaseaddr)
1752         qemuDomainReleaseDeviceAddress(vm, info);
1753 
1754     qemuHostdevReAttachPCIDevices(driver, vm->def->name, &hostdev, 1);
1755 
1756     return -1;
1757 }
1758 
1759 
1760 void
qemuDomainDelTLSObjects(virQEMUDriver * driver,virDomainObj * vm,qemuDomainAsyncJob asyncJob,const char * secAlias,const char * tlsAlias)1761 qemuDomainDelTLSObjects(virQEMUDriver *driver,
1762                         virDomainObj *vm,
1763                         qemuDomainAsyncJob asyncJob,
1764                         const char *secAlias,
1765                         const char *tlsAlias)
1766 {
1767     qemuDomainObjPrivate *priv = vm->privateData;
1768     virErrorPtr orig_err;
1769 
1770     if (!tlsAlias && !secAlias)
1771         return;
1772 
1773     virErrorPreserveLast(&orig_err);
1774 
1775     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
1776         goto cleanup;
1777 
1778     if (tlsAlias)
1779         ignore_value(qemuMonitorDelObject(priv->mon, tlsAlias, false));
1780 
1781     if (secAlias)
1782         ignore_value(qemuMonitorDelObject(priv->mon, secAlias, false));
1783 
1784     ignore_value(qemuDomainObjExitMonitor(driver, vm));
1785 
1786  cleanup:
1787     virErrorRestore(&orig_err);
1788 }
1789 
1790 
1791 int
qemuDomainAddTLSObjects(virQEMUDriver * driver,virDomainObj * vm,qemuDomainAsyncJob asyncJob,virJSONValue ** secProps,virJSONValue ** tlsProps)1792 qemuDomainAddTLSObjects(virQEMUDriver *driver,
1793                         virDomainObj *vm,
1794                         qemuDomainAsyncJob asyncJob,
1795                         virJSONValue **secProps,
1796                         virJSONValue **tlsProps)
1797 {
1798     qemuDomainObjPrivate *priv = vm->privateData;
1799     virErrorPtr orig_err;
1800     g_autofree char *secAlias = NULL;
1801 
1802     if (!tlsProps && !secProps)
1803         return 0;
1804 
1805     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
1806         return -1;
1807 
1808     if (secProps && *secProps &&
1809         qemuMonitorAddObject(priv->mon, secProps, &secAlias) < 0)
1810         goto error;
1811 
1812     if (tlsProps &&
1813         qemuMonitorAddObject(priv->mon, tlsProps, NULL) < 0)
1814         goto error;
1815 
1816     return qemuDomainObjExitMonitor(driver, vm);
1817 
1818  error:
1819     virErrorPreserveLast(&orig_err);
1820     ignore_value(qemuDomainObjExitMonitor(driver, vm));
1821     virErrorRestore(&orig_err);
1822     qemuDomainDelTLSObjects(driver, vm, asyncJob, secAlias, NULL);
1823 
1824     return -1;
1825 }
1826 
1827 
1828 int
qemuDomainGetTLSObjects(qemuDomainSecretInfo * secinfo,const char * tlsCertdir,bool tlsListen,bool tlsVerify,const char * alias,virJSONValue ** tlsProps,virJSONValue ** secProps)1829 qemuDomainGetTLSObjects(qemuDomainSecretInfo *secinfo,
1830                         const char *tlsCertdir,
1831                         bool tlsListen,
1832                         bool tlsVerify,
1833                         const char *alias,
1834                         virJSONValue **tlsProps,
1835                         virJSONValue **secProps)
1836 {
1837     const char *secAlias = NULL;
1838 
1839     if (secinfo) {
1840         if (qemuBuildSecretInfoProps(secinfo, secProps) < 0)
1841             return -1;
1842 
1843         secAlias = secinfo->alias;
1844     }
1845 
1846     if (qemuBuildTLSx509BackendProps(tlsCertdir, tlsListen, tlsVerify,
1847                                      alias, secAlias, tlsProps) < 0)
1848         return -1;
1849 
1850     return 0;
1851 }
1852 
1853 
1854 static int
qemuDomainAddChardevTLSObjects(virQEMUDriver * driver,virDomainObj * vm,virDomainChrSourceDef * dev,char * devAlias,char * charAlias,char ** tlsAlias,const char ** secAlias)1855 qemuDomainAddChardevTLSObjects(virQEMUDriver *driver,
1856                                virDomainObj *vm,
1857                                virDomainChrSourceDef *dev,
1858                                char *devAlias,
1859                                char *charAlias,
1860                                char **tlsAlias,
1861                                const char **secAlias)
1862 {
1863     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
1864     qemuDomainObjPrivate *priv = vm->privateData;
1865     qemuDomainChrSourcePrivate *chrSourcePriv;
1866     qemuDomainSecretInfo *secinfo = NULL;
1867     g_autoptr(virJSONValue) tlsProps = NULL;
1868     g_autoptr(virJSONValue) secProps = NULL;
1869 
1870     /* NB: This may alter haveTLS based on cfg */
1871     qemuDomainPrepareChardevSourceTLS(dev, cfg);
1872 
1873     if (dev->type != VIR_DOMAIN_CHR_TYPE_TCP ||
1874         dev->data.tcp.haveTLS != VIR_TRISTATE_BOOL_YES)
1875         return 0;
1876 
1877     if (qemuDomainSecretChardevPrepare(cfg, priv, devAlias, dev) < 0)
1878         return -1;
1879 
1880     if ((chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev)))
1881         secinfo = chrSourcePriv->secinfo;
1882 
1883     if (secinfo)
1884         *secAlias = secinfo->alias;
1885 
1886     if (!(*tlsAlias = qemuAliasTLSObjFromSrcAlias(charAlias)))
1887         return -1;
1888 
1889     if (qemuDomainGetTLSObjects(secinfo,
1890                                 cfg->chardevTLSx509certdir,
1891                                 dev->data.tcp.listen,
1892                                 cfg->chardevTLSx509verify,
1893                                 *tlsAlias, &tlsProps, &secProps) < 0)
1894         return -1;
1895 
1896     dev->data.tcp.tlscreds = true;
1897 
1898     if (qemuDomainAddTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
1899                                 &secProps, &tlsProps) < 0)
1900         return -1;
1901 
1902     return 0;
1903 }
1904 
1905 
1906 static int
qemuDomainDelChardevTLSObjects(virQEMUDriver * driver,virDomainObj * vm,virDomainChrSourceDef * dev,const char * inAlias)1907 qemuDomainDelChardevTLSObjects(virQEMUDriver *driver,
1908                                virDomainObj *vm,
1909                                virDomainChrSourceDef *dev,
1910                                const char *inAlias)
1911 {
1912     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
1913     qemuDomainObjPrivate *priv = vm->privateData;
1914     g_autofree char *tlsAlias = NULL;
1915     g_autofree char *secAlias = NULL;
1916 
1917     if (dev->type != VIR_DOMAIN_CHR_TYPE_TCP ||
1918         dev->data.tcp.haveTLS != VIR_TRISTATE_BOOL_YES) {
1919         return 0;
1920     }
1921 
1922     if (!(tlsAlias = qemuAliasTLSObjFromSrcAlias(inAlias)))
1923         return -1;
1924 
1925     /* Best shot at this as the secinfo is destroyed after process launch
1926      * and this path does not recreate it. Thus, if the config has the
1927      * secret UUID and we have a serial TCP chardev, then formulate a
1928      * secAlias which we'll attempt to destroy. */
1929     if (cfg->chardevTLSx509secretUUID &&
1930         !(secAlias = qemuAliasForSecret(inAlias, NULL)))
1931         return -1;
1932 
1933     qemuDomainObjEnterMonitor(driver, vm);
1934 
1935     ignore_value(qemuMonitorDelObject(priv->mon, tlsAlias, false));
1936     if (secAlias)
1937         ignore_value(qemuMonitorDelObject(priv->mon, secAlias, false));
1938 
1939     if (qemuDomainObjExitMonitor(driver, vm) < 0)
1940         return -1;
1941 
1942     return 0;
1943 }
1944 
1945 
qemuDomainAttachRedirdevDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainRedirdevDef * redirdev)1946 int qemuDomainAttachRedirdevDevice(virQEMUDriver *driver,
1947                                    virDomainObj *vm,
1948                                    virDomainRedirdevDef *redirdev)
1949 {
1950     int ret = -1;
1951     qemuDomainObjPrivate *priv = vm->privateData;
1952     virDomainDef *def = vm->def;
1953     g_autofree char *charAlias = NULL;
1954     g_autoptr(virJSONValue) devprops = NULL;
1955     bool chardevAdded = false;
1956     g_autofree char *tlsAlias = NULL;
1957     const char *secAlias = NULL;
1958     virErrorPtr orig_err;
1959 
1960     qemuAssignDeviceRedirdevAlias(def, redirdev, -1);
1961 
1962     if (!(charAlias = qemuAliasChardevFromDevAlias(redirdev->info.alias)))
1963         return -1;
1964 
1965     if ((virDomainUSBAddressEnsure(priv->usbaddrs, &redirdev->info)) < 0)
1966         return -1;
1967 
1968     if (!(devprops = qemuBuildRedirdevDevProps(def, redirdev)))
1969         goto cleanup;
1970 
1971     VIR_REALLOC_N(def->redirdevs, def->nredirdevs+1);
1972 
1973     if (qemuDomainAddChardevTLSObjects(driver, vm, redirdev->source,
1974                                        redirdev->info.alias, charAlias,
1975                                        &tlsAlias, &secAlias) < 0)
1976         goto audit;
1977 
1978     qemuDomainObjEnterMonitor(driver, vm);
1979 
1980     if (qemuHotplugChardevAttach(priv->mon, charAlias, redirdev->source) < 0)
1981         goto exit_monitor;
1982     chardevAdded = true;
1983 
1984     if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0)
1985         goto exit_monitor;
1986 
1987     if (qemuDomainObjExitMonitor(driver, vm) < 0)
1988         goto audit;
1989 
1990     def->redirdevs[def->nredirdevs++] = redirdev;
1991     ret = 0;
1992  audit:
1993     virDomainAuditRedirdev(vm, redirdev, "attach", ret == 0);
1994  cleanup:
1995     if (ret < 0)
1996         qemuDomainReleaseDeviceAddress(vm, &redirdev->info);
1997     return ret;
1998 
1999  exit_monitor:
2000     virErrorPreserveLast(&orig_err);
2001     /* detach associated chardev on error */
2002     if (chardevAdded)
2003         ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
2004     ignore_value(qemuDomainObjExitMonitor(driver, vm));
2005     virErrorRestore(&orig_err);
2006     qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
2007                             secAlias, tlsAlias);
2008     goto audit;
2009 }
2010 
2011 static int
qemuDomainChrPreInsert(virDomainDef * vmdef,virDomainChrDef * chr)2012 qemuDomainChrPreInsert(virDomainDef *vmdef,
2013                        virDomainChrDef *chr)
2014 {
2015     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
2016         chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
2017         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2018                        _("attaching serial console is not supported"));
2019         return -1;
2020     }
2021 
2022     if (virDomainChrFind(vmdef, chr)) {
2023         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2024                        _("chardev already exists"));
2025         return -1;
2026     }
2027 
2028     if (virDomainChrPreAlloc(vmdef, chr) < 0)
2029         return -1;
2030 
2031     /* Due to historical reasons, the first console is an alias to the
2032      * first serial device (if such exists). If this is the case, we need to
2033      * create an object for the first console as well.
2034      */
2035     if (vmdef->nserials == 0 && vmdef->nconsoles == 0 &&
2036         chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
2037         if (!vmdef->consoles)
2038             vmdef->consoles = g_new0(virDomainChrDef *, 1);
2039 
2040         /* We'll be dealing with serials[0] directly, so NULL is fine here. */
2041         if (!(vmdef->consoles[0] = virDomainChrDefNew(NULL))) {
2042             VIR_FREE(vmdef->consoles);
2043             return -1;
2044         }
2045         vmdef->nconsoles++;
2046     }
2047     return 0;
2048 }
2049 
2050 static void
qemuDomainChrInsertPreAlloced(virDomainDef * vmdef,virDomainChrDef * chr)2051 qemuDomainChrInsertPreAlloced(virDomainDef *vmdef,
2052                               virDomainChrDef *chr)
2053 {
2054     virDomainChrInsertPreAlloced(vmdef, chr);
2055     if (vmdef->nserials == 1 && vmdef->nconsoles == 0 &&
2056         chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
2057         vmdef->nconsoles = 1;
2058 
2059         /* Create an console alias for the serial port */
2060         vmdef->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
2061         vmdef->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
2062     }
2063 }
2064 
2065 static void
qemuDomainChrInsertPreAllocCleanup(virDomainDef * vmdef,virDomainChrDef * chr)2066 qemuDomainChrInsertPreAllocCleanup(virDomainDef *vmdef,
2067                                    virDomainChrDef *chr)
2068 {
2069     /* Remove the stub console added by qemuDomainChrPreInsert */
2070     if (vmdef->nserials == 0 && vmdef->nconsoles == 1 &&
2071         chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
2072         virDomainChrDefFree(vmdef->consoles[0]);
2073         VIR_FREE(vmdef->consoles);
2074         vmdef->nconsoles = 0;
2075     }
2076 }
2077 
2078 int
qemuDomainChrInsert(virDomainDef * vmdef,virDomainChrDef * chr)2079 qemuDomainChrInsert(virDomainDef *vmdef,
2080                     virDomainChrDef *chr)
2081 {
2082     if (qemuDomainChrPreInsert(vmdef, chr) < 0) {
2083         qemuDomainChrInsertPreAllocCleanup(vmdef, chr);
2084         return -1;
2085     }
2086     qemuDomainChrInsertPreAlloced(vmdef, chr);
2087     return 0;
2088 }
2089 
2090 virDomainChrDef *
qemuDomainChrRemove(virDomainDef * vmdef,virDomainChrDef * chr)2091 qemuDomainChrRemove(virDomainDef *vmdef,
2092                     virDomainChrDef *chr)
2093 {
2094     virDomainChrDef *ret;
2095     bool removeCompat;
2096 
2097     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
2098         chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
2099         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2100                        _("detaching serial console is not supported"));
2101         return NULL;
2102     }
2103 
2104     /* Due to some crazy backcompat stuff, the first serial device is an alias
2105      * to the first console too. If this is the case, the definition must be
2106      * duplicated as first console device. */
2107     removeCompat = vmdef->nserials && vmdef->nconsoles &&
2108         vmdef->consoles[0]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
2109         vmdef->consoles[0]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL &&
2110         virDomainChrEquals(vmdef->serials[0], chr);
2111 
2112     if (!(ret = virDomainChrRemove(vmdef, chr))) {
2113         virReportError(VIR_ERR_INVALID_ARG, "%s",
2114                        _("device not present in domain configuration"));
2115             return NULL;
2116     }
2117 
2118     if (removeCompat)
2119         VIR_DELETE_ELEMENT(vmdef->consoles, 0, vmdef->nconsoles);
2120 
2121     return ret;
2122 }
2123 
2124 
2125 
2126 static int
qemuDomainAttachChrDeviceAssignAddr(virDomainObj * vm,virDomainChrDef * chr,bool * need_release)2127 qemuDomainAttachChrDeviceAssignAddr(virDomainObj *vm,
2128                                     virDomainChrDef *chr,
2129                                     bool *need_release)
2130 {
2131     virDomainDef *def = vm->def;
2132     qemuDomainObjPrivate *priv = vm->privateData;
2133     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CHR, { .chr = chr } };
2134 
2135     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
2136         chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
2137         if (virDomainVirtioSerialAddrAutoAssign(def, &chr->info, true) < 0)
2138             return -1;
2139         return 0;
2140 
2141     } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
2142                chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) {
2143         if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
2144             return -1;
2145 
2146         *need_release = true;
2147         return 0;
2148     } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
2149                chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB) {
2150         if (virDomainUSBAddressEnsure(priv->usbaddrs, &chr->info) < 0)
2151             return -1;
2152 
2153         *need_release = true;
2154         return 0;
2155 
2156     } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
2157                chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
2158         if (virDomainVirtioSerialAddrAutoAssign(def, &chr->info, false) < 0)
2159             return -1;
2160         return 0;
2161     }
2162 
2163     if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL ||
2164         chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
2165         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2166                        _("Unsupported address type for character device"));
2167         return -1;
2168     }
2169 
2170     return 0;
2171 }
2172 
qemuDomainAttachChrDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainChrDef * chr)2173 int qemuDomainAttachChrDevice(virQEMUDriver *driver,
2174                               virDomainObj *vm,
2175                               virDomainChrDef *chr)
2176 {
2177     int ret = -1;
2178     qemuDomainObjPrivate *priv = vm->privateData;
2179     virErrorPtr orig_err;
2180     virDomainDef *vmdef = vm->def;
2181     g_autoptr(virJSONValue) devprops = NULL;
2182     g_autoptr(virJSONValue) netdevprops = NULL;
2183     g_autofree char *charAlias = NULL;
2184     bool chardevAttached = false;
2185     bool teardowncgroup = false;
2186     bool teardowndevice = false;
2187     bool teardownlabel = false;
2188     g_autofree char *tlsAlias = NULL;
2189     const char *secAlias = NULL;
2190     bool need_release = false;
2191     bool guestfwd = false;
2192 
2193     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL) {
2194         guestfwd = chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD;
2195 
2196         if (qemuDomainPrepareChannel(chr, priv->channelTargetDir) < 0)
2197             goto cleanup;
2198     }
2199 
2200     if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
2201         goto cleanup;
2202 
2203     if (qemuDomainAttachChrDeviceAssignAddr(vm, chr, &need_release) < 0)
2204         goto cleanup;
2205 
2206     if (qemuDomainNamespaceSetupChardev(vm, chr, &teardowndevice) < 0)
2207         goto cleanup;
2208 
2209     if (qemuSecuritySetChardevLabel(driver, vm, chr) < 0)
2210         goto cleanup;
2211     teardownlabel = true;
2212 
2213     if (qemuSetupChardevCgroup(vm, chr) < 0)
2214         goto cleanup;
2215     teardowncgroup = true;
2216 
2217     if (guestfwd) {
2218         if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(chr)))
2219             goto cleanup;
2220     } else {
2221         if (!(devprops = qemuBuildChrDeviceProps(vmdef, chr, priv->qemuCaps)))
2222             goto cleanup;
2223     }
2224 
2225     if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
2226         goto cleanup;
2227 
2228     if (qemuDomainChrPreInsert(vmdef, chr) < 0)
2229         goto cleanup;
2230 
2231     if (qemuDomainAddChardevTLSObjects(driver, vm, chr->source,
2232                                        chr->info.alias, charAlias,
2233                                        &tlsAlias, &secAlias) < 0)
2234         goto audit;
2235 
2236     qemuDomainObjEnterMonitor(driver, vm);
2237 
2238     if (qemuHotplugChardevAttach(priv->mon, charAlias, chr->source) < 0)
2239         goto exit_monitor;
2240     chardevAttached = true;
2241 
2242     if (netdevprops) {
2243         if (qemuMonitorAddNetdev(priv->mon, &netdevprops,
2244                                  NULL, NULL, 0, NULL, NULL, 0, -1, NULL) < 0)
2245             goto exit_monitor;
2246     }
2247 
2248     if (devprops) {
2249         if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0)
2250             goto exit_monitor;
2251     }
2252 
2253     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2254         goto audit;
2255 
2256     qemuDomainChrInsertPreAlloced(vmdef, chr);
2257     ret = 0;
2258  audit:
2259     virDomainAuditChardev(vm, NULL, chr, "attach", ret == 0);
2260  cleanup:
2261     if (ret < 0) {
2262         if (virDomainObjIsActive(vm))
2263             qemuDomainChrInsertPreAllocCleanup(vmdef, chr);
2264         if (need_release)
2265             qemuDomainReleaseDeviceAddress(vm, &chr->info);
2266         if (teardowncgroup && qemuTeardownChardevCgroup(vm, chr) < 0)
2267             VIR_WARN("Unable to remove chr device cgroup ACL on hotplug fail");
2268         if (teardownlabel && qemuSecurityRestoreChardevLabel(driver, vm, chr) < 0)
2269             VIR_WARN("Unable to restore security label on char device");
2270         if (teardowndevice && qemuDomainNamespaceTeardownChardev(vm, chr) < 0)
2271             VIR_WARN("Unable to remove chr device from /dev");
2272     }
2273     return ret;
2274 
2275  exit_monitor:
2276     virErrorPreserveLast(&orig_err);
2277     /* detach associated chardev on error */
2278     if (chardevAttached)
2279         qemuMonitorDetachCharDev(priv->mon, charAlias);
2280     ignore_value(qemuDomainObjExitMonitor(driver, vm));
2281     virErrorRestore(&orig_err);
2282 
2283     qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
2284                             secAlias, tlsAlias);
2285     goto audit;
2286 }
2287 
2288 
2289 int
qemuDomainAttachRNGDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainRNGDef * rng)2290 qemuDomainAttachRNGDevice(virQEMUDriver *driver,
2291                           virDomainObj *vm,
2292                           virDomainRNGDef *rng)
2293 {
2294     qemuDomainObjPrivate *priv = vm->privateData;
2295     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_RNG, { .rng = rng } };
2296     virErrorPtr orig_err;
2297     g_autoptr(virJSONValue) devprops = NULL;
2298     g_autofree char *charAlias = NULL;
2299     g_autofree char *objAlias = NULL;
2300     g_autofree char *tlsAlias = NULL;
2301     const char *secAlias = NULL;
2302     bool releaseaddr = false;
2303     bool teardowncgroup = false;
2304     bool teardowndevice = false;
2305     bool chardevAdded = false;
2306     virJSONValue *props = NULL;
2307     int ret = -1;
2308 
2309     qemuAssignDeviceRNGAlias(vm->def, rng);
2310 
2311     /* preallocate space for the device definition */
2312     VIR_REALLOC_N(vm->def->rngs, vm->def->nrngs + 1);
2313 
2314     if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
2315         return -1;
2316 
2317     if (qemuDomainNamespaceSetupRNG(vm, rng, &teardowndevice) < 0)
2318         goto cleanup;
2319 
2320     if (qemuSetupRNGCgroup(vm, rng) < 0)
2321         goto cleanup;
2322     teardowncgroup = true;
2323 
2324     /* build required metadata */
2325     if (!(devprops = qemuBuildRNGDevProps(vm->def, rng, priv->qemuCaps)))
2326         goto cleanup;
2327 
2328     if (qemuBuildRNGBackendProps(rng, &props) < 0)
2329         goto cleanup;
2330 
2331     if (!(charAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
2332         goto cleanup;
2333 
2334     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) {
2335         if (qemuDomainAddChardevTLSObjects(driver, vm,
2336                                            rng->source.chardev,
2337                                            rng->info.alias, charAlias,
2338                                            &tlsAlias, &secAlias) < 0)
2339             goto audit;
2340     }
2341 
2342     qemuDomainObjEnterMonitor(driver, vm);
2343 
2344     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
2345         qemuHotplugChardevAttach(priv->mon, charAlias, rng->source.chardev) < 0)
2346         goto exit_monitor;
2347     chardevAdded = true;
2348 
2349     if (qemuMonitorAddObject(priv->mon, &props, &objAlias) < 0)
2350         goto exit_monitor;
2351 
2352     if (qemuDomainAttachExtensionDevice(priv->mon, &rng->info) < 0)
2353         goto exit_monitor;
2354 
2355     if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) {
2356         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &rng->info));
2357         goto exit_monitor;
2358     }
2359 
2360     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
2361         releaseaddr = false;
2362         goto cleanup;
2363     }
2364 
2365     VIR_APPEND_ELEMENT_INPLACE(vm->def->rngs, vm->def->nrngs, rng);
2366 
2367     ret = 0;
2368 
2369  audit:
2370     virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0);
2371  cleanup:
2372     virJSONValueFree(props);
2373     if (ret < 0) {
2374         if (releaseaddr)
2375             qemuDomainReleaseDeviceAddress(vm, &rng->info);
2376         if (teardowncgroup && qemuTeardownRNGCgroup(vm, rng) < 0)
2377             VIR_WARN("Unable to remove RNG device cgroup ACL on hotplug fail");
2378         if (teardowndevice && qemuDomainNamespaceTeardownRNG(vm, rng) < 0)
2379             VIR_WARN("Unable to remove chr device from /dev");
2380     }
2381 
2382     return ret;
2383 
2384  exit_monitor:
2385     virErrorPreserveLast(&orig_err);
2386     if (objAlias)
2387         ignore_value(qemuMonitorDelObject(priv->mon, objAlias, false));
2388     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD && chardevAdded)
2389         ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
2390     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2391         releaseaddr = false;
2392     virErrorRestore(&orig_err);
2393 
2394     qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
2395                             secAlias, tlsAlias);
2396     goto audit;
2397 }
2398 
2399 
2400 /**
2401  * qemuDomainAttachMemory:
2402  * @driver: qemu driver data
2403  * @vm: VM object
2404  * @mem: Definition of the memory device to be attached. @mem is always consumed
2405  *
2406  * Attaches memory device described by @mem to domain @vm.
2407  *
2408  * Returns 0 on success -1 on error.
2409  */
2410 int
qemuDomainAttachMemory(virQEMUDriver * driver,virDomainObj * vm,virDomainMemoryDef * mem)2411 qemuDomainAttachMemory(virQEMUDriver *driver,
2412                        virDomainObj *vm,
2413                        virDomainMemoryDef *mem)
2414 {
2415     qemuDomainObjPrivate *priv = vm->privateData;
2416     virErrorPtr orig_err;
2417     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
2418     unsigned long long oldmem = virDomainDefGetMemoryTotal(vm->def);
2419     unsigned long long newmem = oldmem + mem->size;
2420     g_autoptr(virJSONValue) devprops = NULL;
2421     g_autofree char *objalias = NULL;
2422     bool objAdded = false;
2423     bool releaseaddr = false;
2424     bool teardownlabel = false;
2425     bool teardowncgroup = false;
2426     bool teardowndevice = false;
2427     virJSONValue *props = NULL;
2428     virObjectEvent *event;
2429     int id;
2430     int ret = -1;
2431 
2432     if (qemuDomainMemoryDeviceAlignSize(vm->def, mem) < 0)
2433         goto cleanup;
2434 
2435     if (qemuDomainDefValidateMemoryHotplug(vm->def, mem) < 0)
2436         goto cleanup;
2437 
2438     if (qemuDomainAssignMemoryDeviceSlot(vm, mem) < 0)
2439         goto cleanup;
2440     releaseaddr = true;
2441 
2442     /* in cases where we are using a VM with aliases generated according to the
2443      * index of the memory device we need to keep continue using that scheme */
2444     if (qemuAssignDeviceMemoryAlias(vm->def, mem, priv->memAliasOrderMismatch) < 0)
2445         goto cleanup;
2446 
2447     objalias = g_strdup_printf("mem%s", mem->info.alias);
2448 
2449     if (!(devprops = qemuBuildMemoryDeviceProps(vm->def, mem)))
2450         goto cleanup;
2451 
2452     if (qemuBuildMemoryBackendProps(&props, objalias, cfg,
2453                                     priv, vm->def, mem, true, false) < 0)
2454         goto cleanup;
2455 
2456     if (qemuProcessBuildDestroyMemoryPaths(driver, vm, mem, true) < 0)
2457         goto cleanup;
2458 
2459     if (qemuDomainNamespaceSetupMemory(vm, mem, &teardowndevice) < 0)
2460         goto cleanup;
2461 
2462     if (qemuSetupMemoryDevicesCgroup(vm, mem) < 0)
2463         goto cleanup;
2464     teardowncgroup = true;
2465 
2466     if (qemuSecuritySetMemoryLabel(driver, vm, mem) < 0)
2467         goto cleanup;
2468     teardownlabel = true;
2469 
2470     if (virDomainMemoryInsert(vm->def, mem) < 0)
2471         goto cleanup;
2472 
2473     if (qemuDomainAdjustMaxMemLock(vm, false) < 0)
2474         goto removedef;
2475 
2476     qemuDomainObjEnterMonitor(driver, vm);
2477     if (qemuMonitorAddObject(priv->mon, &props, NULL) < 0)
2478         goto exit_monitor;
2479     objAdded = true;
2480 
2481     if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0)
2482         goto exit_monitor;
2483 
2484     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
2485         /* we shouldn't touch mem now, as the def might be freed */
2486         mem = NULL;
2487         goto audit;
2488     }
2489 
2490     event = virDomainEventDeviceAddedNewFromObj(vm, objalias);
2491     virObjectEventStateQueue(driver->domainEventState, event);
2492 
2493     /* fix the balloon size */
2494     ignore_value(qemuProcessRefreshBalloonState(driver, vm, QEMU_ASYNC_JOB_NONE));
2495 
2496     /* mem is consumed by vm->def */
2497     mem = NULL;
2498 
2499     /* this step is best effort, removing the device would be so much trouble */
2500     ignore_value(qemuDomainUpdateMemoryDeviceInfo(driver, vm,
2501                                                   QEMU_ASYNC_JOB_NONE));
2502 
2503     ret = 0;
2504 
2505  audit:
2506     virDomainAuditMemory(vm, oldmem, newmem, "update", ret == 0);
2507  cleanup:
2508     if (mem && ret < 0) {
2509         if (teardowncgroup && qemuTeardownMemoryDevicesCgroup(vm, mem) < 0)
2510             VIR_WARN("Unable to remove memory device cgroup ACL on hotplug fail");
2511         if (teardownlabel && qemuSecurityRestoreMemoryLabel(driver, vm, mem) < 0)
2512             VIR_WARN("Unable to restore security label on memdev");
2513         if (teardowndevice &&
2514             qemuDomainNamespaceTeardownMemory(vm, mem) <  0)
2515             VIR_WARN("Unable to remove memory device from /dev");
2516         if (releaseaddr)
2517             qemuDomainReleaseMemoryDeviceSlot(vm, mem);
2518     }
2519 
2520     virJSONValueFree(props);
2521     virDomainMemoryDefFree(mem);
2522     return ret;
2523 
2524  exit_monitor:
2525     virErrorPreserveLast(&orig_err);
2526     if (objAdded)
2527         ignore_value(qemuMonitorDelObject(priv->mon, objalias, false));
2528     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2529         mem = NULL;
2530 
2531     if (objAdded && mem)
2532         ignore_value(qemuProcessDestroyMemoryBackingPath(driver, vm, mem));
2533 
2534     virErrorRestore(&orig_err);
2535     if (!mem)
2536         goto audit;
2537 
2538  removedef:
2539     if ((id = virDomainMemoryFindByDef(vm->def, mem)) >= 0)
2540         mem = virDomainMemoryRemove(vm->def, id);
2541     else
2542         mem = NULL;
2543 
2544     /* reset the mlock limit */
2545     virErrorPreserveLast(&orig_err);
2546     ignore_value(qemuDomainAdjustMaxMemLock(vm, false));
2547     virErrorRestore(&orig_err);
2548 
2549     goto audit;
2550 }
2551 
2552 
2553 static int
qemuDomainAttachHostUSBDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)2554 qemuDomainAttachHostUSBDevice(virQEMUDriver *driver,
2555                               virDomainObj *vm,
2556                               virDomainHostdevDef *hostdev)
2557 {
2558     qemuDomainObjPrivate *priv = vm->privateData;
2559     g_autoptr(virJSONValue) devprops = NULL;
2560     bool added = false;
2561     bool teardowncgroup = false;
2562     bool teardownlabel = false;
2563     bool teardowndevice = false;
2564     int ret = -1;
2565 
2566     if (virDomainUSBAddressEnsure(priv->usbaddrs, hostdev->info) < 0)
2567         return -1;
2568 
2569     if (qemuHostdevPrepareUSBDevices(driver, vm->def->name, &hostdev, 1, 0) < 0)
2570         goto cleanup;
2571 
2572     added = true;
2573 
2574     if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
2575         goto cleanup;
2576 
2577     if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
2578         goto cleanup;
2579     teardowncgroup = true;
2580 
2581     if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
2582         goto cleanup;
2583     teardownlabel = true;
2584 
2585     qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1);
2586 
2587     if (!(devprops = qemuBuildUSBHostdevDevProps(vm->def, hostdev, priv->qemuCaps)))
2588         goto cleanup;
2589 
2590     VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1);
2591 
2592     qemuDomainObjEnterMonitor(driver, vm);
2593     ret = qemuMonitorAddDeviceProps(priv->mon, &devprops);
2594     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
2595         ret = -1;
2596         goto cleanup;
2597     }
2598     virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
2599     if (ret < 0)
2600         goto cleanup;
2601 
2602     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
2603 
2604     ret = 0;
2605  cleanup:
2606     if (ret < 0) {
2607         if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
2608             VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
2609         if (teardownlabel &&
2610             qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
2611             VIR_WARN("Unable to restore host device labelling on hotplug fail");
2612         if (teardowndevice &&
2613             qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
2614             VIR_WARN("Unable to remove host device from /dev");
2615         if (added)
2616             qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
2617         virDomainUSBAddressRelease(priv->usbaddrs, hostdev->info);
2618     }
2619     return ret;
2620 }
2621 
2622 
2623 static int
qemuDomainAttachHostSCSIDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)2624 qemuDomainAttachHostSCSIDevice(virQEMUDriver *driver,
2625                                virDomainObj *vm,
2626                                virDomainHostdevDef *hostdev)
2627 {
2628     size_t i;
2629     int ret = -1;
2630     qemuDomainObjPrivate *priv = vm->privateData;
2631     virErrorPtr orig_err;
2632     g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
2633     const char *backendalias = NULL;
2634     g_autoptr(virJSONValue) devprops = NULL;
2635     bool teardowncgroup = false;
2636     bool teardownlabel = false;
2637     bool teardowndevice = false;
2638 
2639     /* Let's make sure the disk has a controller defined and loaded before
2640      * trying to add it. The controller used by the disk must exist before a
2641      * qemu command line string is generated.
2642      *
2643      * Ensure that the given controller and all controllers with a smaller index
2644      * exist; there must not be any missing index in between.
2645      */
2646     for (i = 0; i <= hostdev->info->addr.drive.controller; i++) {
2647         if (!qemuDomainFindOrCreateSCSIDiskController(driver, vm, i))
2648             return -1;
2649     }
2650 
2651     if (qemuHostdevPrepareSCSIDevices(driver, vm->def->name, &hostdev, 1) < 0)
2652         return -1;
2653 
2654     if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
2655         goto cleanup;
2656 
2657     if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
2658         goto cleanup;
2659     teardowncgroup = true;
2660 
2661     if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
2662         goto cleanup;
2663     teardownlabel = true;
2664 
2665     qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1);
2666 
2667     if (qemuDomainPrepareHostdev(hostdev, priv) < 0)
2668         goto cleanup;
2669 
2670     if (qemuProcessPrepareHostHostdev(hostdev) < 0)
2671         goto cleanup;
2672 
2673     if (!(data = qemuBuildHostdevSCSIAttachPrepare(hostdev, &backendalias,
2674                                                    priv->qemuCaps)))
2675         goto cleanup;
2676 
2677     if (!(devprops = qemuBuildSCSIHostdevDevProps(vm->def, hostdev, backendalias)))
2678         goto cleanup;
2679 
2680     VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
2681 
2682     qemuDomainObjEnterMonitor(driver, vm);
2683 
2684     if (qemuBlockStorageSourceAttachApply(priv->mon, data) < 0)
2685         goto exit_monitor;
2686 
2687     if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0)
2688         goto exit_monitor;
2689 
2690     if (qemuDomainObjExitMonitor(driver, vm) < 0)
2691         goto cleanup;
2692 
2693     virDomainAuditHostdev(vm, hostdev, "attach", true);
2694 
2695     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
2696 
2697     ret = 0;
2698 
2699  cleanup:
2700     if (ret < 0) {
2701         qemuHostdevReAttachSCSIDevices(driver, vm->def->name, &hostdev, 1);
2702         if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
2703             VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
2704         if (teardownlabel &&
2705             qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
2706             VIR_WARN("Unable to restore host device labelling on hotplug fail");
2707         if (teardowndevice &&
2708             qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
2709             VIR_WARN("Unable to remove host device from /dev");
2710     }
2711     qemuDomainSecretHostdevDestroy(hostdev);
2712     return ret;
2713 
2714  exit_monitor:
2715     virErrorPreserveLast(&orig_err);
2716     qemuBlockStorageSourceAttachRollback(priv->mon, data);
2717     ignore_value(qemuDomainObjExitMonitor(driver, vm));
2718     virErrorRestore(&orig_err);
2719 
2720     virDomainAuditHostdev(vm, hostdev, "attach", false);
2721 
2722     goto cleanup;
2723 }
2724 
2725 static int
qemuDomainAttachSCSIVHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)2726 qemuDomainAttachSCSIVHostDevice(virQEMUDriver *driver,
2727                                 virDomainObj *vm,
2728                                 virDomainHostdevDef *hostdev)
2729 {
2730     int ret = -1;
2731     qemuDomainObjPrivate *priv = vm->privateData;
2732     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
2733                                { .hostdev = hostdev } };
2734     virDomainCCWAddressSet *ccwaddrs = NULL;
2735     g_autofree char *vhostfdName = NULL;
2736     int vhostfd = -1;
2737     g_autoptr(virJSONValue) devprops = NULL;
2738     bool removeextension = false;
2739     bool removehandle = false;
2740     bool teardowncgroup = false;
2741     bool teardownlabel = false;
2742     bool teardowndevice = false;
2743     bool releaseaddr = false;
2744 
2745     if (qemuHostdevPrepareSCSIVHostDevices(driver, vm->def->name, &hostdev, 1) < 0)
2746         return -1;
2747 
2748     if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
2749         goto cleanup;
2750 
2751     if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
2752         goto cleanup;
2753     teardowncgroup = true;
2754 
2755     if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
2756         goto cleanup;
2757     teardownlabel = true;
2758 
2759     if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0)
2760         goto cleanup;
2761 
2762     vhostfdName = g_strdup_printf("vhostfd-%d", vhostfd);
2763 
2764     if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
2765         if (qemuDomainIsS390CCW(vm->def) &&
2766             virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CCW))
2767             hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
2768     }
2769 
2770     if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
2771         hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
2772         if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
2773             goto cleanup;
2774     } else if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
2775         if (!(ccwaddrs = virDomainCCWAddressSetCreateFromDomain(vm->def)))
2776             goto cleanup;
2777         if (virDomainCCWAddressAssign(hostdev->info, ccwaddrs,
2778                                       !hostdev->info->addr.ccw.assigned) < 0)
2779             goto cleanup;
2780     }
2781     releaseaddr = true;
2782 
2783     qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1);
2784 
2785     if (!(devprops = qemuBuildSCSIVHostHostdevDevProps(vm->def,
2786                                                        hostdev,
2787                                                        priv->qemuCaps,
2788                                                        vhostfdName)))
2789         goto cleanup;
2790 
2791     VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
2792 
2793     qemuDomainObjEnterMonitor(driver, vm);
2794 
2795     if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
2796         goto exit_monitor;
2797 
2798     removeextension = true;
2799 
2800     if ((ret = qemuMonitorSendFileHandle(priv->mon, vhostfdName, vhostfd)))
2801         goto exit_monitor;
2802 
2803     removehandle = true;
2804 
2805     if ((ret = qemuMonitorAddDeviceProps(priv->mon, &devprops)) < 0)
2806         goto exit_monitor;
2807 
2808     removeextension = false;
2809     removehandle = false;
2810 
2811  exit_monitor:
2812     if (removehandle)
2813         ignore_value(qemuMonitorCloseFileHandle(priv->mon, vhostfdName));
2814     if (removeextension)
2815         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
2816     if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
2817         goto audit;
2818 
2819     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
2820     ret = 0;
2821 
2822  audit:
2823     virDomainAuditHostdev(vm, hostdev, "attach", (ret == 0));
2824 
2825  cleanup:
2826     if (ret < 0) {
2827         if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
2828             VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
2829         if (teardownlabel &&
2830             qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
2831             VIR_WARN("Unable to restore host device labelling on hotplug fail");
2832         if (teardowndevice &&
2833             qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
2834             VIR_WARN("Unable to remove host device from /dev");
2835         if (releaseaddr)
2836             qemuDomainReleaseDeviceAddress(vm, hostdev->info);
2837     }
2838 
2839     virDomainCCWAddressSetFree(ccwaddrs);
2840 
2841     VIR_FORCE_CLOSE(vhostfd);
2842     return ret;
2843 }
2844 
2845 
2846 static int
qemuDomainAttachMediatedDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)2847 qemuDomainAttachMediatedDevice(virQEMUDriver *driver,
2848                                virDomainObj *vm,
2849                                virDomainHostdevDef *hostdev)
2850 {
2851     int ret = -1;
2852     g_autoptr(virJSONValue) devprops = NULL;
2853     bool added = false;
2854     bool teardowncgroup = false;
2855     bool teardownlabel = false;
2856     bool teardowndevice = false;
2857     bool teardownmemlock = false;
2858     qemuDomainObjPrivate *priv = vm->privateData;
2859     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
2860                                 { .hostdev = hostdev } };
2861 
2862     switch (hostdev->source.subsys.u.mdev.model) {
2863     case VIR_MDEV_MODEL_TYPE_VFIO_PCI:
2864         if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
2865             return -1;
2866         break;
2867     case VIR_MDEV_MODEL_TYPE_VFIO_CCW: {
2868         bool releaseaddr = false;
2869 
2870         if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
2871             return -1;
2872     }   break;
2873     case VIR_MDEV_MODEL_TYPE_LAST:
2874         break;
2875     }
2876 
2877     if (qemuHostdevPrepareMediatedDevices(driver,
2878                                           vm->def->name,
2879                                           &hostdev,
2880                                           1) < 0)
2881         goto cleanup;
2882     added = true;
2883 
2884     if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
2885         goto cleanup;
2886 
2887     if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
2888         goto cleanup;
2889     teardowncgroup = true;
2890 
2891     if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
2892         goto cleanup;
2893     teardownlabel = true;
2894 
2895     qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1);
2896 
2897     if (!(devprops = qemuBuildHostdevMediatedDevProps(vm->def, hostdev)))
2898         goto cleanup;
2899 
2900     VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
2901 
2902     if (qemuDomainAdjustMaxMemLockHostdev(vm, hostdev) < 0)
2903         goto cleanup;
2904     teardownmemlock = true;
2905 
2906     qemuDomainObjEnterMonitor(driver, vm);
2907     ret = qemuMonitorAddDeviceProps(priv->mon, &devprops);
2908     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
2909         ret = -1;
2910         goto cleanup;
2911     }
2912 
2913     virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
2914     if (ret < 0)
2915         goto cleanup;
2916 
2917     VIR_APPEND_ELEMENT_INPLACE(vm->def->hostdevs, vm->def->nhostdevs, hostdev);
2918     ret = 0;
2919  cleanup:
2920     if (ret < 0) {
2921         if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm, false) < 0)
2922             VIR_WARN("Unable to reset maximum locked memory on hotplug fail");
2923         if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
2924             VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
2925         if (teardownlabel &&
2926             qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
2927             VIR_WARN("Unable to restore host device labelling on hotplug fail");
2928         if (teardowndevice &&
2929             qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
2930             VIR_WARN("Unable to remove host device from /dev");
2931         if (added)
2932             qemuHostdevReAttachMediatedDevices(driver,
2933                                                vm->def->name,
2934                                                &hostdev,
2935                                                1);
2936         qemuDomainReleaseDeviceAddress(vm, hostdev->info);
2937     }
2938     return ret;
2939 }
2940 
2941 
2942 int
qemuDomainAttachHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)2943 qemuDomainAttachHostDevice(virQEMUDriver *driver,
2944                            virDomainObj *vm,
2945                            virDomainHostdevDef *hostdev)
2946 {
2947     if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
2948         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2949                        _("hotplug is not supported for hostdev mode '%s'"),
2950                        virDomainHostdevModeTypeToString(hostdev->mode));
2951         return -1;
2952     }
2953 
2954     switch (hostdev->source.subsys.type) {
2955     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
2956         if (qemuDomainAttachHostPCIDevice(driver, vm,
2957                                           hostdev) < 0)
2958             return -1;
2959         break;
2960 
2961     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
2962         if (qemuDomainAttachHostUSBDevice(driver, vm,
2963                                           hostdev) < 0)
2964             return -1;
2965         break;
2966 
2967     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
2968         if (qemuDomainAttachHostSCSIDevice(driver, vm,
2969                                            hostdev) < 0)
2970             return -1;
2971         break;
2972 
2973     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
2974         if (qemuDomainAttachSCSIVHostDevice(driver, vm, hostdev) < 0)
2975             return -1;
2976         break;
2977     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
2978         if (qemuDomainAttachMediatedDevice(driver, vm, hostdev) < 0)
2979             return -1;
2980         break;
2981 
2982     default:
2983         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2984                        _("hotplug is not supported for hostdev subsys type '%s'"),
2985                        virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
2986         return -1;
2987     }
2988 
2989     return 0;
2990 }
2991 
2992 
2993 int
qemuDomainAttachShmemDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainShmemDef * shmem)2994 qemuDomainAttachShmemDevice(virQEMUDriver *driver,
2995                             virDomainObj *vm,
2996                             virDomainShmemDef *shmem)
2997 {
2998     int ret = -1;
2999     g_autoptr(virJSONValue) devProps = NULL;
3000     g_autofree char *charAlias = NULL;
3001     g_autofree char *memAlias = NULL;
3002     bool release_backing = false;
3003     bool release_address = true;
3004     virErrorPtr orig_err = NULL;
3005     virJSONValue *props = NULL;
3006     qemuDomainObjPrivate *priv = vm->privateData;
3007     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_SHMEM, { .shmem = shmem } };
3008 
3009     switch (shmem->model) {
3010     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
3011     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
3012         break;
3013 
3014     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
3015         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3016                        _("live attach of shmem model '%s' is not supported"),
3017                        virDomainShmemModelTypeToString(shmem->model));
3018         G_GNUC_FALLTHROUGH;
3019     case VIR_DOMAIN_SHMEM_MODEL_LAST:
3020         return -1;
3021     }
3022 
3023     qemuAssignDeviceShmemAlias(vm->def, shmem, -1);
3024 
3025     qemuDomainPrepareShmemChardev(shmem);
3026 
3027     VIR_REALLOC_N(vm->def->shmems, vm->def->nshmems + 1);
3028 
3029     if ((shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
3030          shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
3031         (qemuDomainEnsurePCIAddress(vm, &dev) < 0))
3032         return -1;
3033 
3034     if (!(devProps = qemuBuildShmemDevProps(vm->def, shmem)))
3035         goto cleanup;
3036 
3037     if (shmem->server.enabled) {
3038         charAlias = g_strdup_printf("char%s", shmem->info.alias);
3039     } else {
3040         if (!(props = qemuBuildShmemBackendMemProps(shmem)))
3041             goto cleanup;
3042 
3043     }
3044 
3045     qemuDomainObjEnterMonitor(driver, vm);
3046 
3047     if (shmem->server.enabled) {
3048         if (qemuHotplugChardevAttach(priv->mon, charAlias, shmem->server.chr) < 0)
3049             goto exit_monitor;
3050     } else {
3051         if (qemuMonitorAddObject(priv->mon, &props, &memAlias) < 0)
3052             goto exit_monitor;
3053     }
3054 
3055     release_backing = true;
3056 
3057     if (qemuDomainAttachExtensionDevice(priv->mon, &shmem->info) < 0)
3058         goto exit_monitor;
3059 
3060     if (qemuMonitorAddDeviceProps(priv->mon, &devProps) < 0) {
3061         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &shmem->info));
3062         goto exit_monitor;
3063     }
3064 
3065     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
3066         release_address = false;
3067         goto cleanup;
3068     }
3069 
3070     /* Doing a copy here just so the pointer doesn't get nullified
3071      * because we need it in the audit function */
3072     VIR_APPEND_ELEMENT_COPY_INPLACE(vm->def->shmems, vm->def->nshmems, shmem);
3073 
3074     ret = 0;
3075     release_address = false;
3076 
3077  audit:
3078     virDomainAuditShmem(vm, shmem, "attach", ret == 0);
3079 
3080  cleanup:
3081     if (release_address)
3082         qemuDomainReleaseDeviceAddress(vm, &shmem->info);
3083 
3084     virJSONValueFree(props);
3085 
3086     return ret;
3087 
3088  exit_monitor:
3089     virErrorPreserveLast(&orig_err);
3090     if (release_backing) {
3091         if (shmem->server.enabled)
3092             ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
3093         else
3094             ignore_value(qemuMonitorDelObject(priv->mon, memAlias, false));
3095     }
3096 
3097     if (qemuDomainObjExitMonitor(driver, vm) < 0)
3098         release_address = false;
3099 
3100     virErrorRestore(&orig_err);
3101 
3102     goto audit;
3103 }
3104 
3105 
3106 int
qemuDomainAttachWatchdog(virQEMUDriver * driver,virDomainObj * vm,virDomainWatchdogDef * watchdog)3107 qemuDomainAttachWatchdog(virQEMUDriver *driver,
3108                          virDomainObj *vm,
3109                          virDomainWatchdogDef *watchdog)
3110 {
3111     int ret = -1;
3112     qemuDomainObjPrivate *priv = vm->privateData;
3113     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_WATCHDOG, { .watchdog = watchdog } };
3114     g_autoptr(virJSONValue) props = NULL;
3115     bool releaseAddress = false;
3116     int rv;
3117 
3118     if (vm->def->watchdog) {
3119         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3120                        _("domain already has a watchdog"));
3121         return -1;
3122     }
3123 
3124     qemuAssignDeviceWatchdogAlias(watchdog);
3125 
3126     if (watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
3127         if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
3128             goto cleanup;
3129         releaseAddress = true;
3130     } else {
3131         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3132                        _("hotplug of watchdog of model %s is not supported"),
3133                        virDomainWatchdogModelTypeToString(watchdog->model));
3134         goto cleanup;
3135     }
3136 
3137     if (!(props = qemuBuildWatchdogDevProps(vm->def, watchdog)))
3138         goto cleanup;
3139 
3140     qemuDomainObjEnterMonitor(driver, vm);
3141 
3142     /* QEMU doesn't have a 'dump' action; we tell qemu to 'pause', then
3143        libvirt listens for the watchdog event, and we perform the dump
3144        ourselves. so convert 'dump' to 'pause' for the qemu cli */
3145     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) {
3146         qemuMonitorActionWatchdog watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_KEEP;
3147 
3148         switch (watchdog->action) {
3149         case VIR_DOMAIN_WATCHDOG_ACTION_RESET:
3150             watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_RESET;
3151             break;
3152 
3153         case VIR_DOMAIN_WATCHDOG_ACTION_SHUTDOWN:
3154             watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_SHUTDOWN;
3155             break;
3156 
3157         case VIR_DOMAIN_WATCHDOG_ACTION_POWEROFF:
3158             watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_POWEROFF;
3159             break;
3160 
3161         case VIR_DOMAIN_WATCHDOG_ACTION_PAUSE:
3162         case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
3163             watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_PAUSE;
3164             break;
3165 
3166         case VIR_DOMAIN_WATCHDOG_ACTION_NONE:
3167             watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_NONE;
3168             break;
3169 
3170         case VIR_DOMAIN_WATCHDOG_ACTION_INJECTNMI:
3171             watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_INJECT_NMI;
3172             break;
3173 
3174         case VIR_DOMAIN_WATCHDOG_ACTION_LAST:
3175         default:
3176             break;
3177         };
3178 
3179         rv = qemuMonitorSetAction(priv->mon,
3180                                   QEMU_MONITOR_ACTION_SHUTDOWN_KEEP,
3181                                   QEMU_MONITOR_ACTION_REBOOT_KEEP,
3182                                   watchdogaction,
3183                                   QEMU_MONITOR_ACTION_PANIC_KEEP);
3184     } else {
3185         virDomainWatchdogAction actualAction = watchdog->action;
3186 
3187         if (actualAction == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
3188             actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
3189 
3190         rv = qemuMonitorSetWatchdogAction(priv->mon,
3191                                           virDomainWatchdogActionTypeToString(actualAction));
3192     }
3193 
3194     if (rv >= 0)
3195         rv = qemuMonitorAddDeviceProps(priv->mon, &props);
3196 
3197     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
3198         releaseAddress = false;
3199         goto cleanup;
3200     }
3201 
3202     if (rv < 0)
3203         goto cleanup;
3204 
3205     releaseAddress = false;
3206     vm->def->watchdog = watchdog;
3207     ret = 0;
3208 
3209  cleanup:
3210     if (releaseAddress)
3211         qemuDomainReleaseDeviceAddress(vm, &watchdog->info);
3212     return ret;
3213 }
3214 
3215 
3216 int
qemuDomainAttachInputDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainInputDef * input)3217 qemuDomainAttachInputDevice(virQEMUDriver *driver,
3218                             virDomainObj *vm,
3219                             virDomainInputDef *input)
3220 {
3221     int ret = -1;
3222     g_autoptr(virJSONValue) devprops = NULL;
3223     qemuDomainObjPrivate *priv = vm->privateData;
3224     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_INPUT,
3225                                { .input = input } };
3226     virErrorPtr originalError = NULL;
3227     bool releaseaddr = false;
3228     bool teardowndevice = false;
3229     bool teardownlabel = false;
3230     bool teardowncgroup = false;
3231 
3232     qemuAssignDeviceInputAlias(vm->def, input, -1);
3233 
3234     switch ((virDomainInputBus) input->bus) {
3235     case VIR_DOMAIN_INPUT_BUS_USB:
3236         if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0)
3237             return -1;
3238 
3239         releaseaddr = true;
3240 
3241         if (!(devprops = qemuBuildInputUSBDevProps(vm->def, input)))
3242             goto cleanup;
3243         break;
3244 
3245     case VIR_DOMAIN_INPUT_BUS_VIRTIO:
3246         if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
3247             goto cleanup;
3248 
3249         if (!(devprops = qemuBuildInputVirtioDevProps(vm->def, input, priv->qemuCaps)))
3250             goto cleanup;
3251         break;
3252 
3253     case VIR_DOMAIN_INPUT_BUS_PS2:
3254     case VIR_DOMAIN_INPUT_BUS_XEN:
3255     case VIR_DOMAIN_INPUT_BUS_PARALLELS:
3256     case VIR_DOMAIN_INPUT_BUS_NONE:
3257     case VIR_DOMAIN_INPUT_BUS_LAST:
3258         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3259                        _("input device on bus '%s' cannot be hot plugged."),
3260                        virDomainInputBusTypeToString(input->bus));
3261         return -1;
3262     }
3263 
3264     if (qemuDomainNamespaceSetupInput(vm, input, &teardowndevice) < 0)
3265         goto cleanup;
3266 
3267     if (qemuSetupInputCgroup(vm, input) < 0)
3268         goto cleanup;
3269     teardowncgroup = true;
3270 
3271     if (qemuSecuritySetInputLabel(vm, input) < 0)
3272         goto cleanup;
3273     teardownlabel = true;
3274 
3275     VIR_REALLOC_N(vm->def->inputs, vm->def->ninputs + 1);
3276 
3277     qemuDomainObjEnterMonitor(driver, vm);
3278 
3279     if (qemuDomainAttachExtensionDevice(priv->mon, &input->info) < 0)
3280         goto exit_monitor;
3281 
3282     if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) {
3283         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info));
3284         goto exit_monitor;
3285     }
3286 
3287     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
3288         releaseaddr = false;
3289         goto cleanup;
3290     }
3291 
3292     VIR_APPEND_ELEMENT_COPY_INPLACE(vm->def->inputs, vm->def->ninputs, input);
3293 
3294     ret = 0;
3295 
3296  audit:
3297     virDomainAuditInput(vm, input, "attach", ret == 0);
3298 
3299  cleanup:
3300     if (ret < 0) {
3301         virErrorPreserveLast(&originalError);
3302         if (teardownlabel)
3303             qemuSecurityRestoreInputLabel(vm, input);
3304         if (teardowncgroup)
3305             qemuTeardownInputCgroup(vm, input);
3306         if (teardowndevice)
3307             qemuDomainNamespaceTeardownInput(vm, input);
3308         if (releaseaddr)
3309             qemuDomainReleaseDeviceAddress(vm, &input->info);
3310         virErrorRestore(&originalError);
3311     }
3312 
3313     return ret;
3314 
3315  exit_monitor:
3316     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
3317         releaseaddr = false;
3318         goto cleanup;
3319     }
3320     goto audit;
3321 }
3322 
3323 
3324 int
qemuDomainAttachVsockDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainVsockDef * vsock)3325 qemuDomainAttachVsockDevice(virQEMUDriver *driver,
3326                             virDomainObj *vm,
3327                             virDomainVsockDef *vsock)
3328 {
3329     qemuDomainVsockPrivate *vsockPriv = (qemuDomainVsockPrivate *)vsock->privateData;
3330     qemuDomainObjPrivate *priv = vm->privateData;
3331     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_VSOCK,
3332                                { .vsock = vsock } };
3333     virErrorPtr originalError = NULL;
3334     const char *fdprefix = "vsockfd";
3335     bool releaseaddr = false;
3336     g_autofree char *fdname = NULL;
3337     g_autoptr(virJSONValue) devprops = NULL;
3338     bool removeextension = false;
3339     bool removehandle = false;
3340     int ret = -1;
3341 
3342     if (vm->def->vsock) {
3343         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3344                        _("the domain already has a vsock device"));
3345         return -1;
3346     }
3347 
3348     if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
3349         return -1;
3350 
3351     qemuAssignDeviceVsockAlias(vsock);
3352 
3353     if (qemuProcessOpenVhostVsock(vsock) < 0)
3354         goto cleanup;
3355 
3356     fdname = g_strdup_printf("%s%u", fdprefix, vsockPriv->vhostfd);
3357 
3358     if (!(devprops = qemuBuildVsockDevProps(vm->def, vsock, priv->qemuCaps, fdprefix)))
3359         goto cleanup;
3360 
3361     qemuDomainObjEnterMonitor(driver, vm);
3362 
3363     if (qemuDomainAttachExtensionDevice(priv->mon, &vsock->info) < 0)
3364         goto exit_monitor;
3365 
3366     removeextension = true;
3367 
3368     if ((ret = qemuMonitorSendFileHandle(priv->mon, fdname, vsockPriv->vhostfd)) < 0)
3369         goto exit_monitor;
3370 
3371     removehandle = true;
3372 
3373     if ((ret = qemuMonitorAddDeviceProps(priv->mon, &devprops)) < 0)
3374         goto exit_monitor;
3375 
3376     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
3377         releaseaddr = false;
3378         goto cleanup;
3379     }
3380 
3381     vm->def->vsock = g_steal_pointer(&vsock);
3382 
3383     ret = 0;
3384 
3385  cleanup:
3386     if (ret < 0) {
3387         virErrorPreserveLast(&originalError);
3388         if (releaseaddr)
3389             qemuDomainReleaseDeviceAddress(vm, &vsock->info);
3390         virErrorRestore(&originalError);
3391     }
3392 
3393     return ret;
3394 
3395  exit_monitor:
3396     if (removehandle)
3397         ignore_value(qemuMonitorCloseFileHandle(priv->mon, fdname));
3398     if (removeextension)
3399         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &vsock->info));
3400     if (qemuDomainObjExitMonitor(driver, vm) < 0)
3401         releaseaddr = false;
3402     goto cleanup;
3403 }
3404 
3405 
3406 int
qemuDomainAttachFSDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainFSDef * fs)3407 qemuDomainAttachFSDevice(virQEMUDriver *driver,
3408                          virDomainObj *vm,
3409                          virDomainFSDef *fs)
3410 {
3411     qemuDomainObjPrivate *priv = vm->privateData;
3412     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_FS,
3413                                { .fs = fs } };
3414     g_autoptr(virDomainChrSourceDef) chardev = NULL;
3415     g_autoptr(virJSONValue) devprops = NULL;
3416     virErrorPtr origErr = NULL;
3417     bool releaseaddr = false;
3418     bool chardevAdded = false;
3419     bool started = false;
3420     g_autofree char *charAlias = NULL;
3421     int ret = -1;
3422 
3423     if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
3424         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3425                        _("only virtiofs filesystems can be hotplugged"));
3426         return -1;
3427     }
3428 
3429     if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
3430         return -1;
3431 
3432     qemuAssignDeviceFSAlias(vm->def, fs);
3433 
3434     chardev = virDomainChrSourceDefNew(priv->driver->xmlopt);
3435     chardev->type = VIR_DOMAIN_CHR_TYPE_UNIX;
3436     chardev->data.nix.path = qemuDomainGetVHostUserFSSocketPath(priv, fs);
3437 
3438     charAlias = qemuDomainGetVhostUserChrAlias(fs->info.alias);
3439 
3440     if (!(devprops = qemuBuildVHostUserFsDevProps(fs, vm->def, charAlias, priv)))
3441         goto cleanup;
3442 
3443     if (!fs->sock) {
3444         if (qemuVirtioFSPrepareDomain(driver, fs) < 0)
3445             goto cleanup;
3446 
3447         if (qemuVirtioFSStart(driver, vm, fs) < 0)
3448             goto cleanup;
3449         started = true;
3450 
3451         if (qemuVirtioFSSetupCgroup(vm, fs, priv->cgroup) < 0)
3452             goto cleanup;
3453     }
3454 
3455     qemuDomainObjEnterMonitor(driver, vm);
3456 
3457     if (qemuHotplugChardevAttach(priv->mon, charAlias, chardev) < 0)
3458         goto exit_monitor;
3459     chardevAdded = true;
3460 
3461     if (qemuDomainAttachExtensionDevice(priv->mon, &fs->info) < 0)
3462         goto exit_monitor;
3463 
3464     if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) {
3465         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &fs->info));
3466         goto exit_monitor;
3467     }
3468 
3469     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
3470         releaseaddr = false;
3471         goto cleanup;
3472     }
3473 
3474     VIR_APPEND_ELEMENT_COPY(vm->def->fss, vm->def->nfss, fs);
3475 
3476     ret = 0;
3477 
3478  audit:
3479     virDomainAuditFS(vm, NULL, fs, "attach", ret == 0);
3480  cleanup:
3481     if (ret < 0) {
3482         virErrorPreserveLast(&origErr);
3483         if (releaseaddr)
3484             qemuDomainReleaseDeviceAddress(vm, &fs->info);
3485         if (started)
3486             qemuVirtioFSStop(driver, vm, fs);
3487         virErrorRestore(&origErr);
3488     }
3489 
3490     return ret;
3491 
3492  exit_monitor:
3493     virErrorPreserveLast(&origErr);
3494     if (chardevAdded)
3495         ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
3496     if (qemuDomainObjExitMonitor(driver, vm) < 0)
3497         releaseaddr = false;
3498     virErrorRestore(&origErr);
3499     goto audit;
3500 }
3501 
3502 
3503 int
qemuDomainAttachLease(virQEMUDriver * driver,virDomainObj * vm,virDomainLeaseDef * lease)3504 qemuDomainAttachLease(virQEMUDriver *driver,
3505                       virDomainObj *vm,
3506                       virDomainLeaseDef *lease)
3507 {
3508     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
3509 
3510     virDomainLeaseInsertPreAlloc(vm->def);
3511 
3512     if (virDomainLockLeaseAttach(driver->lockManager, cfg->uri,
3513                                  vm, lease) < 0) {
3514         virDomainLeaseInsertPreAlloced(vm->def, NULL);
3515         return -1;
3516     }
3517 
3518     virDomainLeaseInsertPreAlloced(vm->def, lease);
3519     return 0;
3520 }
3521 
3522 
3523 static int
qemuDomainChangeNetBridge(virDomainObj * vm,virDomainNetDef * olddev,virDomainNetDef * newdev)3524 qemuDomainChangeNetBridge(virDomainObj *vm,
3525                           virDomainNetDef *olddev,
3526                           virDomainNetDef *newdev)
3527 {
3528     int ret = -1;
3529     const char *oldbridge = virDomainNetGetActualBridgeName(olddev);
3530     const char *newbridge = virDomainNetGetActualBridgeName(newdev);
3531 
3532     if (!oldbridge || !newbridge) {
3533         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name"));
3534         return -1;
3535     }
3536 
3537     VIR_DEBUG("Change bridge for interface %s: %s -> %s",
3538               olddev->ifname, oldbridge, newbridge);
3539 
3540     if (virNetDevExists(newbridge) != 1) {
3541         virReportError(VIR_ERR_OPERATION_FAILED,
3542                        _("bridge %s doesn't exist"), newbridge);
3543         return -1;
3544     }
3545 
3546     ret = virNetDevBridgeRemovePort(oldbridge, olddev->ifname);
3547     virDomainAuditNet(vm, olddev, NULL, "detach", ret == 0);
3548     if (ret < 0) {
3549         /* warn but continue - possibly the old network
3550          * had been destroyed and reconstructed, leaving the
3551          * tap device orphaned.
3552          */
3553         VIR_WARN("Unable to detach device %s from bridge %s",
3554                  olddev->ifname, oldbridge);
3555     }
3556 
3557     ret = virNetDevBridgeAddPort(newbridge, olddev->ifname);
3558     if (ret == 0 &&
3559         virDomainNetGetActualPortOptionsIsolated(newdev) == VIR_TRISTATE_BOOL_YES) {
3560 
3561         ret = virNetDevBridgePortSetIsolated(newbridge, olddev->ifname, true);
3562         if (ret < 0) {
3563             virErrorPtr err;
3564 
3565             virErrorPreserveLast(&err);
3566             ignore_value(virNetDevBridgeRemovePort(newbridge, olddev->ifname));
3567             virErrorRestore(&err);
3568         }
3569     }
3570     virDomainAuditNet(vm, NULL, newdev, "attach", ret == 0);
3571     if (ret < 0) {
3572         virErrorPtr err;
3573 
3574         virErrorPreserveLast(&err);
3575         ret = virNetDevBridgeAddPort(oldbridge, olddev->ifname);
3576         if (ret == 0 &&
3577             virDomainNetGetActualPortOptionsIsolated(olddev) == VIR_TRISTATE_BOOL_YES) {
3578             ignore_value(virNetDevBridgePortSetIsolated(newbridge, olddev->ifname, true));
3579         }
3580         virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
3581         virErrorRestore(&err);
3582         return -1;
3583     }
3584     /* caller will replace entire olddev with newdev in domain nets list */
3585     return 0;
3586 }
3587 
3588 static int
qemuDomainChangeNetFilter(virDomainObj * vm,virDomainNetDef * olddev,virDomainNetDef * newdev)3589 qemuDomainChangeNetFilter(virDomainObj *vm,
3590                           virDomainNetDef *olddev,
3591                           virDomainNetDef *newdev)
3592 {
3593     /* make sure this type of device supports filters. */
3594     switch (virDomainNetGetActualType(newdev)) {
3595     case VIR_DOMAIN_NET_TYPE_ETHERNET:
3596     case VIR_DOMAIN_NET_TYPE_BRIDGE:
3597     case VIR_DOMAIN_NET_TYPE_NETWORK:
3598         break;
3599     case VIR_DOMAIN_NET_TYPE_USER:
3600     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
3601     case VIR_DOMAIN_NET_TYPE_SERVER:
3602     case VIR_DOMAIN_NET_TYPE_CLIENT:
3603     case VIR_DOMAIN_NET_TYPE_MCAST:
3604     case VIR_DOMAIN_NET_TYPE_INTERNAL:
3605     case VIR_DOMAIN_NET_TYPE_DIRECT:
3606     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
3607     case VIR_DOMAIN_NET_TYPE_UDP:
3608     case VIR_DOMAIN_NET_TYPE_VDPA:
3609         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3610                        _("filters not supported on interfaces of type %s"),
3611                        virDomainNetTypeToString(virDomainNetGetActualType(newdev)));
3612         return -1;
3613     case VIR_DOMAIN_NET_TYPE_LAST:
3614     default:
3615         virReportEnumRangeError(virDomainNetType,
3616                                 virDomainNetGetActualType(newdev));
3617         return -1;
3618     }
3619 
3620     virDomainConfNWFilterTeardown(olddev);
3621 
3622     if (newdev->filter &&
3623         virDomainConfNWFilterInstantiate(vm->def->name,
3624                                          vm->def->uuid, newdev, false) < 0) {
3625         virErrorPtr errobj;
3626 
3627         virReportError(VIR_ERR_OPERATION_FAILED,
3628                        _("failed to add new filter rules to '%s' "
3629                          "- attempting to restore old rules"),
3630                        olddev->ifname);
3631         virErrorPreserveLast(&errobj);
3632         ignore_value(virDomainConfNWFilterInstantiate(vm->def->name,
3633                                                       vm->def->uuid, olddev, false));
3634         virErrorRestore(&errobj);
3635         return -1;
3636     }
3637     return 0;
3638 }
3639 
qemuDomainChangeNetLinkState(virQEMUDriver * driver,virDomainObj * vm,virDomainNetDef * dev,int linkstate)3640 int qemuDomainChangeNetLinkState(virQEMUDriver *driver,
3641                                  virDomainObj *vm,
3642                                  virDomainNetDef *dev,
3643                                  int linkstate)
3644 {
3645     int ret = -1;
3646     qemuDomainObjPrivate *priv = vm->privateData;
3647 
3648     if (!dev->info.alias) {
3649         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3650                        _("can't change link state: device alias not found"));
3651         return -1;
3652     }
3653 
3654     VIR_DEBUG("dev: %s, state: %d", dev->info.alias, linkstate);
3655 
3656     qemuDomainObjEnterMonitor(driver, vm);
3657 
3658     ret = qemuMonitorSetLink(priv->mon, dev->info.alias, linkstate);
3659     if (ret < 0)
3660         goto cleanup;
3661 
3662     /* modify the device configuration */
3663     dev->linkstate = linkstate;
3664 
3665  cleanup:
3666     if (qemuDomainObjExitMonitor(driver, vm) < 0)
3667         return -1;
3668 
3669     return ret;
3670 }
3671 
3672 int
qemuDomainChangeNet(virQEMUDriver * driver,virDomainObj * vm,virDomainDeviceDef * dev)3673 qemuDomainChangeNet(virQEMUDriver *driver,
3674                     virDomainObj *vm,
3675                     virDomainDeviceDef *dev)
3676 {
3677     qemuDomainObjPrivate *priv = vm->privateData;
3678     virDomainNetDef *newdev = dev->data.net;
3679     virDomainNetDef **devslot = NULL;
3680     virDomainNetDef *olddev;
3681     virDomainNetType oldType, newType;
3682     bool needReconnect = false;
3683     bool needBridgeChange = false;
3684     bool needFilterChange = false;
3685     bool needLinkStateChange = false;
3686     bool needReplaceDevDef = false;
3687     bool needBandwidthSet = false;
3688     bool needCoalesceChange = false;
3689     bool needVlanUpdate = false;
3690     bool needIsolatedPortChange = false;
3691     int ret = -1;
3692     int changeidx = -1;
3693     g_autoptr(virConnect) conn = NULL;
3694     virErrorPtr save_err = NULL;
3695 
3696     if ((changeidx = virDomainNetFindIdx(vm->def, newdev)) < 0)
3697         goto cleanup;
3698     devslot = &vm->def->nets[changeidx];
3699     olddev = *devslot;
3700 
3701     oldType = virDomainNetGetActualType(olddev);
3702     if (oldType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
3703         oldType == VIR_DOMAIN_NET_TYPE_VDPA) {
3704         /* no changes are possible to a type='hostdev' or type='vdpa' interface */
3705         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3706                        _("cannot change config of '%s' network interface type"),
3707                        virDomainNetTypeToString(oldType));
3708         goto cleanup;
3709     }
3710 
3711     /* Check individual attributes for changes that can't be done to a
3712      * live netdev. These checks *mostly* go in order of the
3713      * declarations in virDomainNetDef in order to assure nothing is
3714      * omitted. (exceptiong where noted in comments - in particular,
3715      * some things require that a new "actual device" be allocated
3716      * from the network driver first, but we delay doing that until
3717      * after we've made as many other checks as possible)
3718      */
3719 
3720     /* type: this can change (with some restrictions), but the actual
3721      * type of the new device connection isn't known until after we
3722      * allocate the "actual" device.
3723      */
3724 
3725     if (virMacAddrCmp(&olddev->mac, &newdev->mac)) {
3726         char oldmac[VIR_MAC_STRING_BUFLEN], newmac[VIR_MAC_STRING_BUFLEN];
3727 
3728         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3729                        _("cannot change network interface mac address "
3730                          "from %s to %s"),
3731                        virMacAddrFormat(&olddev->mac, oldmac),
3732                        virMacAddrFormat(&newdev->mac, newmac));
3733         goto cleanup;
3734     }
3735 
3736     if (STRNEQ_NULLABLE(virDomainNetGetModelString(olddev),
3737                         virDomainNetGetModelString(newdev))) {
3738         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3739                        _("cannot modify network device model from %s to %s"),
3740                        NULLSTR(virDomainNetGetModelString(olddev)),
3741                        NULLSTR(virDomainNetGetModelString(newdev)));
3742         goto cleanup;
3743     }
3744 
3745     if (olddev->model != newdev->model) {
3746         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3747                        _("cannot modify network device model from %s to %s"),
3748                        virDomainNetModelTypeToString(olddev->model),
3749                        virDomainNetModelTypeToString(newdev->model));
3750         goto cleanup;
3751     }
3752 
3753     if (virDomainNetIsVirtioModel(olddev) &&
3754         (olddev->driver.virtio.name != newdev->driver.virtio.name ||
3755          olddev->driver.virtio.txmode != newdev->driver.virtio.txmode ||
3756          olddev->driver.virtio.ioeventfd != newdev->driver.virtio.ioeventfd ||
3757          olddev->driver.virtio.event_idx != newdev->driver.virtio.event_idx ||
3758          olddev->driver.virtio.queues != newdev->driver.virtio.queues ||
3759          olddev->driver.virtio.rx_queue_size != newdev->driver.virtio.rx_queue_size ||
3760          olddev->driver.virtio.tx_queue_size != newdev->driver.virtio.tx_queue_size ||
3761          olddev->driver.virtio.host.csum != newdev->driver.virtio.host.csum ||
3762          olddev->driver.virtio.host.gso != newdev->driver.virtio.host.gso ||
3763          olddev->driver.virtio.host.tso4 != newdev->driver.virtio.host.tso4 ||
3764          olddev->driver.virtio.host.tso6 != newdev->driver.virtio.host.tso6 ||
3765          olddev->driver.virtio.host.ecn != newdev->driver.virtio.host.ecn ||
3766          olddev->driver.virtio.host.ufo != newdev->driver.virtio.host.ufo ||
3767          olddev->driver.virtio.host.mrg_rxbuf != newdev->driver.virtio.host.mrg_rxbuf ||
3768          olddev->driver.virtio.guest.csum != newdev->driver.virtio.guest.csum ||
3769          olddev->driver.virtio.guest.tso4 != newdev->driver.virtio.guest.tso4 ||
3770          olddev->driver.virtio.guest.tso6 != newdev->driver.virtio.guest.tso6 ||
3771          olddev->driver.virtio.guest.ecn != newdev->driver.virtio.guest.ecn ||
3772          olddev->driver.virtio.guest.ufo != newdev->driver.virtio.guest.ufo)) {
3773         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3774                        _("cannot modify virtio network device driver attributes"));
3775         goto cleanup;
3776     }
3777 
3778     if (!!olddev->virtio != !!newdev->virtio ||
3779         (olddev->virtio && newdev->virtio &&
3780          (olddev->virtio->iommu != newdev->virtio->iommu ||
3781           olddev->virtio->ats != newdev->virtio->ats ||
3782           olddev->virtio->packed != newdev->virtio->packed ||
3783           olddev->virtio->page_per_vq != newdev->virtio->page_per_vq))) {
3784         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3785                        _("cannot modify virtio network device driver options"));
3786            goto cleanup;
3787    }
3788 
3789     /* data: this union will be examined later, after allocating new actualdev */
3790     /* virtPortProfile: will be examined later, after allocating new actualdev */
3791 
3792     if (olddev->tune.sndbuf_specified != newdev->tune.sndbuf_specified ||
3793         olddev->tune.sndbuf != newdev->tune.sndbuf) {
3794         needReconnect = true;
3795     }
3796 
3797     if (STRNEQ_NULLABLE(olddev->script, newdev->script)) {
3798         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3799                        _("cannot modify network device script attribute"));
3800         goto cleanup;
3801     }
3802 
3803     /* ifname: check if it's set in newdev. If not, retain the autogenerated one */
3804     if (!newdev->ifname)
3805         newdev->ifname = g_strdup(olddev->ifname);
3806     if (STRNEQ_NULLABLE(olddev->ifname, newdev->ifname)) {
3807         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3808                        _("cannot modify network device tap name"));
3809         goto cleanup;
3810     }
3811 
3812     /* info: Nothing is allowed to change. First fill the missing newdev->info
3813      * from olddev and then check for changes.
3814      */
3815     /* if pci addr is missing or is invalid we overwrite it from olddev */
3816     if (newdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
3817         !virDomainDeviceAddressIsValid(&newdev->info,
3818                                        newdev->info.type)) {
3819         newdev->info.type = olddev->info.type;
3820         newdev->info.addr = olddev->info.addr;
3821     }
3822     if (olddev->info.type != newdev->info.type) {
3823         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3824                        _("cannot modify network device address type"));
3825     }
3826     if (!virPCIDeviceAddressEqual(&olddev->info.addr.pci,
3827                                   &newdev->info.addr.pci)) {
3828         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3829                        _("cannot modify network device guest PCI address"));
3830         goto cleanup;
3831     }
3832     /* grab alias from olddev if not set in newdev */
3833     if (!newdev->info.alias)
3834         newdev->info.alias = g_strdup(olddev->info.alias);
3835 
3836     /* device alias is checked already in virDomainDefCompatibleDevice */
3837 
3838     if (newdev->info.rombar == VIR_TRISTATE_SWITCH_ABSENT)
3839         newdev->info.rombar = olddev->info.rombar;
3840     if (olddev->info.rombar != newdev->info.rombar) {
3841         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3842                        _("cannot modify network device rom bar setting"));
3843         goto cleanup;
3844     }
3845 
3846     if (!newdev->info.romfile)
3847         newdev->info.romfile = g_strdup(olddev->info.romfile);
3848     if (STRNEQ_NULLABLE(olddev->info.romfile, newdev->info.romfile)) {
3849         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3850                        _("cannot modify network rom file"));
3851         goto cleanup;
3852     }
3853 
3854     if (newdev->info.bootIndex == 0)
3855         newdev->info.bootIndex = olddev->info.bootIndex;
3856     if (olddev->info.bootIndex != newdev->info.bootIndex) {
3857         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3858                        _("cannot modify network device boot index setting"));
3859         goto cleanup;
3860     }
3861 
3862     if (newdev->info.romenabled == VIR_TRISTATE_BOOL_ABSENT)
3863         newdev->info.romenabled = olddev->info.romenabled;
3864     if (olddev->info.romenabled != newdev->info.romenabled) {
3865         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3866                        _("cannot modify network device rom enabled setting"));
3867         goto cleanup;
3868     }
3869     /* (end of device info checks) */
3870 
3871     if (STRNEQ_NULLABLE(olddev->filter, newdev->filter) ||
3872         !virNWFilterHashTableEqual(olddev->filterparams, newdev->filterparams)) {
3873         needFilterChange = true;
3874     }
3875 
3876     /* bandwidth can be modified, and will be checked later */
3877     /* vlan can be modified, and will be checked later */
3878     /* linkstate can be modified */
3879 
3880     if (olddev->mtu != newdev->mtu) {
3881         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3882                        _("cannot modify MTU"));
3883         goto cleanup;
3884     }
3885 
3886     /* allocate new actual device to compare to old - we will need to
3887      * free it if we fail for any reason
3888      */
3889     if (newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
3890         if (!(conn = virGetConnectNetwork()))
3891             goto cleanup;
3892         if (virDomainNetAllocateActualDevice(conn, vm->def, newdev) < 0)
3893             goto cleanup;
3894     }
3895 
3896     /* final validation now that we have full info on the type */
3897     if (qemuDomainValidateActualNetDef(newdev, priv->qemuCaps) < 0)
3898         goto cleanup;
3899 
3900     newType = virDomainNetGetActualType(newdev);
3901 
3902     if (newType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
3903         newType == VIR_DOMAIN_NET_TYPE_VDPA) {
3904         /* can't turn it into a type='hostdev' or type='vdpa' interface */
3905         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3906                        _("cannot change network interface type to '%s'"),
3907                        virDomainNetTypeToString(newType));
3908         goto cleanup;
3909     }
3910 
3911     if (olddev->type == newdev->type && oldType == newType) {
3912 
3913         /* if type hasn't changed, check the relevant fields for the type */
3914         switch (newdev->type) {
3915         case VIR_DOMAIN_NET_TYPE_USER:
3916             break;
3917 
3918         case VIR_DOMAIN_NET_TYPE_ETHERNET:
3919             break;
3920 
3921         case VIR_DOMAIN_NET_TYPE_SERVER:
3922         case VIR_DOMAIN_NET_TYPE_CLIENT:
3923         case VIR_DOMAIN_NET_TYPE_MCAST:
3924         case VIR_DOMAIN_NET_TYPE_UDP:
3925             if (STRNEQ_NULLABLE(olddev->data.socket.address,
3926                                 newdev->data.socket.address) ||
3927                 olddev->data.socket.port != newdev->data.socket.port) {
3928                 needReconnect = true;
3929             }
3930             break;
3931 
3932         case VIR_DOMAIN_NET_TYPE_NETWORK:
3933             if (STRNEQ(olddev->data.network.name, newdev->data.network.name)) {
3934                 if (virDomainNetGetActualVirtPortProfile(newdev))
3935                     needReconnect = true;
3936                 else
3937                     needBridgeChange = true;
3938             }
3939             /* other things handled in common code directly below this switch */
3940             break;
3941 
3942         case VIR_DOMAIN_NET_TYPE_BRIDGE:
3943             /* all handled in bridge name checked in common code below */
3944             break;
3945 
3946         case VIR_DOMAIN_NET_TYPE_INTERNAL:
3947             if (STRNEQ_NULLABLE(olddev->data.internal.name,
3948                                 newdev->data.internal.name)) {
3949                 needReconnect = true;
3950             }
3951             break;
3952 
3953         case VIR_DOMAIN_NET_TYPE_DIRECT:
3954             /* all handled in common code directly below this switch */
3955             break;
3956 
3957         case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
3958         case VIR_DOMAIN_NET_TYPE_HOSTDEV:
3959         case VIR_DOMAIN_NET_TYPE_VDPA:
3960             virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
3961                            _("unable to change config on '%s' network type"),
3962                            virDomainNetTypeToString(newdev->type));
3963             goto cleanup;
3964         case VIR_DOMAIN_NET_TYPE_LAST:
3965         default:
3966             virReportEnumRangeError(virDomainNetType, newdev->type);
3967             goto cleanup;
3968         }
3969     } else {
3970         /* interface type has changed. There are a few special cases
3971          * where this can only require a minor (or even no) change,
3972          * but in most cases we need to do a full reconnection.
3973          *
3974          * As long as both the new and old types use a tap device
3975          * connected to a host bridge (ie VIR_DOMAIN_NET_TYPE_NETWORK
3976          * or VIR_DOMAIN_NET_TYPE_BRIDGE), we just need to connect to
3977          * the new bridge.
3978          */
3979         if ((oldType == VIR_DOMAIN_NET_TYPE_NETWORK ||
3980              oldType == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
3981             (newType == VIR_DOMAIN_NET_TYPE_NETWORK ||
3982              newType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
3983 
3984             needBridgeChange = true;
3985 
3986         } else if (oldType == VIR_DOMAIN_NET_TYPE_DIRECT &&
3987                    newType == VIR_DOMAIN_NET_TYPE_DIRECT) {
3988 
3989             /* this is the case of switching from type='direct' to
3990              * type='network' for a network that itself uses direct
3991              * (macvtap) devices. If the physical device and mode are
3992              * the same, this doesn't require any actual setup
3993              * change. If the physical device or mode *does* change,
3994              * that will be caught in the common section below */
3995 
3996         } else {
3997 
3998             /* for all other combinations, we'll need a full reconnect */
3999             needReconnect = true;
4000 
4001         }
4002     }
4003 
4004     /* now several things that are in multiple (but not all)
4005      * different types, and can be safely compared even for those
4006      * cases where they don't apply to a particular type.
4007      */
4008     if (STRNEQ_NULLABLE(virDomainNetGetActualBridgeName(olddev),
4009                         virDomainNetGetActualBridgeName(newdev))) {
4010         if (virDomainNetGetActualVirtPortProfile(newdev))
4011             needReconnect = true;
4012         else
4013             needBridgeChange = true;
4014     }
4015 
4016     if (STRNEQ_NULLABLE(virDomainNetGetActualDirectDev(olddev),
4017                         virDomainNetGetActualDirectDev(newdev)) ||
4018         virDomainNetGetActualDirectMode(olddev) != virDomainNetGetActualDirectMode(newdev) ||
4019         !virNetDevVPortProfileEqual(virDomainNetGetActualVirtPortProfile(olddev),
4020                                     virDomainNetGetActualVirtPortProfile(newdev))) {
4021         needReconnect = true;
4022     }
4023 
4024     if (!virNetDevVlanEqual(virDomainNetGetActualVlan(olddev),
4025                              virDomainNetGetActualVlan(newdev))) {
4026         needVlanUpdate = true;
4027     }
4028 
4029     if (virDomainNetGetActualPortOptionsIsolated(olddev) !=
4030         virDomainNetGetActualPortOptionsIsolated(newdev)) {
4031         needIsolatedPortChange = true;
4032     }
4033 
4034     if (olddev->linkstate != newdev->linkstate)
4035         needLinkStateChange = true;
4036 
4037     if (!virNetDevBandwidthEqual(virDomainNetGetActualBandwidth(olddev),
4038                                  virDomainNetGetActualBandwidth(newdev)))
4039         needBandwidthSet = true;
4040 
4041     if (!!olddev->coalesce != !!newdev->coalesce ||
4042         (olddev->coalesce && newdev->coalesce &&
4043          memcmp(olddev->coalesce, newdev->coalesce,
4044                 sizeof(*olddev->coalesce))))
4045         needCoalesceChange = true;
4046 
4047     /* FINALLY - actually perform the required actions */
4048 
4049     if (needReconnect) {
4050         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
4051                        _("unable to change config on '%s' network type"),
4052                        virDomainNetTypeToString(newdev->type));
4053         goto cleanup;
4054     }
4055 
4056     if (needBandwidthSet) {
4057         const virNetDevBandwidth *newb = virDomainNetGetActualBandwidth(newdev);
4058 
4059         if (newb) {
4060             if (virDomainNetDefIsOvsport(newdev)) {
4061                 if (virNetDevOpenvswitchInterfaceSetQos(newdev->ifname, newb,
4062                                                         vm->def->uuid,
4063                                                         !virDomainNetTypeSharesHostView(newdev)) < 0)
4064                     goto cleanup;
4065             } else if (virNetDevBandwidthSet(newdev->ifname, newb, false,
4066                                              !virDomainNetTypeSharesHostView(newdev)) < 0) {
4067                 goto cleanup;
4068             }
4069         } else {
4070             /*
4071              * virNetDevBandwidthSet() doesn't clear any existing
4072              * setting unless something new is being set.
4073              */
4074             virNetDevBandwidthClear(newdev->ifname);
4075         }
4076 
4077         /* If the old bandwidth was cleared out, restore qdisc. */
4078         if (virDomainNetTypeSharesHostView(newdev)) {
4079             if (!newb || !newb->out || newb->out->average == 0)
4080                 qemuDomainInterfaceSetDefaultQDisc(driver, newdev);
4081         } else {
4082             if (!newb || !newb->in || newb->in->average == 0)
4083                 qemuDomainInterfaceSetDefaultQDisc(driver, newdev);
4084         }
4085         needReplaceDevDef = true;
4086     }
4087 
4088     if (needBridgeChange) {
4089         if (qemuDomainChangeNetBridge(vm, olddev, newdev) < 0)
4090             goto cleanup;
4091         /* we successfully switched to the new bridge, and we've
4092          * determined that the rest of newdev is equivalent to olddev,
4093          * so move newdev into place */
4094         needReplaceDevDef = true;
4095 
4096         /* this is already updated as a part of reconnecting the bridge */
4097         needIsolatedPortChange = false;
4098     }
4099 
4100     if (needIsolatedPortChange) {
4101         const char *bridge = virDomainNetGetActualBridgeName(newdev);
4102         bool isolatedOn = (virDomainNetGetActualPortOptionsIsolated(newdev) ==
4103                            VIR_TRISTATE_BOOL_YES);
4104 
4105         if (virNetDevBridgePortSetIsolated(bridge, newdev->ifname, isolatedOn) < 0)
4106             goto cleanup;
4107 
4108         needReplaceDevDef = true;
4109     }
4110 
4111     if (needFilterChange) {
4112         if (qemuDomainChangeNetFilter(vm, olddev, newdev) < 0)
4113             goto cleanup;
4114         /* we successfully switched to the new filter, and we've
4115          * determined that the rest of newdev is equivalent to olddev,
4116          * so move newdev into place */
4117         needReplaceDevDef = true;
4118     }
4119 
4120     if (needCoalesceChange) {
4121         if (virNetDevSetCoalesce(newdev->ifname, newdev->coalesce, true) < 0)
4122             goto cleanup;
4123         needReplaceDevDef = true;
4124     }
4125 
4126     if (needLinkStateChange &&
4127         qemuDomainChangeNetLinkState(driver, vm, olddev, newdev->linkstate) < 0) {
4128         goto cleanup;
4129     }
4130 
4131     if (needVlanUpdate) {
4132         if (virNetDevOpenvswitchUpdateVlan(newdev->ifname, &newdev->vlan) < 0)
4133             goto cleanup;
4134         needReplaceDevDef = true;
4135     }
4136 
4137     if (needReplaceDevDef) {
4138         /* the changes above warrant replacing olddev with newdev in
4139          * the domain's nets list.
4140          */
4141 
4142         /* this function doesn't work with HOSTDEV networks yet, thus
4143          * no need to change the pointer in the hostdev structure */
4144         if (olddev->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
4145             if (conn || (conn = virGetConnectNetwork()))
4146                 virDomainNetReleaseActualDevice(conn, vm->def, olddev);
4147             else
4148                 VIR_WARN("Unable to release network device '%s'", NULLSTR(olddev->ifname));
4149         }
4150         virDomainNetDefFree(olddev);
4151         /* move newdev into the nets list, and NULL it out from the
4152          * virDomainDeviceDef that we were given so that the caller
4153          * won't delete it on return.
4154          */
4155         *devslot = newdev;
4156         newdev = dev->data.net = NULL;
4157         dev->type = VIR_DOMAIN_DEVICE_NONE;
4158     }
4159 
4160     ret = 0;
4161  cleanup:
4162     virErrorPreserveLast(&save_err);
4163     /* When we get here, we will be in one of these two states:
4164      *
4165      * 1) newdev has been moved into the domain's list of nets and
4166      *    newdev set to NULL, and dev->data.net will be NULL (and
4167      *    dev->type is NONE). olddev will have been completely
4168      *    released and freed. (aka success) In this case no extra
4169      *    cleanup is needed.
4170      *
4171      * 2) newdev has *not* been moved into the domain's list of nets,
4172      *    and dev->data.net == newdev (and dev->type == NET). In this *
4173      *    case, we need to at least release the "actual device" from *
4174      *    newdev (the caller will free dev->data.net a.k.a. newdev, and
4175      *    the original olddev is still in used)
4176      *
4177      * Note that case (2) isn't necessarily a failure. It may just be
4178      * that the changes were minor enough that we didn't need to
4179      * replace the entire device object.
4180      */
4181     if (newdev && newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK && conn)
4182         virDomainNetReleaseActualDevice(conn, vm->def, newdev);
4183     virErrorRestore(&save_err);
4184 
4185     return ret;
4186 }
4187 
4188 static virDomainGraphicsDef *
qemuDomainFindGraphics(virDomainObj * vm,virDomainGraphicsDef * dev)4189 qemuDomainFindGraphics(virDomainObj *vm,
4190                        virDomainGraphicsDef *dev)
4191 {
4192     size_t i;
4193 
4194     for (i = 0; i < vm->def->ngraphics; i++) {
4195         if (vm->def->graphics[i]->type == dev->type)
4196             return vm->def->graphics[i];
4197     }
4198 
4199     return NULL;
4200 }
4201 
4202 int
qemuDomainFindGraphicsIndex(virDomainDef * def,virDomainGraphicsDef * dev)4203 qemuDomainFindGraphicsIndex(virDomainDef *def,
4204                             virDomainGraphicsDef *dev)
4205 {
4206     size_t i;
4207 
4208     for (i = 0; i < def->ngraphics; i++) {
4209         if (def->graphics[i]->type == dev->type)
4210             return i;
4211     }
4212 
4213     return -1;
4214 }
4215 
4216 
4217 int
qemuDomainChangeGraphicsPasswords(virQEMUDriver * driver,virDomainObj * vm,int type,virDomainGraphicsAuthDef * auth,const char * defaultPasswd,int asyncJob)4218 qemuDomainChangeGraphicsPasswords(virQEMUDriver *driver,
4219                                   virDomainObj *vm,
4220                                   int type,
4221                                   virDomainGraphicsAuthDef *auth,
4222                                   const char *defaultPasswd,
4223                                   int asyncJob)
4224 {
4225     qemuDomainObjPrivate *priv = vm->privateData;
4226     time_t now = time(NULL);
4227     const char *expire;
4228     g_autofree char *validTo = NULL;
4229     const char *connected = NULL;
4230     const char *password;
4231     int ret = -1;
4232 
4233     if (!auth->passwd && !defaultPasswd)
4234         return 0;
4235 
4236     password = auth->passwd ? auth->passwd : defaultPasswd;
4237 
4238     if (auth->connected)
4239         connected = virDomainGraphicsAuthConnectedTypeToString(auth->connected);
4240 
4241     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
4242         return ret;
4243     ret = qemuMonitorSetPassword(priv->mon, type, password, connected);
4244 
4245     if (ret != 0)
4246         goto end_job;
4247 
4248     if (password[0] == '\0' ||
4249         (auth->expires && auth->validTo <= now)) {
4250         expire = "now";
4251     } else if (auth->expires) {
4252         validTo = g_strdup_printf("%lu", (unsigned long)auth->validTo);
4253         expire = validTo;
4254     } else {
4255         expire = "never";
4256     }
4257 
4258     ret = qemuMonitorExpirePassword(priv->mon, type, expire);
4259 
4260  end_job:
4261     if (qemuDomainObjExitMonitor(driver, vm) < 0)
4262         ret = -1;
4263 
4264     return ret;
4265 }
4266 
4267 
4268 int
qemuDomainChangeGraphics(virQEMUDriver * driver,virDomainObj * vm,virDomainGraphicsDef * dev)4269 qemuDomainChangeGraphics(virQEMUDriver *driver,
4270                          virDomainObj *vm,
4271                          virDomainGraphicsDef *dev)
4272 {
4273     virDomainGraphicsDef *olddev = qemuDomainFindGraphics(vm, dev);
4274     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
4275     const char *type = virDomainGraphicsTypeToString(dev->type);
4276     size_t i;
4277 
4278     if (!olddev) {
4279         virReportError(VIR_ERR_DEVICE_MISSING,
4280                        _("cannot find existing graphics device to modify of "
4281                          "type '%s'"), type);
4282         return -1;
4283     }
4284 
4285     if (dev->nListens != olddev->nListens) {
4286         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
4287                        _("cannot change the number of listen addresses "
4288                          "on '%s' graphics"), type);
4289         return -1;
4290     }
4291 
4292     for (i = 0; i < dev->nListens; i++) {
4293         virDomainGraphicsListenDef *newlisten = &dev->listens[i];
4294         virDomainGraphicsListenDef *oldlisten = &olddev->listens[i];
4295 
4296         if (newlisten->type != oldlisten->type) {
4297             virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
4298                            _("cannot change the type of listen address "
4299                              "on '%s' graphics"), type);
4300             return -1;
4301         }
4302 
4303         switch (newlisten->type) {
4304         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
4305             if (STRNEQ_NULLABLE(newlisten->address, oldlisten->address)) {
4306                 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
4307                                _("cannot change listen address setting "
4308                                  "on '%s' graphics"), type);
4309                 return -1;
4310             }
4311 
4312             break;
4313 
4314         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
4315             if (STRNEQ_NULLABLE(newlisten->network, oldlisten->network)) {
4316                 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
4317                                _("cannot change listen address setting "
4318                                  "on '%s' graphics"), type);
4319                 return -1;
4320             }
4321 
4322             break;
4323 
4324         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
4325             if (STRNEQ_NULLABLE(newlisten->socket, oldlisten->socket)) {
4326                 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
4327                                _("cannot change listen socket setting "
4328                                  "on '%s' graphics"), type);
4329                 return -1;
4330             }
4331             break;
4332 
4333         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
4334         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
4335             /* nada */
4336             break;
4337         }
4338     }
4339 
4340     switch (dev->type) {
4341     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
4342         if ((olddev->data.vnc.autoport != dev->data.vnc.autoport) ||
4343             (!dev->data.vnc.autoport &&
4344              (olddev->data.vnc.port != dev->data.vnc.port))) {
4345             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4346                            _("cannot change port settings on vnc graphics"));
4347             return -1;
4348         }
4349         if (STRNEQ_NULLABLE(olddev->data.vnc.keymap, dev->data.vnc.keymap)) {
4350             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4351                            _("cannot change keymap setting on vnc graphics"));
4352             return -1;
4353         }
4354 
4355         /* If a password lifetime was, or is set, or action if connected has
4356          * changed, then we must always run, even if new password matches
4357          * old password */
4358         if (olddev->data.vnc.auth.expires ||
4359             dev->data.vnc.auth.expires ||
4360             olddev->data.vnc.auth.connected != dev->data.vnc.auth.connected ||
4361             STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd,
4362                             dev->data.vnc.auth.passwd)) {
4363             VIR_DEBUG("Updating password on VNC server %p %p",
4364                       dev->data.vnc.auth.passwd, cfg->vncPassword);
4365             if (qemuDomainChangeGraphicsPasswords(driver, vm,
4366                                                   VIR_DOMAIN_GRAPHICS_TYPE_VNC,
4367                                                   &dev->data.vnc.auth,
4368                                                   cfg->vncPassword,
4369                                                   QEMU_ASYNC_JOB_NONE) < 0)
4370                 return -1;
4371 
4372             /* Steal the new dev's  char * reference */
4373             VIR_FREE(olddev->data.vnc.auth.passwd);
4374             olddev->data.vnc.auth.passwd = dev->data.vnc.auth.passwd;
4375             dev->data.vnc.auth.passwd = NULL;
4376             olddev->data.vnc.auth.validTo = dev->data.vnc.auth.validTo;
4377             olddev->data.vnc.auth.expires = dev->data.vnc.auth.expires;
4378             olddev->data.vnc.auth.connected = dev->data.vnc.auth.connected;
4379         }
4380         break;
4381 
4382     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
4383         if ((olddev->data.spice.autoport != dev->data.spice.autoport) ||
4384             (!dev->data.spice.autoport &&
4385              (olddev->data.spice.port != dev->data.spice.port)) ||
4386             (!dev->data.spice.autoport &&
4387              (olddev->data.spice.tlsPort != dev->data.spice.tlsPort))) {
4388             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4389                            _("cannot change port settings on spice graphics"));
4390             return -1;
4391         }
4392         if (STRNEQ_NULLABLE(olddev->data.spice.keymap,
4393                             dev->data.spice.keymap)) {
4394             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4395                             _("cannot change keymap setting on spice graphics"));
4396             return -1;
4397         }
4398 
4399         /* We must reset the password if it has changed but also if:
4400          * - password lifetime is or was set
4401          * - the requested action has changed
4402          * - the action is "disconnect"
4403          */
4404         if (olddev->data.spice.auth.expires ||
4405             dev->data.spice.auth.expires ||
4406             olddev->data.spice.auth.connected != dev->data.spice.auth.connected ||
4407             dev->data.spice.auth.connected ==
4408             VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DISCONNECT ||
4409             STRNEQ_NULLABLE(olddev->data.spice.auth.passwd,
4410                             dev->data.spice.auth.passwd)) {
4411             VIR_DEBUG("Updating password on SPICE server %p %p",
4412                       dev->data.spice.auth.passwd, cfg->spicePassword);
4413             if (qemuDomainChangeGraphicsPasswords(driver, vm,
4414                                                   VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
4415                                                   &dev->data.spice.auth,
4416                                                   cfg->spicePassword,
4417                                                   QEMU_ASYNC_JOB_NONE) < 0)
4418                 return -1;
4419 
4420             /* Steal the new dev's char * reference */
4421             VIR_FREE(olddev->data.spice.auth.passwd);
4422             olddev->data.spice.auth.passwd = dev->data.spice.auth.passwd;
4423             dev->data.spice.auth.passwd = NULL;
4424             olddev->data.spice.auth.validTo = dev->data.spice.auth.validTo;
4425             olddev->data.spice.auth.expires = dev->data.spice.auth.expires;
4426             olddev->data.spice.auth.connected = dev->data.spice.auth.connected;
4427         } else {
4428             VIR_DEBUG("Not updating since password didn't change");
4429         }
4430         break;
4431 
4432     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
4433     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
4434     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
4435     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
4436         virReportError(VIR_ERR_INTERNAL_ERROR,
4437                        _("unable to change config on '%s' graphics type"), type);
4438         break;
4439     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
4440     default:
4441         virReportEnumRangeError(virDomainGraphicsType, dev->type);
4442         break;
4443     }
4444 
4445     return 0;
4446 }
4447 
4448 
qemuComparePCIDevice(virDomainDef * def G_GNUC_UNUSED,virDomainDeviceDef * device G_GNUC_UNUSED,virDomainDeviceInfo * info1,void * opaque)4449 static int qemuComparePCIDevice(virDomainDef *def G_GNUC_UNUSED,
4450                                 virDomainDeviceDef *device G_GNUC_UNUSED,
4451                                 virDomainDeviceInfo *info1,
4452                                 void *opaque)
4453 {
4454     virDomainDeviceInfo *info2 = opaque;
4455 
4456     if (info1->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
4457         info2->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
4458         return 0;
4459 
4460     if (info1->addr.pci.domain == info2->addr.pci.domain &&
4461         info1->addr.pci.bus == info2->addr.pci.bus &&
4462         info1->addr.pci.slot == info2->addr.pci.slot &&
4463         info1->addr.pci.function != info2->addr.pci.function)
4464         return -1;
4465     return 0;
4466 }
4467 
qemuIsMultiFunctionDevice(virDomainDef * def,virDomainDeviceInfo * info)4468 static bool qemuIsMultiFunctionDevice(virDomainDef *def,
4469                                       virDomainDeviceInfo *info)
4470 {
4471     if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
4472         return false;
4473 
4474     if (virDomainDeviceInfoIterate(def, qemuComparePCIDevice, info) < 0)
4475         return true;
4476     return false;
4477 }
4478 
4479 
4480 static int
qemuDomainRemoveDiskDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainDiskDef * disk)4481 qemuDomainRemoveDiskDevice(virQEMUDriver *driver,
4482                            virDomainObj *vm,
4483                            virDomainDiskDef *disk)
4484 {
4485     qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
4486     g_autoptr(qemuBlockStorageSourceChainData) diskBackend = NULL;
4487     virDomainDeviceDef dev;
4488     size_t i;
4489     qemuDomainObjPrivate *priv = vm->privateData;
4490     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
4491     int ret = -1;
4492 
4493     VIR_DEBUG("Removing disk %s from domain %p %s",
4494               disk->info.alias, vm, vm->def->name);
4495 
4496 
4497     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
4498         char *chardevAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
4499 
4500         if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareChardev(chardevAlias)))
4501             goto cleanup;
4502     } else if (blockdev && !qemuDiskBusIsSD(disk->bus)) {
4503         if (diskPriv->blockjob) {
4504             /* the block job keeps reference to the disk chain */
4505             diskPriv->blockjob->disk = NULL;
4506             virObjectUnref(diskPriv->blockjob);
4507             diskPriv->blockjob = NULL;
4508         } else {
4509             if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareBlockdev(disk->src)))
4510                 goto cleanup;
4511         }
4512 
4513         if (diskPriv->nodeCopyOnRead) {
4514             if (!diskBackend)
4515                 diskBackend = g_new0(qemuBlockStorageSourceChainData, 1);
4516             diskBackend->copyOnReadNodename = g_strdup(diskPriv->nodeCopyOnRead);
4517             diskBackend->copyOnReadAttached = true;
4518         }
4519     } else {
4520         char *driveAlias;
4521 
4522         if (!(driveAlias = qemuAliasDiskDriveFromDisk(disk)))
4523             goto cleanup;
4524 
4525         if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareDrive(disk->src, driveAlias)))
4526             goto cleanup;
4527     }
4528 
4529     for (i = 0; i < vm->def->ndisks; i++) {
4530         if (vm->def->disks[i] == disk) {
4531             virDomainDiskRemove(vm->def, i);
4532             break;
4533         }
4534     }
4535 
4536     qemuDomainObjEnterMonitor(driver, vm);
4537 
4538     if (diskBackend)
4539         qemuBlockStorageSourceChainDetach(priv->mon, diskBackend);
4540 
4541     if (qemuDomainObjExitMonitor(driver, vm) < 0)
4542         goto cleanup;
4543 
4544     virDomainAuditDisk(vm, disk->src, NULL, "detach", true);
4545 
4546     qemuDomainReleaseDeviceAddress(vm, &disk->info);
4547 
4548     /* tear down disk security access */
4549     if (diskBackend)
4550         qemuDomainStorageSourceChainAccessRevoke(driver, vm, disk->src);
4551 
4552     dev.type = VIR_DOMAIN_DEVICE_DISK;
4553     dev.data.disk = disk;
4554     ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
4555 
4556     if (virStorageSourceChainHasManagedPR(disk->src) &&
4557         qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
4558         goto cleanup;
4559 
4560     if (disk->transient) {
4561         VIR_DEBUG("Removing transient overlay '%s' of disk '%s'",
4562                   disk->src->path, disk->dst);
4563         if (qemuDomainStorageFileInit(driver, vm, disk->src, NULL) >= 0) {
4564             virStorageSourceUnlink(disk->src);
4565             virStorageSourceDeinit(disk->src);
4566         }
4567     }
4568 
4569     ret = 0;
4570 
4571  cleanup:
4572     virDomainDiskDefFree(disk);
4573     return ret;
4574 }
4575 
4576 
4577 static int
qemuDomainRemoveControllerDevice(virDomainObj * vm,virDomainControllerDef * controller)4578 qemuDomainRemoveControllerDevice(virDomainObj *vm,
4579                                  virDomainControllerDef *controller)
4580 {
4581     size_t i;
4582 
4583     VIR_DEBUG("Removing controller %s from domain %p %s",
4584               controller->info.alias, vm, vm->def->name);
4585 
4586     for (i = 0; i < vm->def->ncontrollers; i++) {
4587         if (vm->def->controllers[i] == controller) {
4588             virDomainControllerRemove(vm->def, i);
4589             break;
4590         }
4591     }
4592 
4593     qemuDomainReleaseDeviceAddress(vm, &controller->info);
4594     virDomainControllerDefFree(controller);
4595     return 0;
4596 }
4597 
4598 
4599 static int
qemuDomainRemoveMemoryDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainMemoryDef * mem)4600 qemuDomainRemoveMemoryDevice(virQEMUDriver *driver,
4601                              virDomainObj *vm,
4602                              virDomainMemoryDef *mem)
4603 {
4604     qemuDomainObjPrivate *priv = vm->privateData;
4605     unsigned long long oldmem = virDomainDefGetMemoryTotal(vm->def);
4606     unsigned long long newmem = oldmem - mem->size;
4607     g_autofree char *backendAlias = NULL;
4608     int rc;
4609     int idx;
4610 
4611     VIR_DEBUG("Removing memory device %s from domain %p %s",
4612               mem->info.alias, vm, vm->def->name);
4613 
4614     backendAlias = g_strdup_printf("mem%s", mem->info.alias);
4615 
4616     qemuDomainObjEnterMonitor(driver, vm);
4617     rc = qemuMonitorDelObject(priv->mon, backendAlias, true);
4618     if (qemuDomainObjExitMonitor(driver, vm) < 0)
4619         rc = -1;
4620 
4621     virDomainAuditMemory(vm, oldmem, newmem, "update", rc == 0);
4622     if (rc < 0)
4623         return -1;
4624 
4625     if ((idx = virDomainMemoryFindByDef(vm->def, mem)) >= 0)
4626         virDomainMemoryRemove(vm->def, idx);
4627 
4628     if (qemuSecurityRestoreMemoryLabel(driver, vm, mem) < 0)
4629         VIR_WARN("Unable to restore security label on memdev");
4630 
4631     if (qemuTeardownMemoryDevicesCgroup(vm, mem) < 0)
4632         VIR_WARN("Unable to remove memory device cgroup ACL");
4633 
4634     if (qemuDomainNamespaceTeardownMemory(vm, mem) <  0)
4635         VIR_WARN("Unable to remove memory device from /dev");
4636 
4637     if (qemuProcessDestroyMemoryBackingPath(driver, vm, mem) < 0)
4638         VIR_WARN("Unable to destroy memory backing path");
4639 
4640     qemuDomainReleaseMemoryDeviceSlot(vm, mem);
4641 
4642     virDomainMemoryDefFree(mem);
4643 
4644     /* fix the balloon size */
4645     ignore_value(qemuProcessRefreshBalloonState(driver, vm, QEMU_ASYNC_JOB_NONE));
4646 
4647     /* decrease the mlock limit after memory unplug if necessary */
4648     ignore_value(qemuDomainAdjustMaxMemLock(vm, false));
4649 
4650     return 0;
4651 }
4652 
4653 
4654 static void
qemuDomainRemovePCIHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)4655 qemuDomainRemovePCIHostDevice(virQEMUDriver *driver,
4656                               virDomainObj *vm,
4657                               virDomainHostdevDef *hostdev)
4658 {
4659     qemuHostdevReAttachPCIDevices(driver, vm->def->name, &hostdev, 1);
4660     qemuDomainReleaseDeviceAddress(vm, hostdev->info);
4661 }
4662 
4663 static void
qemuDomainRemoveUSBHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)4664 qemuDomainRemoveUSBHostDevice(virQEMUDriver *driver,
4665                               virDomainObj *vm,
4666                               virDomainHostdevDef *hostdev)
4667 {
4668     qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
4669     qemuDomainReleaseDeviceAddress(vm, hostdev->info);
4670 }
4671 
4672 static void
qemuDomainRemoveSCSIHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)4673 qemuDomainRemoveSCSIHostDevice(virQEMUDriver *driver,
4674                                virDomainObj *vm,
4675                                virDomainHostdevDef *hostdev)
4676 {
4677     qemuHostdevReAttachSCSIDevices(driver, vm->def->name, &hostdev, 1);
4678 }
4679 
4680 static void
qemuDomainRemoveSCSIVHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)4681 qemuDomainRemoveSCSIVHostDevice(virQEMUDriver *driver,
4682                                 virDomainObj *vm,
4683                                 virDomainHostdevDef *hostdev)
4684 {
4685     qemuHostdevReAttachSCSIVHostDevices(driver, vm->def->name, &hostdev, 1);
4686 }
4687 
4688 
4689 static void
qemuDomainRemoveMediatedDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)4690 qemuDomainRemoveMediatedDevice(virQEMUDriver *driver,
4691                                virDomainObj *vm,
4692                                virDomainHostdevDef *hostdev)
4693 {
4694     qemuHostdevReAttachMediatedDevices(driver, vm->def->name, &hostdev, 1);
4695     qemuDomainReleaseDeviceAddress(vm, hostdev->info);
4696 }
4697 
4698 
4699 static int
qemuDomainRemoveHostDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainHostdevDef * hostdev)4700 qemuDomainRemoveHostDevice(virQEMUDriver *driver,
4701                            virDomainObj *vm,
4702                            virDomainHostdevDef *hostdev)
4703 {
4704     virDomainNetDef *net = NULL;
4705     size_t i;
4706     qemuDomainObjPrivate *priv = vm->privateData;
4707 
4708     VIR_DEBUG("Removing host device %s from domain %p %s",
4709               hostdev->info->alias, vm, vm->def->name);
4710 
4711     if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
4712         g_autoptr(qemuBlockStorageSourceAttachData) detachscsi = NULL;
4713 
4714         detachscsi = qemuBuildHostdevSCSIDetachPrepare(hostdev, priv->qemuCaps);
4715 
4716         qemuDomainObjEnterMonitor(driver, vm);
4717         qemuBlockStorageSourceAttachRollback(priv->mon, detachscsi);
4718         if (qemuDomainObjExitMonitor(driver, vm) < 0)
4719             return -1;
4720     }
4721 
4722     if (hostdev->parentnet) {
4723         net = hostdev->parentnet;
4724         for (i = 0; i < vm->def->nnets; i++) {
4725             if (vm->def->nets[i] == hostdev->parentnet) {
4726                 virDomainNetRemove(vm->def, i);
4727                 break;
4728             }
4729         }
4730     }
4731 
4732     for (i = 0; i < vm->def->nhostdevs; i++) {
4733         if (vm->def->hostdevs[i] == hostdev) {
4734             virDomainHostdevRemove(vm->def, i);
4735             break;
4736         }
4737     }
4738 
4739     virDomainAuditHostdev(vm, hostdev, "detach", true);
4740 
4741     if (!virHostdevIsVFIODevice(hostdev) &&
4742         qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
4743         VIR_WARN("Failed to restore host device labelling");
4744 
4745     if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
4746         VIR_WARN("Failed to remove host device cgroup ACL");
4747 
4748     if (qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
4749         VIR_WARN("Unable to remove host device from /dev");
4750 
4751     switch ((virDomainHostdevSubsysType)hostdev->source.subsys.type) {
4752     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
4753         qemuDomainRemovePCIHostDevice(driver, vm, hostdev);
4754         /* QEMU might no longer need to lock as much memory, eg. we just
4755          * detached the last VFIO device, so adjust the limit here */
4756         if (qemuDomainAdjustMaxMemLock(vm, false) < 0)
4757             VIR_WARN("Failed to adjust locked memory limit");
4758         break;
4759     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
4760         qemuDomainRemoveUSBHostDevice(driver, vm, hostdev);
4761         break;
4762     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
4763         qemuDomainRemoveSCSIHostDevice(driver, vm, hostdev);
4764         break;
4765     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
4766         qemuDomainRemoveSCSIVHostDevice(driver, vm, hostdev);
4767         break;
4768     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
4769         qemuDomainRemoveMediatedDevice(driver, vm, hostdev);
4770         break;
4771     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
4772         break;
4773     }
4774 
4775     virDomainHostdevDefFree(hostdev);
4776 
4777     if (net) {
4778         if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
4779             g_autoptr(virConnect) conn = virGetConnectNetwork();
4780             if (conn)
4781                 virDomainNetReleaseActualDevice(conn, vm->def, net);
4782             else
4783                 VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
4784         }
4785         virDomainNetDefFree(net);
4786     }
4787 
4788     return 0;
4789 }
4790 
4791 
4792 static int
qemuDomainRemoveNetDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainNetDef * net)4793 qemuDomainRemoveNetDevice(virQEMUDriver *driver,
4794                           virDomainObj *vm,
4795                           virDomainNetDef *net)
4796 {
4797     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
4798     qemuDomainObjPrivate *priv = vm->privateData;
4799     g_autofree char *hostnet_name = NULL;
4800     g_autofree char *charDevAlias = NULL;
4801     size_t i;
4802     int actualType = virDomainNetGetActualType(net);
4803 
4804     if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
4805         /* this function handles all hostdev and netdev cleanup */
4806         return qemuDomainRemoveHostDevice(driver, vm,
4807                                           virDomainNetGetActualHostdev(net));
4808     }
4809 
4810     VIR_DEBUG("Removing network interface %s from domain %p %s",
4811               net->info.alias, vm, vm->def->name);
4812 
4813     hostnet_name = g_strdup_printf("host%s", net->info.alias);
4814     if (!(charDevAlias = qemuAliasChardevFromDevAlias(net->info.alias)))
4815         return -1;
4816 
4817     if (virNetDevSupportsBandwidth(virDomainNetGetActualType(net))) {
4818         if (virDomainNetDefIsOvsport(net)) {
4819             if (virNetDevOpenvswitchInterfaceClearQos(net->ifname, vm->def->uuid) < 0)
4820                 VIR_WARN("cannot clear bandwidth setting for ovs device : %s",
4821                          net->ifname);
4822         } else if (virNetDevBandwidthClear(net->ifname) < 0) {
4823             VIR_WARN("cannot clear bandwidth setting for device : %s",
4824                      net->ifname);
4825         }
4826     }
4827 
4828     /* deactivate the tap/macvtap device on the host, which could also
4829      * affect the parent device (e.g. macvtap passthrough mode sets
4830      * the parent device offline)
4831      */
4832     ignore_value(qemuInterfaceStopDevice(net));
4833 
4834     qemuDomainObjEnterMonitor(driver, vm);
4835     if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
4836         if (qemuDomainObjExitMonitor(driver, vm) < 0)
4837             return -1;
4838         virDomainAuditNet(vm, net, NULL, "detach", false);
4839         return -1;
4840     }
4841 
4842     if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
4843         /* vhostuser has a chardev too */
4844         if (qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0) {
4845             /* well, this is a messy situation. Guest visible PCI device has
4846              * been removed, netdev too but chardev not. The best seems to be
4847              * to just ignore the error and carry on.
4848              */
4849         }
4850     } else if (actualType == VIR_DOMAIN_NET_TYPE_VDPA) {
4851         int vdpafdset = -1;
4852         g_autoptr(qemuMonitorFdsets) fdsets = NULL;
4853 
4854         /* query qemu for which fdset is associated with the fd that we passed
4855          * to qemu via 'add-fd' for this vdpa device. If we don't remove the
4856          * fd, qemu will keep it open */
4857         if (qemuMonitorQueryFdsets(priv->mon, &fdsets) == 0) {
4858             for (i = 0; i < fdsets->nfdsets && vdpafdset < 0; i++) {
4859                 size_t j;
4860                 qemuMonitorFdsetInfo *set = &fdsets->fdsets[i];
4861 
4862                 for (j = 0; j < set->nfds; j++) {
4863                     qemuMonitorFdsetFdInfo *fdinfo = &set->fds[j];
4864                     if (STREQ_NULLABLE(fdinfo->opaque, net->data.vdpa.devicepath)) {
4865                         vdpafdset = set->id;
4866                         break;
4867                     }
4868                 }
4869             }
4870         }
4871 
4872         if (vdpafdset < 0) {
4873             VIR_WARN("Cannot determine fdset for vdpa device");
4874         } else {
4875             if (qemuMonitorRemoveFdset(priv->mon, vdpafdset) < 0) {
4876                 /* if it fails, there's not much we can do... just carry on */
4877                 VIR_WARN("failed to close vdpa device");
4878             }
4879         }
4880     }
4881 
4882 
4883     if (qemuDomainObjExitMonitor(driver, vm) < 0)
4884         return -1;
4885 
4886     if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
4887         qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net);
4888 
4889     virDomainAuditNet(vm, net, NULL, "detach", true);
4890 
4891     for (i = 0; i < vm->def->nnets; i++) {
4892         if (vm->def->nets[i] == net) {
4893             virDomainNetRemove(vm->def, i);
4894             break;
4895         }
4896     }
4897 
4898     qemuDomainReleaseDeviceAddress(vm, &net->info);
4899     virDomainConfNWFilterTeardown(net);
4900 
4901     if (cfg->macFilter && (net->ifname != NULL)) {
4902         ignore_value(ebtablesRemoveForwardAllowIn(driver->ebtables,
4903                                                   net->ifname,
4904                                                   &net->mac));
4905     }
4906 
4907     if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
4908         ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
4909                          net->ifname, &net->mac,
4910                          virDomainNetGetActualDirectDev(net),
4911                          virDomainNetGetActualDirectMode(net),
4912                          virDomainNetGetActualVirtPortProfile(net),
4913                          cfg->stateDir));
4914     }
4915 
4916     if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
4917         if (qemuSecurityRestoreNetdevLabel(driver, vm, net) < 0)
4918             VIR_WARN("Unable to restore security label on vhostuser char device");
4919     }
4920 
4921     qemuDomainNetDeviceVportRemove(net);
4922 
4923     if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
4924         g_autoptr(virConnect) conn = virGetConnectNetwork();
4925         if (conn)
4926             virDomainNetReleaseActualDevice(conn, vm->def, net);
4927         else
4928             VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
4929     } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
4930         if (net->downscript)
4931             virNetDevRunEthernetScript(net->ifname, net->downscript);
4932     }
4933     virDomainNetDefFree(net);
4934     return 0;
4935 }
4936 
4937 
4938 static int
qemuDomainRemoveChrDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainChrDef * chr,bool monitor)4939 qemuDomainRemoveChrDevice(virQEMUDriver *driver,
4940                           virDomainObj *vm,
4941                           virDomainChrDef *chr,
4942                           bool monitor)
4943 {
4944     virObjectEvent *event;
4945     g_autofree char *charAlias = NULL;
4946     qemuDomainObjPrivate *priv = vm->privateData;
4947     int rc = 0;
4948 
4949     VIR_DEBUG("Removing character device %s from domain %p %s",
4950               chr->info.alias, vm, vm->def->name);
4951 
4952     if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
4953         return -1;
4954 
4955     if (monitor) {
4956         qemuDomainObjEnterMonitor(driver, vm);
4957         rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
4958         if (qemuDomainObjExitMonitor(driver, vm) < 0)
4959             return -1;
4960     }
4961 
4962     if (rc == 0 &&
4963         qemuDomainDelChardevTLSObjects(driver, vm, chr->source, charAlias) < 0)
4964         return -1;
4965 
4966     virDomainAuditChardev(vm, chr, NULL, "detach", rc == 0);
4967 
4968     if (rc < 0)
4969         return -1;
4970 
4971     if (qemuTeardownChardevCgroup(vm, chr) < 0)
4972         VIR_WARN("Failed to remove chr device cgroup ACL");
4973 
4974     if (qemuSecurityRestoreChardevLabel(driver, vm, chr) < 0)
4975         VIR_WARN("Unable to restore security label on char device");
4976 
4977     if (qemuDomainNamespaceTeardownChardev(vm, chr) < 0)
4978         VIR_WARN("Unable to remove chr device from /dev");
4979 
4980     qemuDomainReleaseDeviceAddress(vm, &chr->info);
4981     qemuDomainChrRemove(vm->def, chr);
4982 
4983     /* The caller does not emit the event, so we must do it here. Note
4984      * that the event should be reported only after all backend
4985      * teardown is completed.
4986      */
4987     event = virDomainEventDeviceRemovedNewFromObj(vm, chr->info.alias);
4988     virObjectEventStateQueue(driver->domainEventState, event);
4989 
4990     virDomainChrDefFree(chr);
4991     return 0;
4992 }
4993 
4994 
4995 static int
qemuDomainRemoveRNGDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainRNGDef * rng)4996 qemuDomainRemoveRNGDevice(virQEMUDriver *driver,
4997                           virDomainObj *vm,
4998                           virDomainRNGDef *rng)
4999 {
5000     g_autofree char *charAlias = NULL;
5001     g_autofree char *objAlias = NULL;
5002     qemuDomainObjPrivate *priv = vm->privateData;
5003     ssize_t idx;
5004     int rc = 0;
5005 
5006     VIR_DEBUG("Removing RNG device %s from domain %p %s",
5007               rng->info.alias, vm, vm->def->name);
5008 
5009 
5010     objAlias = g_strdup_printf("obj%s", rng->info.alias);
5011 
5012     if (!(charAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
5013         return -1;
5014 
5015     qemuDomainObjEnterMonitor(driver, vm);
5016 
5017     if (qemuMonitorDelObject(priv->mon, objAlias, true) < 0)
5018         rc = -1;
5019 
5020     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
5021         rc == 0 &&
5022         qemuMonitorDetachCharDev(priv->mon, charAlias) < 0)
5023         rc = -1;
5024 
5025     if (qemuDomainObjExitMonitor(driver, vm) < 0)
5026         return -1;
5027 
5028     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
5029         rc == 0 &&
5030         qemuDomainDelChardevTLSObjects(driver, vm, rng->source.chardev,
5031                                        charAlias) < 0)
5032         rc = -1;
5033 
5034     virDomainAuditRNG(vm, rng, NULL, "detach", rc == 0);
5035 
5036     if (rc < 0)
5037         return -1;
5038 
5039     if (qemuTeardownRNGCgroup(vm, rng) < 0)
5040         VIR_WARN("Failed to remove RNG device cgroup ACL");
5041 
5042     if (qemuDomainNamespaceTeardownRNG(vm, rng) < 0)
5043         VIR_WARN("Unable to remove RNG device from /dev");
5044 
5045     if ((idx = virDomainRNGFind(vm->def, rng)) >= 0)
5046         virDomainRNGRemove(vm->def, idx);
5047     qemuDomainReleaseDeviceAddress(vm, &rng->info);
5048     virDomainRNGDefFree(rng);
5049     return 0;
5050 }
5051 
5052 
5053 static int
qemuDomainRemoveShmemDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainShmemDef * shmem)5054 qemuDomainRemoveShmemDevice(virQEMUDriver *driver,
5055                             virDomainObj *vm,
5056                             virDomainShmemDef *shmem)
5057 {
5058     int rc;
5059     ssize_t idx = -1;
5060     g_autofree char *charAlias = NULL;
5061     g_autofree char *memAlias = NULL;
5062     qemuDomainObjPrivate *priv = vm->privateData;
5063 
5064     VIR_DEBUG("Removing shmem device %s from domain %p %s",
5065               shmem->info.alias, vm, vm->def->name);
5066 
5067     if (shmem->server.enabled) {
5068         charAlias = g_strdup_printf("char%s", shmem->info.alias);
5069     } else {
5070         memAlias = g_strdup_printf("shmmem-%s", shmem->info.alias);
5071     }
5072 
5073     qemuDomainObjEnterMonitor(driver, vm);
5074 
5075     if (shmem->server.enabled)
5076         rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
5077     else
5078         rc = qemuMonitorDelObject(priv->mon, memAlias, true);
5079 
5080     if (qemuDomainObjExitMonitor(driver, vm) < 0)
5081         return -1;
5082 
5083     virDomainAuditShmem(vm, shmem, "detach", rc == 0);
5084 
5085     if (rc < 0)
5086         return -1;
5087 
5088     if ((idx = virDomainShmemDefFind(vm->def, shmem)) >= 0)
5089         virDomainShmemDefRemove(vm->def, idx);
5090     qemuDomainReleaseDeviceAddress(vm, &shmem->info);
5091     virDomainShmemDefFree(shmem);
5092 
5093     return 0;
5094 }
5095 
5096 
5097 static int
qemuDomainRemoveWatchdog(virDomainObj * vm,virDomainWatchdogDef * watchdog)5098 qemuDomainRemoveWatchdog(virDomainObj *vm,
5099                          virDomainWatchdogDef *watchdog)
5100 {
5101     VIR_DEBUG("Removing watchdog %s from domain %p %s",
5102               watchdog->info.alias, vm, vm->def->name);
5103 
5104     qemuDomainReleaseDeviceAddress(vm, &watchdog->info);
5105     virDomainWatchdogDefFree(vm->def->watchdog);
5106     vm->def->watchdog = NULL;
5107     return 0;
5108 }
5109 
5110 
5111 static int
qemuDomainRemoveInputDevice(virDomainObj * vm,virDomainInputDef * dev)5112 qemuDomainRemoveInputDevice(virDomainObj *vm,
5113                             virDomainInputDef *dev)
5114 {
5115     size_t i;
5116 
5117     VIR_DEBUG("Removing input device %s from domain %p %s",
5118               dev->info.alias, vm, vm->def->name);
5119 
5120     for (i = 0; i < vm->def->ninputs; i++) {
5121         if (vm->def->inputs[i] == dev)
5122             break;
5123     }
5124     qemuDomainReleaseDeviceAddress(vm, &dev->info);
5125     if (qemuSecurityRestoreInputLabel(vm, dev) < 0)
5126         VIR_WARN("Unable to restore security label on input device");
5127 
5128     if (qemuTeardownInputCgroup(vm, dev) < 0)
5129         VIR_WARN("Unable to remove input device cgroup ACL");
5130 
5131     if (qemuDomainNamespaceTeardownInput(vm, dev) < 0)
5132         VIR_WARN("Unable to remove input device from /dev");
5133 
5134     virDomainInputDefFree(vm->def->inputs[i]);
5135     VIR_DELETE_ELEMENT(vm->def->inputs, i, vm->def->ninputs);
5136     return 0;
5137 }
5138 
5139 
5140 static int
qemuDomainRemoveVsockDevice(virDomainObj * vm,virDomainVsockDef * dev)5141 qemuDomainRemoveVsockDevice(virDomainObj *vm,
5142                             virDomainVsockDef *dev)
5143 {
5144     VIR_DEBUG("Removing vsock device %s from domain %p %s",
5145               dev->info.alias, vm, vm->def->name);
5146 
5147     qemuDomainReleaseDeviceAddress(vm, &dev->info);
5148     virDomainVsockDefFree(vm->def->vsock);
5149     vm->def->vsock = NULL;
5150     return 0;
5151 }
5152 
5153 
5154 static int
qemuDomainRemoveRedirdevDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainRedirdevDef * dev)5155 qemuDomainRemoveRedirdevDevice(virQEMUDriver *driver,
5156                                virDomainObj *vm,
5157                                virDomainRedirdevDef *dev)
5158 {
5159     qemuDomainObjPrivate *priv = vm->privateData;
5160     g_autofree char *charAlias = NULL;
5161     ssize_t idx;
5162 
5163     VIR_DEBUG("Removing redirdev device %s from domain %p %s",
5164               dev->info.alias, vm, vm->def->name);
5165 
5166     if (!(charAlias = qemuAliasChardevFromDevAlias(dev->info.alias)))
5167         return -1;
5168 
5169     qemuDomainObjEnterMonitor(driver, vm);
5170     /* DeviceDel from Detach may remove chardev,
5171      * so we cannot rely on return status to delete TLS chardevs.
5172      */
5173     ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
5174 
5175     if (qemuDomainObjExitMonitor(driver, vm) < 0)
5176         return -1;
5177 
5178     if (qemuDomainDelChardevTLSObjects(driver, vm, dev->source, charAlias) < 0)
5179         return -1;
5180 
5181     virDomainAuditRedirdev(vm, dev, "detach", true);
5182 
5183     if ((idx = virDomainRedirdevDefFind(vm->def, dev)) >= 0)
5184         virDomainRedirdevDefRemove(vm->def, idx);
5185     qemuDomainReleaseDeviceAddress(vm, &dev->info);
5186     virDomainRedirdevDefFree(dev);
5187 
5188     return 0;
5189 }
5190 
5191 
5192 static int
qemuDomainRemoveFSDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainFSDef * fs)5193 qemuDomainRemoveFSDevice(virQEMUDriver *driver,
5194                          virDomainObj *vm,
5195                          virDomainFSDef *fs)
5196 {
5197     g_autofree char *charAlias = NULL;
5198     qemuDomainObjPrivate *priv = vm->privateData;
5199     ssize_t idx;
5200     int rc = 0;
5201 
5202     VIR_DEBUG("Removing FS device %s from domain %p %s",
5203               fs->info.alias, vm, vm->def->name);
5204 
5205     if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
5206         charAlias = qemuDomainGetVhostUserChrAlias(fs->info.alias);
5207 
5208         qemuDomainObjEnterMonitor(driver, vm);
5209 
5210         if (qemuMonitorDetachCharDev(priv->mon, charAlias) < 0)
5211             rc = -1;
5212 
5213         if (qemuDomainObjExitMonitor(driver, vm) < 0)
5214             return -1;
5215     }
5216 
5217     virDomainAuditFS(vm, fs, NULL, "detach", rc == 0);
5218 
5219     if (rc < 0)
5220         return -1;
5221 
5222     if (!fs->sock && fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS)
5223         qemuVirtioFSStop(driver, vm, fs);
5224 
5225     if ((idx = virDomainFSDefFind(vm->def, fs)) >= 0)
5226         virDomainFSRemove(vm->def, idx);
5227     qemuDomainReleaseDeviceAddress(vm, &fs->info);
5228     virDomainFSDefFree(fs);
5229     return 0;
5230 }
5231 
5232 
5233 static void
qemuDomainRemoveAuditDevice(virDomainObj * vm,virDomainDeviceDef * detach,bool success)5234 qemuDomainRemoveAuditDevice(virDomainObj *vm,
5235                             virDomainDeviceDef *detach,
5236                             bool success)
5237 {
5238     switch ((virDomainDeviceType)detach->type) {
5239     case VIR_DOMAIN_DEVICE_DISK:
5240         virDomainAuditDisk(vm, detach->data.disk->src, NULL, "detach", success);
5241         break;
5242     case VIR_DOMAIN_DEVICE_NET:
5243         virDomainAuditNet(vm, detach->data.net, NULL, "detach", success);
5244         break;
5245     case VIR_DOMAIN_DEVICE_HOSTDEV:
5246         virDomainAuditHostdev(vm, detach->data.hostdev, "detach", success);
5247         break;
5248     case VIR_DOMAIN_DEVICE_INPUT:
5249         virDomainAuditInput(vm, detach->data.input, "detach", success);
5250         break;
5251     case VIR_DOMAIN_DEVICE_CHR:
5252         virDomainAuditChardev(vm, detach->data.chr, NULL, "detach", success);
5253         break;
5254     case VIR_DOMAIN_DEVICE_RNG:
5255         virDomainAuditRNG(vm, detach->data.rng, NULL, "detach", success);
5256         break;
5257     case VIR_DOMAIN_DEVICE_MEMORY: {
5258         unsigned long long oldmem = virDomainDefGetMemoryTotal(vm->def);
5259         unsigned long long newmem = oldmem - detach->data.memory->size;
5260 
5261         virDomainAuditMemory(vm, oldmem, newmem, "update", success);
5262         break;
5263     }
5264     case VIR_DOMAIN_DEVICE_SHMEM:
5265         virDomainAuditShmem(vm, detach->data.shmem, "detach", success);
5266         break;
5267     case VIR_DOMAIN_DEVICE_REDIRDEV:
5268         virDomainAuditRedirdev(vm, detach->data.redirdev, "detach", success);
5269         break;
5270 
5271     case VIR_DOMAIN_DEVICE_FS:
5272         virDomainAuditFS(vm, detach->data.fs, NULL, "detach", success);
5273         break;
5274 
5275     case VIR_DOMAIN_DEVICE_LEASE:
5276     case VIR_DOMAIN_DEVICE_CONTROLLER:
5277     case VIR_DOMAIN_DEVICE_WATCHDOG:
5278     case VIR_DOMAIN_DEVICE_VSOCK:
5279         /* These devices don't have associated audit logs */
5280         break;
5281 
5282     case VIR_DOMAIN_DEVICE_SOUND:
5283     case VIR_DOMAIN_DEVICE_VIDEO:
5284     case VIR_DOMAIN_DEVICE_GRAPHICS:
5285     case VIR_DOMAIN_DEVICE_HUB:
5286     case VIR_DOMAIN_DEVICE_SMARTCARD:
5287     case VIR_DOMAIN_DEVICE_MEMBALLOON:
5288     case VIR_DOMAIN_DEVICE_NVRAM:
5289     case VIR_DOMAIN_DEVICE_NONE:
5290     case VIR_DOMAIN_DEVICE_TPM:
5291     case VIR_DOMAIN_DEVICE_PANIC:
5292     case VIR_DOMAIN_DEVICE_IOMMU:
5293     case VIR_DOMAIN_DEVICE_AUDIO:
5294     case VIR_DOMAIN_DEVICE_LAST:
5295         /* libvirt doesn't yet support detaching these devices */
5296         break;
5297     }
5298 }
5299 
5300 
5301 int
qemuDomainRemoveDevice(virQEMUDriver * driver,virDomainObj * vm,virDomainDeviceDef * dev)5302 qemuDomainRemoveDevice(virQEMUDriver *driver,
5303                        virDomainObj *vm,
5304                        virDomainDeviceDef *dev)
5305 {
5306     virDomainDeviceInfo *info;
5307     virObjectEvent *event;
5308     g_autofree char *alias = NULL;
5309 
5310     /*
5311      * save the alias to use when sending a DEVICE_REMOVED event after
5312      * all other teardown is complete
5313      */
5314     if ((info = virDomainDeviceGetInfo(dev)))
5315         alias = g_strdup(info->alias);
5316     info = NULL;
5317 
5318     switch ((virDomainDeviceType)dev->type) {
5319     case VIR_DOMAIN_DEVICE_CHR:
5320         /* We must return directly after calling
5321          * qemuDomainRemoveChrDevice because it is called directly
5322          * from other places, so it must be completely self-contained
5323          * and can't take advantage of any common code at the end of
5324          * qemuDomainRemoveDevice().
5325          */
5326         return qemuDomainRemoveChrDevice(driver, vm, dev->data.chr, true);
5327 
5328         /*
5329          * all of the following qemuDomainRemove*Device() functions
5330          * are (and must be) only called from this function, so any
5331          * code that is common to them all can be pulled out and put
5332          * into this function.
5333          */
5334     case VIR_DOMAIN_DEVICE_DISK:
5335         if (qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk) < 0)
5336             return -1;
5337         break;
5338     case VIR_DOMAIN_DEVICE_CONTROLLER:
5339         if (qemuDomainRemoveControllerDevice(vm, dev->data.controller) < 0)
5340             return -1;
5341         break;
5342     case VIR_DOMAIN_DEVICE_NET:
5343         if (qemuDomainRemoveNetDevice(driver, vm, dev->data.net) < 0)
5344             return -1;
5345         break;
5346     case VIR_DOMAIN_DEVICE_HOSTDEV:
5347         if (qemuDomainRemoveHostDevice(driver, vm, dev->data.hostdev) < 0)
5348             return -1;
5349         break;
5350     case VIR_DOMAIN_DEVICE_RNG:
5351         if (qemuDomainRemoveRNGDevice(driver, vm, dev->data.rng) < 0)
5352             return -1;
5353         break;
5354     case VIR_DOMAIN_DEVICE_MEMORY:
5355         if (qemuDomainRemoveMemoryDevice(driver, vm, dev->data.memory) < 0)
5356             return -1;
5357         break;
5358     case VIR_DOMAIN_DEVICE_SHMEM:
5359         if (qemuDomainRemoveShmemDevice(driver, vm, dev->data.shmem) < 0)
5360             return -1;
5361         break;
5362     case VIR_DOMAIN_DEVICE_INPUT:
5363         if (qemuDomainRemoveInputDevice(vm, dev->data.input) < 0)
5364             return -1;
5365         break;
5366     case VIR_DOMAIN_DEVICE_REDIRDEV:
5367         if (qemuDomainRemoveRedirdevDevice(driver, vm, dev->data.redirdev) < 0)
5368             return -1;
5369         break;
5370     case VIR_DOMAIN_DEVICE_WATCHDOG:
5371         if (qemuDomainRemoveWatchdog(vm, dev->data.watchdog) < 0)
5372             return -1;
5373         break;
5374     case VIR_DOMAIN_DEVICE_VSOCK:
5375         if (qemuDomainRemoveVsockDevice(vm, dev->data.vsock) < 0)
5376             return -1;
5377         break;
5378 
5379     case VIR_DOMAIN_DEVICE_FS:
5380         if (qemuDomainRemoveFSDevice(driver, vm, dev->data.fs) < 0)
5381             return -1;
5382         break;
5383 
5384     case VIR_DOMAIN_DEVICE_NONE:
5385     case VIR_DOMAIN_DEVICE_LEASE:
5386     case VIR_DOMAIN_DEVICE_SOUND:
5387     case VIR_DOMAIN_DEVICE_VIDEO:
5388     case VIR_DOMAIN_DEVICE_GRAPHICS:
5389     case VIR_DOMAIN_DEVICE_HUB:
5390     case VIR_DOMAIN_DEVICE_SMARTCARD:
5391     case VIR_DOMAIN_DEVICE_MEMBALLOON:
5392     case VIR_DOMAIN_DEVICE_NVRAM:
5393     case VIR_DOMAIN_DEVICE_TPM:
5394     case VIR_DOMAIN_DEVICE_PANIC:
5395     case VIR_DOMAIN_DEVICE_IOMMU:
5396     case VIR_DOMAIN_DEVICE_AUDIO:
5397     case VIR_DOMAIN_DEVICE_LAST:
5398         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
5399                        _("don't know how to remove a %s device"),
5400                        virDomainDeviceTypeToString(dev->type));
5401         break;
5402     }
5403 
5404     event = virDomainEventDeviceRemovedNewFromObj(vm, alias);
5405     virObjectEventStateQueue(driver->domainEventState, event);
5406 
5407     return 0;
5408 }
5409 
5410 
5411 static void
qemuDomainMarkDeviceAliasForRemoval(virDomainObj * vm,const char * alias)5412 qemuDomainMarkDeviceAliasForRemoval(virDomainObj *vm,
5413                                     const char *alias)
5414 {
5415     qemuDomainObjPrivate *priv = vm->privateData;
5416 
5417     memset(&priv->unplug, 0, sizeof(priv->unplug));
5418 
5419     priv->unplug.alias = alias;
5420 }
5421 
5422 
5423 static void
qemuDomainMarkDeviceForRemoval(virDomainObj * vm,virDomainDeviceInfo * info)5424 qemuDomainMarkDeviceForRemoval(virDomainObj *vm,
5425                                virDomainDeviceInfo *info)
5426 
5427 {
5428     qemuDomainMarkDeviceAliasForRemoval(vm, info->alias);
5429 }
5430 
5431 
5432 static void
qemuDomainResetDeviceRemoval(virDomainObj * vm)5433 qemuDomainResetDeviceRemoval(virDomainObj *vm)
5434 {
5435     qemuDomainObjPrivate *priv = vm->privateData;
5436     priv->unplug.alias = NULL;
5437     priv->unplug.eventSeen = false;
5438 }
5439 
5440 
5441 unsigned long long G_GNUC_NO_INLINE
qemuDomainGetUnplugTimeout(virDomainObj * vm)5442 qemuDomainGetUnplugTimeout(virDomainObj *vm)
5443 {
5444     if (qemuDomainIsPSeries(vm->def))
5445         return QEMU_UNPLUG_TIMEOUT_PPC64;
5446 
5447     return QEMU_UNPLUG_TIMEOUT;
5448 }
5449 
5450 
5451 /* Returns:
5452  *  -1 Unplug of the device failed
5453  *
5454  *   0 removal of the device did not finish in qemuDomainRemoveDeviceWaitTime
5455  *
5456  *   1 when the caller is responsible for finishing the device removal:
5457  *      - DEVICE_DELETED event arrived before the timeout time
5458  *      - we failed to reliably wait for the event and thus use fallback behavior
5459  */
5460 static int
qemuDomainWaitForDeviceRemoval(virDomainObj * vm)5461 qemuDomainWaitForDeviceRemoval(virDomainObj *vm)
5462 {
5463     qemuDomainObjPrivate *priv = vm->privateData;
5464     unsigned long long until;
5465     int rc;
5466 
5467     if (virTimeMillisNow(&until) < 0)
5468         return 1;
5469     until += qemuDomainGetUnplugTimeout(vm);
5470 
5471     while (priv->unplug.alias) {
5472         if ((rc = virDomainObjWaitUntil(vm, until)) == 1)
5473             return 0;
5474 
5475         if (rc < 0) {
5476             VIR_WARN("Failed to wait on unplug condition for domain '%s' "
5477                      "device '%s'", vm->def->name, priv->unplug.alias);
5478             return 1;
5479         }
5480     }
5481 
5482     if (priv->unplug.status == QEMU_DOMAIN_UNPLUGGING_DEVICE_STATUS_GUEST_REJECTED) {
5483         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
5484                        _("unplug of device was rejected by the guest"));
5485         return -1;
5486     }
5487 
5488     return 1;
5489 }
5490 
5491 /* Returns:
5492  *  true    there was a thread waiting for devAlias to be removed and this
5493  *          thread will take care of finishing the removal
5494  *  false   the thread that started the removal is already gone and delegate
5495  *          finishing the removal to a new thread
5496  */
5497 bool
qemuDomainSignalDeviceRemoval(virDomainObj * vm,const char * devAlias,qemuDomainUnpluggingDeviceStatus status)5498 qemuDomainSignalDeviceRemoval(virDomainObj *vm,
5499                               const char *devAlias,
5500                               qemuDomainUnpluggingDeviceStatus status)
5501 {
5502     qemuDomainObjPrivate *priv = vm->privateData;
5503 
5504     if (STREQ_NULLABLE(priv->unplug.alias, devAlias)) {
5505         VIR_DEBUG("Removal of device '%s' continues in waiting thread", devAlias);
5506         qemuDomainResetDeviceRemoval(vm);
5507         priv->unplug.status = status;
5508         priv->unplug.eventSeen = true;
5509         virDomainObjBroadcast(vm);
5510         return true;
5511     }
5512     return false;
5513 }
5514 
5515 
5516 static int
qemuFindDisk(virDomainDef * def,const char * dst)5517 qemuFindDisk(virDomainDef *def, const char *dst)
5518 {
5519     size_t i;
5520 
5521     for (i = 0; i < def->ndisks; i++) {
5522         if (STREQ(def->disks[i]->dst, dst))
5523             return i;
5524     }
5525 
5526     return -1;
5527 }
5528 
5529 static int
qemuDomainDetachPrepDisk(virDomainObj * vm,virDomainDiskDef * match,virDomainDiskDef ** detach)5530 qemuDomainDetachPrepDisk(virDomainObj *vm,
5531                          virDomainDiskDef *match,
5532                          virDomainDiskDef **detach)
5533 {
5534     virDomainDiskDef *disk;
5535     int idx;
5536 
5537     if ((idx = qemuFindDisk(vm->def, match->dst)) < 0) {
5538         virReportError(VIR_ERR_DEVICE_MISSING,
5539                        _("disk %s not found"), match->dst);
5540         return -1;
5541     }
5542     *detach = disk = vm->def->disks[idx];
5543 
5544     switch ((virDomainDiskDevice) disk->device) {
5545     case VIR_DOMAIN_DISK_DEVICE_DISK:
5546     case VIR_DOMAIN_DISK_DEVICE_LUN:
5547 
5548         switch ((virDomainDiskBus) disk->bus) {
5549         case VIR_DOMAIN_DISK_BUS_VIRTIO:
5550         case VIR_DOMAIN_DISK_BUS_USB:
5551         case VIR_DOMAIN_DISK_BUS_SCSI:
5552             break;
5553 
5554         case VIR_DOMAIN_DISK_BUS_IDE:
5555         case VIR_DOMAIN_DISK_BUS_FDC:
5556         case VIR_DOMAIN_DISK_BUS_XEN:
5557         case VIR_DOMAIN_DISK_BUS_UML:
5558         case VIR_DOMAIN_DISK_BUS_SATA:
5559         case VIR_DOMAIN_DISK_BUS_SD:
5560             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
5561                            _("This type of disk cannot be hot unplugged"));
5562             return -1;
5563 
5564         case VIR_DOMAIN_DISK_BUS_NONE:
5565         case VIR_DOMAIN_DISK_BUS_LAST:
5566         default:
5567             virReportEnumRangeError(virDomainDiskBus, disk->bus);
5568             return -1;
5569         }
5570         break;
5571 
5572     case VIR_DOMAIN_DISK_DEVICE_CDROM:
5573     case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
5574         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
5575                        _("disk device type '%s' cannot be detached"),
5576                        virDomainDiskDeviceTypeToString(disk->device));
5577         return -1;
5578 
5579     case VIR_DOMAIN_DISK_DEVICE_LAST:
5580     default:
5581         virReportEnumRangeError(virDomainDiskDevice, disk->device);
5582         return -1;
5583     }
5584 
5585     if (qemuDomainDiskBlockJobIsActive(disk))
5586         return -1;
5587 
5588     return 0;
5589 }
5590 
5591 
5592 static bool
qemuDomainDiskControllerIsBusy(virDomainObj * vm,virDomainControllerDef * detach)5593 qemuDomainDiskControllerIsBusy(virDomainObj *vm,
5594                                virDomainControllerDef *detach)
5595 {
5596     size_t i;
5597     virDomainDiskDef *disk;
5598     virDomainHostdevDef *hostdev;
5599 
5600     for (i = 0; i < vm->def->ndisks; i++) {
5601         disk = vm->def->disks[i];
5602         if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
5603             /* the disk does not use disk controller */
5604             continue;
5605 
5606         /* check whether the disk uses this type controller */
5607         switch ((virDomainControllerType) detach->type) {
5608         case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
5609             if (disk->bus != VIR_DOMAIN_DISK_BUS_IDE)
5610                 continue;
5611             break;
5612 
5613         case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
5614             if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC)
5615                 continue;
5616             break;
5617 
5618         case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5619             if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)
5620                 continue;
5621             break;
5622 
5623         case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
5624             if (disk->bus != VIR_DOMAIN_DISK_BUS_SATA)
5625                 continue;
5626             break;
5627 
5628         case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
5629             /* xenbus is not supported by the qemu driver */
5630             continue;
5631 
5632         case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
5633             /* virtio-serial does not host any disks */
5634             continue;
5635 
5636         case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
5637         case VIR_DOMAIN_CONTROLLER_TYPE_USB:
5638         case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
5639         case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
5640             /* These buses have (also) other device types too so they need to
5641              * be checked elsewhere */
5642             continue;
5643 
5644         case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
5645         default:
5646             continue;
5647         }
5648 
5649         if (disk->info.addr.drive.controller == detach->idx)
5650             return true;
5651     }
5652 
5653     if (detach->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
5654         for (i = 0; i < vm->def->nhostdevs; i++) {
5655             hostdev = vm->def->hostdevs[i];
5656             if (!virHostdevIsSCSIDevice(hostdev))
5657                 continue;
5658 
5659             if (hostdev->info->addr.drive.controller == detach->idx)
5660                 return true;
5661         }
5662     }
5663 
5664     return false;
5665 }
5666 
5667 
5668 static bool
qemuDomainControllerIsBusy(virDomainObj * vm,virDomainControllerDef * detach)5669 qemuDomainControllerIsBusy(virDomainObj *vm,
5670                            virDomainControllerDef *detach)
5671 {
5672     switch ((virDomainControllerType) detach->type) {
5673     case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
5674     case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
5675     case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5676     case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
5677         return qemuDomainDiskControllerIsBusy(vm, detach);
5678 
5679     case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
5680     case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
5681     case VIR_DOMAIN_CONTROLLER_TYPE_USB:
5682     case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
5683     case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
5684         /* detach of the controller types above is not yet supported */
5685         return false;
5686 
5687     case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
5688         /* qemu driver doesn't support xenbus */
5689         return false;
5690 
5691     case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
5692     default:
5693         return false;
5694     }
5695 }
5696 
5697 
5698 static int
qemuDomainDetachPrepController(virDomainObj * vm,virDomainControllerDef * match,virDomainControllerDef ** detach)5699 qemuDomainDetachPrepController(virDomainObj *vm,
5700                                virDomainControllerDef *match,
5701                                virDomainControllerDef **detach)
5702 {
5703     int idx;
5704     virDomainControllerDef *controller = NULL;
5705 
5706     if (match->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
5707         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
5708                        _("'%s' controller cannot be hot unplugged."),
5709                        virDomainControllerTypeToString(match->type));
5710         return -1;
5711     }
5712 
5713     if ((idx = virDomainControllerFind(vm->def, match->type, match->idx)) < 0) {
5714         virReportError(VIR_ERR_DEVICE_MISSING,
5715                        _("controller %s:%d not found"),
5716                        virDomainControllerTypeToString(match->type),
5717                        match->idx);
5718         return -1;
5719     }
5720 
5721     *detach = controller = vm->def->controllers[idx];
5722 
5723     if (qemuDomainControllerIsBusy(vm, controller)) {
5724         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
5725                        _("device cannot be detached: device is busy"));
5726         return -1;
5727     }
5728 
5729     return 0;
5730 }
5731 
5732 
5733 /* search for a hostdev matching dev and detach it */
5734 static int
qemuDomainDetachPrepHostdev(virDomainObj * vm,virDomainHostdevDef * match,virDomainHostdevDef ** detach)5735 qemuDomainDetachPrepHostdev(virDomainObj *vm,
5736                             virDomainHostdevDef *match,
5737                             virDomainHostdevDef **detach)
5738 {
5739     virDomainHostdevSubsys *subsys = &match->source.subsys;
5740     virDomainHostdevSubsysUSB *usbsrc = &subsys->u.usb;
5741     virDomainHostdevSubsysPCI *pcisrc = &subsys->u.pci;
5742     virDomainHostdevSubsysSCSI *scsisrc = &subsys->u.scsi;
5743     virDomainHostdevSubsysMediatedDev *mdevsrc = &subsys->u.mdev;
5744     virDomainHostdevDef *hostdev = NULL;
5745     int idx;
5746 
5747     if (match->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
5748         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5749                        _("hot unplug is not supported for hostdev mode '%s'"),
5750                        virDomainHostdevModeTypeToString(match->mode));
5751         return -1;
5752     }
5753 
5754     idx = virDomainHostdevFind(vm->def, match, &hostdev);
5755     *detach = hostdev;
5756 
5757     if (idx < 0) {
5758         switch (subsys->type) {
5759         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
5760             virReportError(VIR_ERR_DEVICE_MISSING,
5761                            _("host pci device " VIR_PCI_DEVICE_ADDRESS_FMT
5762                              " not found"),
5763                            pcisrc->addr.domain, pcisrc->addr.bus,
5764                            pcisrc->addr.slot, pcisrc->addr.function);
5765             break;
5766         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
5767             if (usbsrc->bus && usbsrc->device) {
5768                 virReportError(VIR_ERR_DEVICE_MISSING,
5769                                _("host usb device %03d.%03d not found"),
5770                                usbsrc->bus, usbsrc->device);
5771             } else {
5772                 virReportError(VIR_ERR_DEVICE_MISSING,
5773                                _("host usb device vendor=0x%.4x product=0x%.4x not found"),
5774                                usbsrc->vendor, usbsrc->product);
5775             }
5776             break;
5777         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
5778             if (scsisrc->protocol ==
5779                 VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
5780                 virDomainHostdevSubsysSCSIiSCSI *iscsisrc = &scsisrc->u.iscsi;
5781                 virReportError(VIR_ERR_DEVICE_MISSING,
5782                                _("host scsi iSCSI path %s not found"),
5783                                iscsisrc->src->path);
5784             } else {
5785                  virDomainHostdevSubsysSCSIHost *scsihostsrc =
5786                      &scsisrc->u.host;
5787                  virReportError(VIR_ERR_DEVICE_MISSING,
5788                                 _("host scsi device %s:%u:%u.%llu not found"),
5789                                 scsihostsrc->adapter, scsihostsrc->bus,
5790                                 scsihostsrc->target, scsihostsrc->unit);
5791             }
5792             break;
5793         }
5794         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
5795             virReportError(VIR_ERR_DEVICE_MISSING,
5796                            _("mediated device '%s' not found"),
5797                            mdevsrc->uuidstr);
5798             break;
5799         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
5800             break;
5801         default:
5802             virReportError(VIR_ERR_INTERNAL_ERROR,
5803                            _("unexpected hostdev type %d"), subsys->type);
5804             break;
5805         }
5806         return -1;
5807     }
5808 
5809     return 0;
5810 }
5811 
5812 
5813 static int
qemuDomainDetachPrepShmem(virDomainObj * vm,virDomainShmemDef * match,virDomainShmemDef ** detach)5814 qemuDomainDetachPrepShmem(virDomainObj *vm,
5815                           virDomainShmemDef *match,
5816                           virDomainShmemDef **detach)
5817 {
5818     ssize_t idx = -1;
5819     virDomainShmemDef *shmem = NULL;
5820 
5821     if ((idx = virDomainShmemDefFind(vm->def, match)) < 0) {
5822         virReportError(VIR_ERR_DEVICE_MISSING,
5823                        _("model '%s' shmem device not present "
5824                          "in domain configuration"),
5825                        virDomainShmemModelTypeToString(match->model));
5826         return -1;
5827     }
5828 
5829     *detach = shmem = vm->def->shmems[idx];
5830 
5831     switch (shmem->model) {
5832     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
5833     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
5834         break;
5835 
5836     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
5837         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
5838                        _("live detach of shmem model '%s' is not supported"),
5839                        virDomainShmemModelTypeToString(shmem->model));
5840         G_GNUC_FALLTHROUGH;
5841     case VIR_DOMAIN_SHMEM_MODEL_LAST:
5842         return -1;
5843     }
5844 
5845     return 0;
5846 }
5847 
5848 
5849 static int
qemuDomainDetachPrepWatchdog(virDomainObj * vm,virDomainWatchdogDef * match,virDomainWatchdogDef ** detach)5850 qemuDomainDetachPrepWatchdog(virDomainObj *vm,
5851                              virDomainWatchdogDef *match,
5852                              virDomainWatchdogDef **detach)
5853 {
5854     virDomainWatchdogDef *watchdog;
5855 
5856     *detach = watchdog = vm->def->watchdog;
5857 
5858     if (!watchdog) {
5859         virReportError(VIR_ERR_DEVICE_MISSING, "%s",
5860                        _("watchdog device not present in domain configuration"));
5861         return -1;
5862     }
5863 
5864     /* While domains can have up to one watchdog, the one supplied by the user
5865      * doesn't necessarily match the one domain has. Refuse to detach in such
5866      * case. */
5867     if (!(watchdog->model == match->model &&
5868           watchdog->action == match->action &&
5869           virDomainDeviceInfoAddressIsEqual(&match->info, &watchdog->info))) {
5870         virReportError(VIR_ERR_DEVICE_MISSING,
5871                        _("model '%s' watchdog device not present "
5872                          "in domain configuration"),
5873                        virDomainWatchdogModelTypeToString(watchdog->model));
5874         return -1;
5875     }
5876 
5877     if (watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
5878         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
5879                        _("hot unplug of watchdog of model %s is not supported"),
5880                        virDomainWatchdogModelTypeToString(watchdog->model));
5881         return -1;
5882     }
5883 
5884     return 0;
5885 }
5886 
5887 
5888 static int
qemuDomainDetachPrepRedirdev(virDomainObj * vm,virDomainRedirdevDef * match,virDomainRedirdevDef ** detach)5889 qemuDomainDetachPrepRedirdev(virDomainObj *vm,
5890                              virDomainRedirdevDef *match,
5891                              virDomainRedirdevDef **detach)
5892 {
5893     ssize_t idx;
5894 
5895     if ((idx = virDomainRedirdevDefFind(vm->def, match)) < 0) {
5896         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5897                        _("no matching redirdev was not found"));
5898         return -1;
5899     }
5900 
5901     *detach = vm->def->redirdevs[idx];
5902 
5903     return 0;
5904 }
5905 
5906 
5907 static int
qemuDomainDetachPrepNet(virDomainObj * vm,virDomainNetDef * match,virDomainNetDef ** detach)5908 qemuDomainDetachPrepNet(virDomainObj *vm,
5909                         virDomainNetDef *match,
5910                         virDomainNetDef **detach)
5911 {
5912     int detachidx;
5913 
5914     if ((detachidx = virDomainNetFindIdx(vm->def, match)) < 0)
5915         return -1;
5916 
5917     *detach = vm->def->nets[detachidx];
5918 
5919     return 0;
5920 }
5921 
5922 
5923 static int
qemuDomainDetachDeviceChr(virQEMUDriver * driver,virDomainObj * vm,virDomainChrDef * chr,bool async)5924 qemuDomainDetachDeviceChr(virQEMUDriver *driver,
5925                           virDomainObj *vm,
5926                           virDomainChrDef *chr,
5927                           bool async)
5928 {
5929     int ret = -1;
5930     qemuDomainObjPrivate *priv = vm->privateData;
5931     virDomainDef *vmdef = vm->def;
5932     virDomainChrDef *tmpChr;
5933     bool guestfwd = false;
5934 
5935     if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
5936         virReportError(VIR_ERR_DEVICE_MISSING,
5937                        _("chr type '%s' device not present "
5938                          "in domain configuration"),
5939                        virDomainChrDeviceTypeToString(chr->deviceType));
5940         goto cleanup;
5941     }
5942 
5943     /* guestfwd channels are not really -device rather than
5944      * -netdev. We need to treat them slightly differently. */
5945     guestfwd = tmpChr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
5946                tmpChr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD;
5947 
5948     if (!async && !guestfwd)
5949         qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
5950 
5951     if (guestfwd) {
5952         int rc;
5953         qemuDomainObjEnterMonitor(driver, vm);
5954         rc = qemuMonitorRemoveNetdev(priv->mon, tmpChr->info.alias);
5955         if (qemuDomainObjExitMonitor(driver, vm) < 0)
5956             rc = -1;
5957 
5958         if (rc < 0)
5959             goto cleanup;
5960     } else {
5961         if (qemuDomainDeleteDevice(vm, tmpChr->info.alias) < 0)
5962             goto cleanup;
5963     }
5964 
5965     if (guestfwd) {
5966         ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr, false);
5967     } else if (async) {
5968         ret = 0;
5969     } else {
5970         if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
5971             ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr, true);
5972     }
5973 
5974  cleanup:
5975     if (!async)
5976         qemuDomainResetDeviceRemoval(vm);
5977     return ret;
5978 }
5979 
5980 
5981 static int
qemuDomainDetachPrepRNG(virDomainObj * vm,virDomainRNGDef * match,virDomainRNGDef ** detach)5982 qemuDomainDetachPrepRNG(virDomainObj *vm,
5983                         virDomainRNGDef *match,
5984                         virDomainRNGDef **detach)
5985 {
5986     ssize_t idx;
5987 
5988     if ((idx = virDomainRNGFind(vm->def, match)) < 0) {
5989         virReportError(VIR_ERR_DEVICE_MISSING,
5990                        _("model '%s' RNG device not present "
5991                          "in domain configuration"),
5992                        virDomainRNGBackendTypeToString(match->model));
5993         return -1;
5994     }
5995 
5996     *detach = vm->def->rngs[idx];
5997 
5998     return 0;
5999 }
6000 
6001 
6002 static int
qemuDomainDetachPrepMemory(virDomainObj * vm,virDomainMemoryDef * match,virDomainMemoryDef ** detach)6003 qemuDomainDetachPrepMemory(virDomainObj *vm,
6004                            virDomainMemoryDef *match,
6005                            virDomainMemoryDef **detach)
6006 {
6007     int idx;
6008 
6009     if (qemuDomainMemoryDeviceAlignSize(vm->def, match) < 0)
6010         return -1;
6011 
6012     if ((idx = virDomainMemoryFindByDef(vm->def, match)) < 0) {
6013         virReportError(VIR_ERR_DEVICE_MISSING,
6014                        _("model '%s' memory device not present "
6015                          "in the domain configuration"),
6016                        virDomainMemoryModelTypeToString(match->model));
6017         return -1;
6018     }
6019 
6020     *detach = vm->def->mems[idx];
6021 
6022     return 0;
6023 }
6024 
6025 
6026 static int
qemuDomainDetachPrepInput(virDomainObj * vm,virDomainInputDef * match,virDomainInputDef ** detach)6027 qemuDomainDetachPrepInput(virDomainObj *vm,
6028                           virDomainInputDef *match,
6029                           virDomainInputDef **detach)
6030 {
6031     virDomainInputDef *input;
6032     int idx;
6033 
6034     if ((idx = virDomainInputDefFind(vm->def, match)) < 0) {
6035         virReportError(VIR_ERR_DEVICE_MISSING, "%s",
6036                        _("matching input device not found"));
6037         return -1;
6038     }
6039     *detach = input = vm->def->inputs[idx];
6040 
6041     switch ((virDomainInputBus) input->bus) {
6042     case VIR_DOMAIN_INPUT_BUS_PS2:
6043     case VIR_DOMAIN_INPUT_BUS_XEN:
6044     case VIR_DOMAIN_INPUT_BUS_PARALLELS:
6045         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
6046                        _("input device on bus '%s' cannot be detached"),
6047                        virDomainInputBusTypeToString(input->bus));
6048         return -1;
6049 
6050     case VIR_DOMAIN_INPUT_BUS_LAST:
6051     case VIR_DOMAIN_INPUT_BUS_USB:
6052     case VIR_DOMAIN_INPUT_BUS_VIRTIO:
6053     case VIR_DOMAIN_INPUT_BUS_NONE:
6054         break;
6055     }
6056 
6057     return 0;
6058 }
6059 
6060 
6061 static int
qemuDomainDetachPrepVsock(virDomainObj * vm,virDomainVsockDef * match,virDomainVsockDef ** detach)6062 qemuDomainDetachPrepVsock(virDomainObj *vm,
6063                           virDomainVsockDef *match,
6064                           virDomainVsockDef **detach)
6065 {
6066     virDomainVsockDef *vsock;
6067 
6068     *detach = vsock = vm->def->vsock;
6069     if (!vsock ||
6070         !virDomainVsockDefEquals(match, vsock)) {
6071         virReportError(VIR_ERR_DEVICE_MISSING, "%s",
6072                        _("matching vsock device not found"));
6073         return -1;
6074     }
6075 
6076     return 0;
6077 }
6078 
6079 
6080 static int
qemuDomainDetachPrepFS(virDomainObj * vm,virDomainFSDef * match,virDomainFSDef ** detach)6081 qemuDomainDetachPrepFS(virDomainObj *vm,
6082                        virDomainFSDef *match,
6083                        virDomainFSDef **detach)
6084 {
6085     ssize_t idx;
6086 
6087     if ((idx = virDomainFSDefFind(vm->def, match)) < 0) {
6088         virReportError(VIR_ERR_DEVICE_MISSING, "%s",
6089                        _("matching filesystem not found"));
6090         return -1;
6091     }
6092 
6093     if (vm->def->fss[idx]->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
6094         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
6095                        _("only virtiofs filesystems can be hotplugged"));
6096         return -1;
6097     }
6098 
6099     *detach = vm->def->fss[idx];
6100 
6101     return 0;
6102 }
6103 
6104 
6105 static int
qemuDomainDetachDeviceLease(virQEMUDriver * driver,virDomainObj * vm,virDomainLeaseDef * lease)6106 qemuDomainDetachDeviceLease(virQEMUDriver *driver,
6107                             virDomainObj *vm,
6108                             virDomainLeaseDef *lease)
6109 {
6110     virDomainLeaseDef *det_lease;
6111     int idx;
6112 
6113     if ((idx = virDomainLeaseIndex(vm->def, lease)) < 0) {
6114         virReportError(VIR_ERR_INVALID_ARG,
6115                        _("Lease %s in lockspace %s does not exist"),
6116                        lease->key, NULLSTR(lease->lockspace));
6117         return -1;
6118     }
6119 
6120     if (virDomainLockLeaseDetach(driver->lockManager, vm, lease) < 0)
6121         return -1;
6122 
6123     det_lease = virDomainLeaseRemoveAt(vm->def, idx);
6124     virDomainLeaseDefFree(det_lease);
6125     return 0;
6126 }
6127 
6128 
6129 int
qemuDomainDetachDeviceLive(virDomainObj * vm,virDomainDeviceDef * match,virQEMUDriver * driver,bool async)6130 qemuDomainDetachDeviceLive(virDomainObj *vm,
6131                            virDomainDeviceDef *match,
6132                            virQEMUDriver *driver,
6133                            bool async)
6134 {
6135     virDomainDeviceDef detach = { .type = match->type };
6136     virDomainDeviceInfo *info = NULL;
6137     int ret = -1;
6138 
6139     switch ((virDomainDeviceType)match->type) {
6140         /*
6141          * lease and chr devices don't follow the standard pattern of
6142          * the others, so they must have their own self-contained
6143          * Detach functions.
6144          */
6145     case VIR_DOMAIN_DEVICE_LEASE:
6146         return qemuDomainDetachDeviceLease(driver, vm, match->data.lease);
6147 
6148     case VIR_DOMAIN_DEVICE_CHR:
6149         return qemuDomainDetachDeviceChr(driver, vm, match->data.chr, async);
6150 
6151         /*
6152          * All the other device types follow a very similar pattern -
6153          * First we call type-specific functions to 1) locate the
6154          * device we want to detach (based on the prototype device in
6155          * match) and 2) do any device-type-specific validation to
6156          * assure it is okay to detach the device.
6157          */
6158     case VIR_DOMAIN_DEVICE_DISK:
6159         if (qemuDomainDetachPrepDisk(vm, match->data.disk,
6160                                      &detach.data.disk) < 0) {
6161             return -1;
6162         }
6163         break;
6164     case VIR_DOMAIN_DEVICE_CONTROLLER:
6165         if (qemuDomainDetachPrepController(vm, match->data.controller,
6166                                            &detach.data.controller) < 0) {
6167             return -1;
6168         }
6169         break;
6170     case VIR_DOMAIN_DEVICE_NET:
6171         if (qemuDomainDetachPrepNet(vm, match->data.net,
6172                                     &detach.data.net) < 0) {
6173             return -1;
6174         }
6175         break;
6176     case VIR_DOMAIN_DEVICE_HOSTDEV:
6177         if (qemuDomainDetachPrepHostdev(vm, match->data.hostdev,
6178                                         &detach.data.hostdev) < 0) {
6179             return -1;
6180         }
6181         break;
6182     case VIR_DOMAIN_DEVICE_RNG:
6183         if (qemuDomainDetachPrepRNG(vm, match->data.rng,
6184                                     &detach.data.rng) < 0) {
6185             return -1;
6186         }
6187         break;
6188     case VIR_DOMAIN_DEVICE_MEMORY:
6189         if (qemuDomainDetachPrepMemory(vm, match->data.memory,
6190                                        &detach.data.memory) < 0) {
6191             return -1;
6192         }
6193         break;
6194     case VIR_DOMAIN_DEVICE_SHMEM:
6195         if (qemuDomainDetachPrepShmem(vm, match->data.shmem,
6196                                       &detach.data.shmem) < 0) {
6197             return -1;
6198         }
6199         break;
6200     case VIR_DOMAIN_DEVICE_WATCHDOG:
6201         if (qemuDomainDetachPrepWatchdog(vm, match->data.watchdog,
6202                                          &detach.data.watchdog) < 0) {
6203             return -1;
6204         }
6205         break;
6206     case VIR_DOMAIN_DEVICE_INPUT:
6207         if (qemuDomainDetachPrepInput(vm, match->data.input,
6208                                       &detach.data.input) < 0) {
6209             return -1;
6210         }
6211         break;
6212     case VIR_DOMAIN_DEVICE_REDIRDEV:
6213         if (qemuDomainDetachPrepRedirdev(vm, match->data.redirdev,
6214                                          &detach.data.redirdev) < 0) {
6215             return -1;
6216         }
6217         break;
6218     case VIR_DOMAIN_DEVICE_VSOCK:
6219         if (qemuDomainDetachPrepVsock(vm, match->data.vsock,
6220                                       &detach.data.vsock) < 0) {
6221             return -1;
6222         }
6223         break;
6224 
6225     case VIR_DOMAIN_DEVICE_FS:
6226         if (qemuDomainDetachPrepFS(vm, match->data.fs,
6227                                    &detach.data.fs) < 0) {
6228             return -1;
6229         }
6230         break;
6231 
6232     case VIR_DOMAIN_DEVICE_SOUND:
6233     case VIR_DOMAIN_DEVICE_VIDEO:
6234     case VIR_DOMAIN_DEVICE_GRAPHICS:
6235     case VIR_DOMAIN_DEVICE_HUB:
6236     case VIR_DOMAIN_DEVICE_SMARTCARD:
6237     case VIR_DOMAIN_DEVICE_MEMBALLOON:
6238     case VIR_DOMAIN_DEVICE_NVRAM:
6239     case VIR_DOMAIN_DEVICE_NONE:
6240     case VIR_DOMAIN_DEVICE_TPM:
6241     case VIR_DOMAIN_DEVICE_PANIC:
6242     case VIR_DOMAIN_DEVICE_IOMMU:
6243     case VIR_DOMAIN_DEVICE_AUDIO:
6244     case VIR_DOMAIN_DEVICE_LAST:
6245         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
6246                        _("live detach of device '%s' is not supported"),
6247                        virDomainDeviceTypeToString(match->type));
6248         return -1;
6249     }
6250 
6251     /* "detach" now points to the actual device we want to detach */
6252 
6253     if (!(info = virDomainDeviceGetInfo(&detach))) {
6254         /*
6255          * This should never happen, since all of the device types in
6256          * the switch cases that end with a "break" instead of a
6257          * return have a virDeviceInfo in them.
6258          */
6259         virReportError(VIR_ERR_INTERNAL_ERROR,
6260                        _("device of type '%s' has no device info"),
6261                        virDomainDeviceTypeToString(detach.type));
6262         return -1;
6263     }
6264 
6265 
6266     /* Make generic validation checks common to all device types */
6267 
6268     if (!info->alias) {
6269         virReportError(VIR_ERR_INTERNAL_ERROR,
6270                        _("Cannot detach %s device with no alias"),
6271                        virDomainDeviceTypeToString(detach.type));
6272         return -1;
6273     }
6274 
6275     if (qemuIsMultiFunctionDevice(vm->def, info)) {
6276         virReportError(VIR_ERR_OPERATION_FAILED,
6277                        _("cannot hot unplug %s device with multifunction PCI guest address: "
6278                          VIR_PCI_DEVICE_ADDRESS_FMT),
6279                        virDomainDeviceTypeToString(detach.type),
6280                        info->addr.pci.domain, info->addr.pci.bus,
6281                        info->addr.pci.slot, info->addr.pci.function);
6282         return -1;
6283     }
6284 
6285     if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
6286 
6287         virDomainControllerDef *controller;
6288         int controllerIdx = virDomainControllerFind(vm->def,
6289                                                     VIR_DOMAIN_CONTROLLER_TYPE_PCI,
6290                                                     info->addr.pci.bus);
6291         if (controllerIdx < 0) {
6292             virReportError(VIR_ERR_OPERATION_FAILED,
6293                            _("cannot hot unplug %s device with PCI guest address: "
6294                              VIR_PCI_DEVICE_ADDRESS_FMT
6295                              " - controller not found"),
6296                            virDomainDeviceTypeToString(detach.type),
6297                            info->addr.pci.domain, info->addr.pci.bus,
6298                            info->addr.pci.slot, info->addr.pci.function);
6299             return -1;
6300         }
6301 
6302         controller = vm->def->controllers[controllerIdx];
6303         if (controller->opts.pciopts.hotplug == VIR_TRISTATE_SWITCH_OFF) {
6304             virReportError(VIR_ERR_OPERATION_FAILED,
6305                            _("cannot hot unplug %s device with PCI guest address: "
6306                              VIR_PCI_DEVICE_ADDRESS_FMT
6307                              " - not allowed by controller"),
6308                            virDomainDeviceTypeToString(detach.type),
6309                            info->addr.pci.domain, info->addr.pci.bus,
6310                            info->addr.pci.slot, info->addr.pci.function);
6311             return -1;
6312         }
6313     }
6314 
6315     /*
6316      * Issue the qemu monitor command to delete the device (based on
6317      * its alias), and optionally wait a short time in case the
6318      * DEVICE_DELETED event arrives from qemu right away.
6319      */
6320     if (!async)
6321         qemuDomainMarkDeviceForRemoval(vm, info);
6322 
6323     if (qemuDomainDeleteDevice(vm, info->alias) < 0) {
6324         if (virDomainObjIsActive(vm))
6325             qemuDomainRemoveAuditDevice(vm, &detach, false);
6326         goto cleanup;
6327     }
6328 
6329     if (async) {
6330         ret = 0;
6331     } else {
6332         if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
6333             ret = qemuDomainRemoveDevice(driver, vm, &detach);
6334     }
6335 
6336  cleanup:
6337     if (!async)
6338         qemuDomainResetDeviceRemoval(vm);
6339 
6340     return ret;
6341 }
6342 
6343 
6344 static int
qemuDomainRemoveVcpu(virQEMUDriver * driver,virDomainObj * vm,unsigned int vcpu)6345 qemuDomainRemoveVcpu(virQEMUDriver *driver,
6346                      virDomainObj *vm,
6347                      unsigned int vcpu)
6348 {
6349     qemuDomainObjPrivate *priv = vm->privateData;
6350     virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
6351     qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
6352     int oldvcpus = virDomainDefGetVcpus(vm->def);
6353     unsigned int nvcpus = vcpupriv->vcpus;
6354     virErrorPtr save_error = NULL;
6355     size_t i;
6356 
6357     if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
6358         return -1;
6359 
6360     /* validation requires us to set the expected state prior to calling it */
6361     for (i = vcpu; i < vcpu + nvcpus; i++) {
6362         vcpuinfo = virDomainDefGetVcpu(vm->def, i);
6363         vcpuinfo->online = false;
6364     }
6365 
6366     if (qemuDomainValidateVcpuInfo(vm) < 0) {
6367         /* rollback vcpu count if the setting has failed */
6368         virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
6369 
6370         for (i = vcpu; i < vcpu + nvcpus; i++) {
6371             vcpuinfo = virDomainDefGetVcpu(vm->def, i);
6372             vcpuinfo->online = true;
6373         }
6374         return -1;
6375     }
6376 
6377     virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", true);
6378 
6379     virErrorPreserveLast(&save_error);
6380 
6381     for (i = vcpu; i < vcpu + nvcpus; i++)
6382         ignore_value(virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i));
6383 
6384     virErrorRestore(&save_error);
6385 
6386     return 0;
6387 }
6388 
6389 
6390 void
qemuDomainRemoveVcpuAlias(virQEMUDriver * driver,virDomainObj * vm,const char * alias)6391 qemuDomainRemoveVcpuAlias(virQEMUDriver *driver,
6392                           virDomainObj *vm,
6393                           const char *alias)
6394 {
6395     virDomainVcpuDef *vcpu;
6396     qemuDomainVcpuPrivate *vcpupriv;
6397     size_t i;
6398 
6399     for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
6400         vcpu = virDomainDefGetVcpu(vm->def, i);
6401         vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
6402 
6403         if (STREQ_NULLABLE(alias, vcpupriv->alias)) {
6404             qemuDomainRemoveVcpu(driver, vm, i);
6405             return;
6406         }
6407     }
6408 }
6409 
6410 
6411 static int
qemuDomainHotplugDelVcpu(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * vm,unsigned int vcpu)6412 qemuDomainHotplugDelVcpu(virQEMUDriver *driver,
6413                          virQEMUDriverConfig *cfg,
6414                          virDomainObj *vm,
6415                          unsigned int vcpu)
6416 {
6417     virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
6418     qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
6419     int oldvcpus = virDomainDefGetVcpus(vm->def);
6420     unsigned int nvcpus = vcpupriv->vcpus;
6421     int rc;
6422     int ret = -1;
6423 
6424     if (!vcpupriv->alias) {
6425         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
6426                        _("vcpu '%u' can't be unplugged"), vcpu);
6427         return -1;
6428     }
6429 
6430     qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
6431 
6432     if (qemuDomainDeleteDevice(vm, vcpupriv->alias) < 0) {
6433         if (virDomainObjIsActive(vm))
6434             virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
6435         goto cleanup;
6436     }
6437 
6438     if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) {
6439         if (rc == 0)
6440             virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s",
6441                            _("vcpu unplug request timed out. Unplug result "
6442                              "must be manually inspected in the domain"));
6443 
6444         goto cleanup;
6445     }
6446 
6447     if (qemuDomainRemoveVcpu(driver, vm, vcpu) < 0)
6448         goto cleanup;
6449 
6450     qemuDomainVcpuPersistOrder(vm->def);
6451 
6452     if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
6453         goto cleanup;
6454 
6455     ret = 0;
6456 
6457  cleanup:
6458     qemuDomainResetDeviceRemoval(vm);
6459     return ret;
6460 }
6461 
6462 
6463 static int
qemuDomainHotplugAddVcpu(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * vm,unsigned int vcpu)6464 qemuDomainHotplugAddVcpu(virQEMUDriver *driver,
6465                          virQEMUDriverConfig *cfg,
6466                          virDomainObj *vm,
6467                          unsigned int vcpu)
6468 {
6469     g_autoptr(virJSONValue) vcpuprops = NULL;
6470     virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
6471     qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
6472     unsigned int nvcpus = vcpupriv->vcpus;
6473     int rc;
6474     int oldvcpus = virDomainDefGetVcpus(vm->def);
6475     size_t i;
6476 
6477     if (!qemuDomainSupportsNewVcpuHotplug(vm)) {
6478         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
6479                        _("cpu hotplug is not supported"));
6480         return -1;
6481     }
6482 
6483     vcpupriv->alias = g_strdup_printf("vcpu%u", vcpu);
6484 
6485     if (!(vcpuprops = qemuBuildHotpluggableCPUProps(vcpuinfo)))
6486         return -1;
6487 
6488     qemuDomainObjEnterMonitor(driver, vm);
6489 
6490     rc = qemuMonitorAddDeviceProps(qemuDomainGetMonitor(vm), &vcpuprops);
6491 
6492     if (qemuDomainObjExitMonitor(driver, vm) < 0)
6493         return -1;
6494 
6495     virDomainAuditVcpu(vm, oldvcpus, oldvcpus + nvcpus, "update", rc == 0);
6496 
6497     if (rc < 0)
6498         return -1;
6499 
6500     /* start outputting of the new XML element to allow keeping unpluggability */
6501     vm->def->individualvcpus = true;
6502 
6503     if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
6504         return -1;
6505 
6506     /* validation requires us to set the expected state prior to calling it */
6507     for (i = vcpu; i < vcpu + nvcpus; i++) {
6508         vcpuinfo = virDomainDefGetVcpu(vm->def, i);
6509         vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
6510 
6511         vcpuinfo->online = true;
6512 
6513         if (vcpupriv->tid > 0 &&
6514             qemuProcessSetupVcpu(vm, i) < 0)
6515             return -1;
6516     }
6517 
6518     if (qemuDomainValidateVcpuInfo(vm) < 0)
6519         return -1;
6520 
6521     qemuDomainVcpuPersistOrder(vm->def);
6522 
6523     if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
6524         return -1;
6525 
6526     return 0;
6527 }
6528 
6529 
6530 /**
6531  * qemuDomainSelectHotplugVcpuEntities:
6532  *
6533  * @def: domain definition
6534  * @nvcpus: target vcpu count
6535  * @enable: set to true if vcpus should be enabled
6536  *
6537  * Tries to find which vcpu entities need to be enabled or disabled to reach
6538  * @nvcpus. This function works in order of the legacy hotplug but is able to
6539  * skip over entries that are added out of order.
6540  *
6541  * Returns the bitmap of vcpus to modify on success, NULL on error.
6542  */
6543 static virBitmap *
qemuDomainSelectHotplugVcpuEntities(virDomainDef * def,unsigned int nvcpus,bool * enable)6544 qemuDomainSelectHotplugVcpuEntities(virDomainDef *def,
6545                                     unsigned int nvcpus,
6546                                     bool *enable)
6547 {
6548     virBitmap *ret = NULL;
6549     virDomainVcpuDef *vcpu;
6550     qemuDomainVcpuPrivate *vcpupriv;
6551     unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
6552     unsigned int curvcpus = virDomainDefGetVcpus(def);
6553     ssize_t i;
6554 
6555     ret = virBitmapNew(maxvcpus);
6556 
6557     if (nvcpus > curvcpus) {
6558         *enable = true;
6559 
6560         for (i = 0; i < maxvcpus && curvcpus < nvcpus; i++) {
6561             vcpu = virDomainDefGetVcpu(def, i);
6562             vcpupriv =  QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
6563 
6564             if (vcpu->online)
6565                 continue;
6566 
6567             if (vcpupriv->vcpus == 0)
6568                 continue;
6569 
6570             curvcpus += vcpupriv->vcpus;
6571 
6572             if (curvcpus > nvcpus) {
6573                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6574                                _("target vm vcpu granularity does not allow the "
6575                                  "desired vcpu count"));
6576                 goto error;
6577             }
6578 
6579             ignore_value(virBitmapSetBit(ret, i));
6580         }
6581     } else {
6582         *enable = false;
6583 
6584         for (i = maxvcpus - 1; i >= 0 && curvcpus > nvcpus; i--) {
6585             vcpu = virDomainDefGetVcpu(def, i);
6586             vcpupriv =  QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
6587 
6588             if (!vcpu->online)
6589                 continue;
6590 
6591             if (vcpupriv->vcpus == 0)
6592                 continue;
6593 
6594             if (!vcpupriv->alias)
6595                 continue;
6596 
6597             curvcpus -= vcpupriv->vcpus;
6598 
6599             if (curvcpus < nvcpus) {
6600                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6601                                _("target vm vcpu granularity does not allow the "
6602                                  "desired vcpu count"));
6603                 goto error;
6604             }
6605 
6606             ignore_value(virBitmapSetBit(ret, i));
6607         }
6608     }
6609 
6610     if (curvcpus != nvcpus) {
6611         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6612                        _("failed to find appropriate hotpluggable vcpus to "
6613                          "reach the desired target vcpu count"));
6614         goto error;
6615     }
6616 
6617     return ret;
6618 
6619  error:
6620     virBitmapFree(ret);
6621     return NULL;
6622 }
6623 
6624 
6625 static int
qemuDomainSetVcpusLive(virQEMUDriver * driver,virQEMUDriverConfig * cfg,virDomainObj * vm,virBitmap * vcpumap,bool enable)6626 qemuDomainSetVcpusLive(virQEMUDriver *driver,
6627                        virQEMUDriverConfig *cfg,
6628                        virDomainObj *vm,
6629                        virBitmap *vcpumap,
6630                        bool enable)
6631 {
6632     qemuDomainObjPrivate *priv = vm->privateData;
6633     qemuCgroupEmulatorAllNodesData *emulatorCgroup = NULL;
6634     ssize_t nextvcpu = -1;
6635     int ret = -1;
6636 
6637     if (qemuCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
6638         goto cleanup;
6639 
6640     if (enable) {
6641         while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
6642             if (qemuDomainHotplugAddVcpu(driver, cfg, vm, nextvcpu) < 0)
6643                 goto cleanup;
6644         }
6645     } else {
6646         for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0; nextvcpu--) {
6647             if (!virBitmapIsBitSet(vcpumap, nextvcpu))
6648                 continue;
6649 
6650             if (qemuDomainHotplugDelVcpu(driver, cfg, vm, nextvcpu) < 0)
6651                 goto cleanup;
6652         }
6653     }
6654 
6655     ret = 0;
6656 
6657  cleanup:
6658     qemuCgroupEmulatorAllNodesRestore(emulatorCgroup);
6659 
6660     return ret;
6661 }
6662 
6663 
6664 /**
6665  * qemuDomainSetVcpusConfig:
6666  * @def: config/offline definition of a domain
6667  * @nvcpus: target vcpu count
6668  *
6669  * Properly handle cold(un)plug of vcpus:
6670  * - plug in inactive vcpus/uplug active rather than rewriting state
6671  * - fix hotpluggable state
6672  */
6673 static void
qemuDomainSetVcpusConfig(virDomainDef * def,unsigned int nvcpus,bool hotpluggable)6674 qemuDomainSetVcpusConfig(virDomainDef *def,
6675                          unsigned int nvcpus,
6676                          bool hotpluggable)
6677 {
6678     virDomainVcpuDef *vcpu;
6679     size_t curvcpus = virDomainDefGetVcpus(def);
6680     size_t maxvcpus = virDomainDefGetVcpusMax(def);
6681     size_t i;
6682 
6683     /* ordering information may become invalid, thus clear it */
6684     virDomainDefVcpuOrderClear(def);
6685 
6686     if (curvcpus == nvcpus)
6687         return;
6688 
6689     if (curvcpus < nvcpus) {
6690         for (i = 0; i < maxvcpus; i++) {
6691             vcpu = virDomainDefGetVcpu(def, i);
6692 
6693             if (!vcpu)
6694                 continue;
6695 
6696             if (vcpu->online) {
6697                 /* non-hotpluggable vcpus need to be clustered at the beginning,
6698                  * thus we need to force vcpus to be hotpluggable when we find
6699                  * vcpus that are hotpluggable and online prior to the ones
6700                  * we are going to add */
6701                 if (vcpu->hotpluggable == VIR_TRISTATE_BOOL_YES)
6702                     hotpluggable = true;
6703 
6704                 continue;
6705             }
6706 
6707             vcpu->online = true;
6708             if (hotpluggable) {
6709                 vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
6710                 def->individualvcpus = true;
6711             } else {
6712                 vcpu->hotpluggable = VIR_TRISTATE_BOOL_NO;
6713             }
6714 
6715             if (++curvcpus == nvcpus)
6716                 break;
6717         }
6718     } else {
6719         for (i = maxvcpus; i != 0; i--) {
6720             vcpu = virDomainDefGetVcpu(def, i - 1);
6721 
6722             if (!vcpu || !vcpu->online)
6723                 continue;
6724 
6725             vcpu->online = false;
6726             vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
6727 
6728             if (--curvcpus == nvcpus)
6729                 break;
6730         }
6731     }
6732 }
6733 
6734 
6735 int
qemuDomainSetVcpusInternal(virQEMUDriver * driver,virDomainObj * vm,virDomainDef * def,virDomainDef * persistentDef,unsigned int nvcpus,bool hotpluggable)6736 qemuDomainSetVcpusInternal(virQEMUDriver *driver,
6737                            virDomainObj *vm,
6738                            virDomainDef *def,
6739                            virDomainDef *persistentDef,
6740                            unsigned int nvcpus,
6741                            bool hotpluggable)
6742 {
6743     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
6744     virBitmap *vcpumap = NULL;
6745     bool enable;
6746     int ret = -1;
6747 
6748     if (def && nvcpus > virDomainDefGetVcpusMax(def)) {
6749         virReportError(VIR_ERR_INVALID_ARG,
6750                        _("requested vcpus is greater than max allowable"
6751                          " vcpus for the live domain: %u > %u"),
6752                        nvcpus, virDomainDefGetVcpusMax(def));
6753         goto cleanup;
6754     }
6755 
6756     if (persistentDef && nvcpus > virDomainDefGetVcpusMax(persistentDef)) {
6757         virReportError(VIR_ERR_INVALID_ARG,
6758                        _("requested vcpus is greater than max allowable"
6759                          " vcpus for the persistent domain: %u > %u"),
6760                        nvcpus, virDomainDefGetVcpusMax(persistentDef));
6761         goto cleanup;
6762     }
6763 
6764     if (def) {
6765         if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus,
6766                                                             &enable)))
6767             goto cleanup;
6768 
6769         if (qemuDomainSetVcpusLive(driver, cfg, vm, vcpumap, enable) < 0)
6770             goto cleanup;
6771     }
6772 
6773     if (persistentDef) {
6774         qemuDomainSetVcpusConfig(persistentDef, nvcpus, hotpluggable);
6775 
6776         if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
6777             goto cleanup;
6778     }
6779 
6780     ret = 0;
6781 
6782  cleanup:
6783     virBitmapFree(vcpumap);
6784     return ret;
6785 }
6786 
6787 
6788 static void
qemuDomainSetVcpuConfig(virDomainDef * def,virBitmap * map,bool state)6789 qemuDomainSetVcpuConfig(virDomainDef *def,
6790                         virBitmap *map,
6791                         bool state)
6792 {
6793     virDomainVcpuDef *vcpu;
6794     ssize_t next = -1;
6795 
6796     def->individualvcpus = true;
6797 
6798     /* ordering information may become invalid, thus clear it */
6799     virDomainDefVcpuOrderClear(def);
6800 
6801     while ((next = virBitmapNextSetBit(map, next)) >= 0) {
6802         if (!(vcpu = virDomainDefGetVcpu(def, next)))
6803             continue;
6804 
6805         vcpu->online = state;
6806         vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
6807     }
6808 }
6809 
6810 
6811 /**
6812  * qemuDomainFilterHotplugVcpuEntities:
6813  *
6814  * Returns a bitmap of hotpluggable vcpu entities that correspond to the logical
6815  * vcpus requested in @vcpus.
6816  */
6817 static virBitmap *
qemuDomainFilterHotplugVcpuEntities(virDomainDef * def,virBitmap * vcpus,bool state)6818 qemuDomainFilterHotplugVcpuEntities(virDomainDef *def,
6819                                     virBitmap *vcpus,
6820                                     bool state)
6821 {
6822     qemuDomainVcpuPrivate *vcpupriv;
6823     virDomainVcpuDef *vcpu;
6824     g_autoptr(virBitmap) map = virBitmapNewCopy(vcpus);
6825     ssize_t next = -1;
6826     size_t i;
6827 
6828     /* make sure that all selected vcpus are in the correct state */
6829     while ((next = virBitmapNextSetBit(map, next)) >= 0) {
6830         if (!(vcpu = virDomainDefGetVcpu(def, next)))
6831             continue;
6832 
6833         if (vcpu->online == state) {
6834             virReportError(VIR_ERR_INVALID_ARG,
6835                            _("vcpu '%zd' is already in requested state"), next);
6836             return NULL;
6837         }
6838 
6839         if (vcpu->online && !vcpu->hotpluggable) {
6840             virReportError(VIR_ERR_INVALID_ARG,
6841                            _("vcpu '%zd' can't be hotunplugged"), next);
6842             return NULL;
6843         }
6844     }
6845 
6846     /* Make sure that all vCPUs belonging to a single hotpluggable entity were
6847      * selected and then de-select any sub-threads of it. */
6848     next = -1;
6849     while ((next = virBitmapNextSetBit(map, next)) >= 0) {
6850         if (!(vcpu = virDomainDefGetVcpu(def, next)))
6851             continue;
6852 
6853         vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
6854 
6855         if (vcpupriv->vcpus == 0) {
6856             virReportError(VIR_ERR_INVALID_ARG,
6857                            _("vcpu '%zd' belongs to a larger hotpluggable entity, "
6858                              "but siblings were not selected"), next);
6859             return NULL;
6860         }
6861 
6862         for (i = next + 1; i < next + vcpupriv->vcpus; i++) {
6863             if (!virBitmapIsBitSet(map, i)) {
6864                 virReportError(VIR_ERR_INVALID_ARG,
6865                                _("vcpu '%zu' was not selected but it belongs to "
6866                                  "hotpluggable entity '%zd-%zd' which was "
6867                                  "partially selected"),
6868                                i, next, next + vcpupriv->vcpus - 1);
6869                 return NULL;
6870             }
6871 
6872             /* clear the subthreads */
6873             ignore_value(virBitmapClearBit(map, i));
6874         }
6875     }
6876 
6877     return g_steal_pointer(&map);
6878 }
6879 
6880 
6881 static int
qemuDomainVcpuValidateConfig(virDomainDef * def,virBitmap * map)6882 qemuDomainVcpuValidateConfig(virDomainDef *def,
6883                              virBitmap *map)
6884 {
6885     virDomainVcpuDef *vcpu;
6886     size_t maxvcpus = virDomainDefGetVcpusMax(def);
6887     ssize_t next;
6888     ssize_t firstvcpu = -1;
6889 
6890     /* vcpu 0 can't be modified */
6891     if (virBitmapIsBitSet(map, 0)) {
6892         virReportError(VIR_ERR_INVALID_ARG, "%s",
6893                        _("vCPU '0' can't be modified"));
6894         return -1;
6895     }
6896 
6897     firstvcpu = virBitmapNextSetBit(map, -1);
6898 
6899     /* non-hotpluggable vcpus need to stay clustered starting from vcpu 0 */
6900     for (next = firstvcpu + 1; next < maxvcpus; next++) {
6901         if (!(vcpu = virDomainDefGetVcpu(def, next)))
6902             continue;
6903 
6904         /* skip vcpus being modified */
6905         if (virBitmapIsBitSet(map, next))
6906             continue;
6907 
6908         if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_NO) {
6909             virReportError(VIR_ERR_INVALID_ARG,
6910                            _("vcpu '%zd' can't be modified as it is followed "
6911                              "by non-hotpluggable online vcpus"), firstvcpu);
6912             return -1;
6913         }
6914     }
6915 
6916     return 0;
6917 }
6918 
6919 
6920 int
qemuDomainSetVcpuInternal(virQEMUDriver * driver,virDomainObj * vm,virDomainDef * def,virDomainDef * persistentDef,virBitmap * map,bool state)6921 qemuDomainSetVcpuInternal(virQEMUDriver *driver,
6922                           virDomainObj *vm,
6923                           virDomainDef *def,
6924                           virDomainDef *persistentDef,
6925                           virBitmap *map,
6926                           bool state)
6927 {
6928     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
6929     virBitmap *livevcpus = NULL;
6930     int ret = -1;
6931 
6932     if (def) {
6933         if (!qemuDomainSupportsNewVcpuHotplug(vm)) {
6934             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
6935                            _("this qemu version does not support specific "
6936                              "vCPU hotplug"));
6937             goto cleanup;
6938         }
6939 
6940         if (!(livevcpus = qemuDomainFilterHotplugVcpuEntities(def, map, state)))
6941             goto cleanup;
6942 
6943         /* Make sure that only one hotpluggable entity is selected.
6944          * qemuDomainSetVcpusLive allows setting more at once but error
6945          * resolution in case of a partial failure is hard, so don't let users
6946          * do so */
6947         if (virBitmapCountBits(livevcpus) != 1) {
6948             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
6949                            _("only one hotpluggable entity can be selected"));
6950             goto cleanup;
6951         }
6952     }
6953 
6954     if (persistentDef) {
6955         if (qemuDomainVcpuValidateConfig(persistentDef, map) < 0)
6956             goto cleanup;
6957     }
6958 
6959     if (livevcpus &&
6960         qemuDomainSetVcpusLive(driver, cfg, vm, livevcpus, state) < 0)
6961         goto cleanup;
6962 
6963     if (persistentDef) {
6964         qemuDomainSetVcpuConfig(persistentDef, map, state);
6965 
6966         if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
6967             goto cleanup;
6968     }
6969 
6970     ret = 0;
6971 
6972  cleanup:
6973     virBitmapFree(livevcpus);
6974     return ret;
6975 }
6976 
6977 
6978 int
qemuDomainChangeMemoryRequestedSize(virQEMUDriver * driver,virDomainObj * vm,const char * alias,unsigned long long requestedsize)6979 qemuDomainChangeMemoryRequestedSize(virQEMUDriver *driver,
6980                                     virDomainObj *vm,
6981                                     const char *alias,
6982                                     unsigned long long requestedsize)
6983 {
6984     qemuDomainObjPrivate *priv = vm->privateData;
6985     int rc;
6986 
6987     qemuDomainObjEnterMonitor(driver, vm);
6988     rc = qemuMonitorChangeMemoryRequestedSize(priv->mon, alias, requestedsize);
6989     if (qemuDomainObjExitMonitor(driver, vm) < 0)
6990         return -1;
6991 
6992     return rc;
6993 }
6994