libvirt/src/qemu/qemu_domain.h

1060 lines
36 KiB
C
Raw Normal View History

/*
* qemu_domain.h: QEMU domain private state
*
* Copyright (C) 2006-2019 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib-object.h>
#include "virthread.h"
#include "vircgroup.h"
#include "virperf.h"
#include "domain_addr.h"
#include "domain_conf.h"
#include "snapshot_conf.h"
#include "qemu_monitor.h"
#include "qemu_agent.h"
#include "qemu_blockjob.h"
#include "qemu_domainjob.h"
#include "qemu_conf.h"
#include "qemu_capabilities.h"
#include "qemu_migration_params.h"
#include "qemu_slirp.h"
#include "virmdev.h"
#include "virchrdev.h"
#include "virobject.h"
#include "logging/log_manager.h"
#include "virdomainmomentobjlist.h"
#include "virenum.h"
#include "vireventthread.h"
#define QEMU_DOMAIN_FORMAT_LIVE_FLAGS \
(VIR_DOMAIN_XML_SECURE)
#if ULONG_MAX == 4294967295
/* QEMU has a 64-bit limit, but we are limited by our historical choice of
* representing bandwidth in a long instead of a 64-bit int. */
# define QEMU_DOMAIN_MIG_BANDWIDTH_MAX ULONG_MAX
#else
# define QEMU_DOMAIN_MIG_BANDWIDTH_MAX (INT64_MAX / (1024 * 1024))
#endif
typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver,
virDomainObjPtr vm);
#define QEMU_DOMAIN_MASTER_KEY_LEN 32 /* 32 bytes for 256 bit random key */
void
qemuDomainObjSaveStatus(virQEMUDriverPtr driver,
virDomainObjPtr obj);
void qemuDomainSaveStatus(virDomainObjPtr obj);
void qemuDomainSaveConfig(virDomainObjPtr obj);
/* helper data types for async device unplug */
typedef enum {
QEMU_DOMAIN_UNPLUGGING_DEVICE_STATUS_NONE = 0,
QEMU_DOMAIN_UNPLUGGING_DEVICE_STATUS_OK,
QEMU_DOMAIN_UNPLUGGING_DEVICE_STATUS_GUEST_REJECTED,
} qemuDomainUnpluggingDeviceStatus;
typedef struct _qemuDomainUnpluggingDevice qemuDomainUnpluggingDevice;
typedef qemuDomainUnpluggingDevice *qemuDomainUnpluggingDevicePtr;
struct _qemuDomainUnpluggingDevice {
const char *alias;
qemuDomainUnpluggingDeviceStatus status;
qemu_hotplug: Fix a rare race condition when detaching a device twice https://bugzilla.redhat.com/show_bug.cgi?id=1623389 If a device is detached twice from the same domain the following race condition may happen: 1) The first DetachDevice() call will issue "device_del" on qemu monitor, but since the DEVICE_DELETED event did not arrive in time, the API ends claiming "Device detach request sent successfully". 2) The second DetachDevice() therefore still find the device in the domain and thus proceeds to detaching it again. It calls EnterMonitor() and qemuMonitorSend() trying to issue "device_del" command again. This gets both domain lock and monitor lock released. 3) At this point, qemu sends us the DEVICE_DELETED event which is going to be handled by the event loop which ends up calling qemuDomainSignalDeviceRemoval() to determine who is going to remove the device from domain definition. Whether it is the caller that marked the device for removal or whether it is going to be the event processing thread. 4) Because the device was marked for removal, qemuDomainSignalDeviceRemoval() returns true, which means the event is to be processed by the thread that has marked the device for removal (and is currently still trying to issue "device_del" command) 5) The thread finally issues the "device_del" command, which fails (obviously) and therefore it calls qemuDomainResetDeviceRemoval() to reset the device marking and quits immediately after, NOT removing any device from the domain definition. At this point, the device is still present in the domain definition but doesn't exist in qemu anymore. Worse, there is no way to remove it from the domain definition. Solution is to note down that we've seen the event and if the second "device_del" fails, not take it as a failure but carry on with the usual execution. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-14 10:02:52 +00:00
bool eventSeen; /* True if DEVICE_DELETED event arrived. */
};
qemu: Spawn qemu under mount namespace Prime time. When it comes to spawning qemu process and relabelling all the devices it's going to touch, there's inherent race with other applications in the system (e.g. udev). Instead of trying convincing udev to not touch libvirt managed devices, we can create a separate mount namespace for the qemu, and mount our own /dev there. Of course this puts more work onto us as we have to maintain /dev files on each domain start and device hot(un-)plug. On the other hand, this enhances security also. From technical POV, on domain startup process the parent (libvirtd) creates: /var/lib/libvirt/qemu/$domain.dev /var/lib/libvirt/qemu/$domain.devpts The child (which is going to be qemu eventually) calls unshare() to create new mount namespace. From now on anything that child does is invisible to the parent. Child then mounts tmpfs on $domain.dev (so that it still sees original /dev from the host) and creates some devices (as explained in one of the previous patches). The devices have to be created exactly as they are in the host (including perms, seclabels, ACLs, ...). After that it moves $domain.dev mount to /dev. What's the $domain.devpts mount there for then you ask? QEMU can create PTYs for some chardevs. And historically we exposed the host ends in our domain XML allowing users to connect to them. Therefore we must preserve devpts mount to be shared with the host's one. To make this patch as small as possible, creating of devices configured for domain in question is implemented in next patches. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2016-11-15 10:30:18 +00:00
#define QEMU_PROC_MOUNTS "/proc/mounts"
#define QEMU_DEVPREFIX "/dev/"
#define QEMU_DEV_VFIO "/dev/vfio/vfio"
#define QEMU_DEV_SEV "/dev/sev"
#define QEMU_DEVICE_MAPPER_CONTROL_PATH "/dev/mapper/control"
/* Type of domain secret */
typedef enum {
VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN = 0,
VIR_DOMAIN_SECRET_INFO_TYPE_AES, /* utilize GNUTLS_CIPHER_AES_256_CBC */
VIR_DOMAIN_SECRET_INFO_TYPE_LAST
} qemuDomainSecretInfoType;
typedef struct _qemuDomainSecretPlain qemuDomainSecretPlain;
typedef struct _qemuDomainSecretPlain *qemuDomainSecretPlainPtr;
struct _qemuDomainSecretPlain {
char *username;
uint8_t *secret;
size_t secretlen;
};
#define QEMU_DOMAIN_AES_IV_LEN 16 /* 16 bytes for 128 bit random */
/* initialization vector */
typedef struct _qemuDomainSecretAES qemuDomainSecretAES;
typedef struct _qemuDomainSecretAES *qemuDomainSecretAESPtr;
struct _qemuDomainSecretAES {
char *username;
char *alias; /* generated alias for secret */
char *iv; /* base64 encoded initialization vector */
char *ciphertext; /* encoded/encrypted secret */
};
typedef struct _qemuDomainSecretInfo qemuDomainSecretInfo;
typedef qemuDomainSecretInfo *qemuDomainSecretInfoPtr;
struct _qemuDomainSecretInfo {
qemuDomainSecretInfoType type;
union {
qemuDomainSecretPlain plain;
qemuDomainSecretAES aes;
} s;
};
typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
struct _qemuDomainObjPrivate {
virQEMUDriverPtr driver;
qemuDomainJobObj job;
qemu: Spawn qemu under mount namespace Prime time. When it comes to spawning qemu process and relabelling all the devices it's going to touch, there's inherent race with other applications in the system (e.g. udev). Instead of trying convincing udev to not touch libvirt managed devices, we can create a separate mount namespace for the qemu, and mount our own /dev there. Of course this puts more work onto us as we have to maintain /dev files on each domain start and device hot(un-)plug. On the other hand, this enhances security also. From technical POV, on domain startup process the parent (libvirtd) creates: /var/lib/libvirt/qemu/$domain.dev /var/lib/libvirt/qemu/$domain.devpts The child (which is going to be qemu eventually) calls unshare() to create new mount namespace. From now on anything that child does is invisible to the parent. Child then mounts tmpfs on $domain.dev (so that it still sees original /dev from the host) and creates some devices (as explained in one of the previous patches). The devices have to be created exactly as they are in the host (including perms, seclabels, ACLs, ...). After that it moves $domain.dev mount to /dev. What's the $domain.devpts mount there for then you ask? QEMU can create PTYs for some chardevs. And historically we exposed the host ends in our domain XML allowing users to connect to them. Therefore we must preserve devpts mount to be shared with the host's one. To make this patch as small as possible, creating of devices configured for domain in question is implemented in next patches. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2016-11-15 10:30:18 +00:00
virBitmapPtr namespaces;
virEventThread *eventThread;
qemuMonitorPtr mon;
virDomainChrSourceDefPtr monConfig;
bool monError;
unsigned long long monStart;
int agentTimeout;
qemuAgentPtr agent;
bool agentError;
bool beingDestroyed;
char *pidfile;
virDomainPCIAddressSetPtr pciaddrs;
virDomainUSBAddressSetPtr usbaddrs;
virQEMUCapsPtr qemuCaps;
char *lockState;
bool fakeReboot;
bool pausedShutdown;
virTristateBool allowReboot;
int jobs_queued;
unsigned long migMaxBandwidth;
char *origname;
int nbdPort; /* Port used for migration with NBD */
unsigned short migrationPort;
int preMigrationState;
virChrdevsPtr devs;
qemuDomainCleanupCallback *cleanupCallbacks;
size_t ncleanupCallbacks;
size_t ncleanupCallbacks_max;
virCgroupPtr cgroup;
virPerfPtr perf;
qemuDomainUnpluggingDevice unplug;
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
bool hookRun; /* true if there was a hook run over this domain */
/* Bitmaps below hold data from the auto NUMA feature */
virBitmapPtr autoNodeset;
virBitmapPtr autoCpuset;
bool signalIOError; /* true if the domain condition should be signalled on
I/O error */
bool signalStop; /* true if the domain condition should be signalled on
QMP STOP event */
systemd: Modernize machine naming So, systemd-machined has this philosophy that machine names are like hostnames and hence should follow the same rules. But we always allowed international characters in domain names. Thus we need to modify the machine name we are passing to systemd. In order to change some machine names that we will be passing to systemd, we also need to call TerminateMachine at the end of a lifetime of a domain. Even for domains that were started with older libvirt. That can be achieved thanks to virSystemdGetMachineNameByPID(). And because we can change machine names, we can get rid of the inconsistent and pointless escaping of domain names when creating machine names. So this patch modifies the naming in the following way. It creates the name as <drivername>-<id>-<name> where invalid hostname characters are stripped out of the name and if the resulting name is longer, it truncates it to 64 characters. That way we can start domains we couldn't start before. Well, at least on systemd. To make it work all together, the machineName (which is needed only with systemd) is saved in domain's private data. That way the generation is moved to the driver and we don't need to pass various unnecessary arguments to cgroup functions. The only thing this complicates a bit is the scope generation when validating a cgroup where we must check both old and new naming, so a slight modification was needed there. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1282846 Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2016-02-01 15:50:54 +00:00
char *machineName;
char *libDir; /* base path for per-domain files */
char *channelTargetDir; /* base path for per-domain channel targets */
qemu: Create domain master key Add a masterKey and masterKeyLen to _qemuDomainObjPrivate to store a random domain master key and its length in order to support the ability to encrypt/decrypt sensitive data shared between libvirt and qemu. The key will be base64 encoded and written to a file to be used by the command line building code to share with qemu. New API's from this patch: qemuDomainGetMasterKeyFilePath: Return a path to where the key is located qemuDomainWriteMasterKeyFile: (private) Open (create/trunc) the masterKey path and write the masterKey qemuDomainMasterKeyReadFile: Using the master key path, open/read the file, and store the masterKey and masterKeyLen. Expected use only from qemuProcessReconnect qemuDomainGenerateRandomKey: (private) Generate a random key using available algorithms The key is generated either from the gnutls_rnd function if it exists or a less cryptographically strong mechanism using virGenerateRandomBytes qemuDomainMasterKeyRemove: Remove traces of the master key, remove the *KeyFilePath qemuDomainMasterKeyCreate: Generate the domain master key and save the key in the location returned by qemuDomainGetMasterKeyFilePath. This API will first ensure the QEMU_CAPS_OBJECT_SECRET is set in the capabilities. If not, then there's no need to generate the secret or file. The creation of the key will be attempted from qemuProcessPrepareHost once the libDir directory structure exists. The removal of the key will handled from qemuProcessStop just prior to deleting the libDir tree. Since the key will not be written out to the domain object XML file, the qemuProcessReconnect will read the saved file and restore the masterKey and masterKeyLen.
2016-03-29 22:22:46 +00:00
/* random masterKey and length for encryption (not to be saved in our */
/* private XML) - need to restore at process reconnect */
uint8_t *masterKey;
size_t masterKeyLen;
/* note whether memory device alias does not correspond to slot number */
bool memAliasOrderMismatch;
/* for migrations using TLS with a secret (not to be saved in our */
/* private XML). */
qemuDomainSecretInfoPtr migSecinfo;
/* CPU def used to start the domain when it differs from the one actually
* provided by QEMU. */
virCPUDefPtr origCPU;
/* If true virtlogd is used as stdio handler for character devices. */
bool chardevStdioLogd;
/* Tracks blockjob state for vm. Valid only while reconnecting to qemu. */
virTristateBool reconnectBlockjobs;
/* Migration capabilities. Rechecked on reconnect, not to be saved in
* private XML. */
virBitmapPtr migrationCaps;
/* true if qemu-pr-helper process is running for the domain */
bool prDaemonRunning;
/* counter for generating node names for qemu disks */
unsigned long long nodenameindex;
/* qemuProcessStartCPUs stores the reason for starting vCPUs here for the
* RESUME event handler to use it */
virDomainRunningReason runningReason;
/* qemuProcessStopCPUs stores the reason for pausing vCPUs here for the
* STOP event handler to use it */
virDomainPausedReason pausedReason;
/* true if libvirt remembers the original owner for files */
bool rememberOwner;
/* true if global -mem-prealloc appears on cmd line */
bool memPrealloc;
/* running block jobs */
GHashTable *blockjobs;
bool disableSlirp;
/* Until we add full support for backing chains for pflash drives, these
* pointers hold the temporary virStorageSources for creating the -blockdev
* commandline for pflash drives. */
virStorageSourcePtr pflash0;
virStorageSourcePtr pflash1;
/* running backup job */
virDomainBackupDefPtr backup;
bool dbusDaemonRunning;
/* list of Ids to migrate */
char **dbusVMStateIds;
/* true if -object dbus-vmstate was added */
bool dbusVMState;
/* prevent deletion of <transient> disk overlay files between startup and
* succesful setup of the overlays */
bool inhibitDiskTransientDelete;
};
#define QEMU_DOMAIN_PRIVATE(vm) \
((qemuDomainObjPrivatePtr) (vm)->privateData)
#define QEMU_DOMAIN_DISK_PRIVATE(disk) \
((qemuDomainDiskPrivatePtr) (disk)->privateData)
typedef struct _qemuDomainDiskPrivate qemuDomainDiskPrivate;
typedef qemuDomainDiskPrivate *qemuDomainDiskPrivatePtr;
struct _qemuDomainDiskPrivate {
virObject parent;
/* ideally we want a smarter way to interlock block jobs on single qemu disk
* in the future, but for now we just disallow any concurrent job on a
* single disk */
qemuBlockJobDataPtr blockjob;
bool migrating; /* the disk is being migrated */
virStorageSourcePtr migrSource; /* disk source object used for NBD migration */
/* information about the device */
bool tray; /* device has tray */
bool removable; /* device media can be removed/changed */
char *qomName; /* QOM path of the disk (also refers to the block backend) */
char *nodeCopyOnRead; /* nodename of the disk-wide copy-on-read blockdev layer */
};
#define QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src) \
((qemuDomainStorageSourcePrivatePtr) (src)->privateData)
typedef struct _qemuDomainStorageSourcePrivate qemuDomainStorageSourcePrivate;
typedef qemuDomainStorageSourcePrivate *qemuDomainStorageSourcePrivatePtr;
struct _qemuDomainStorageSourcePrivate {
virObject parent;
/* data required for authentication to the storage source */
qemuDomainSecretInfoPtr secinfo;
/* data required for decryption of encrypted storage source */
qemuDomainSecretInfoPtr encinfo;
/* secure passthrough of the http cookie */
qemuDomainSecretInfoPtr httpcookie;
/* key for decrypting TLS certificate */
qemuDomainSecretInfoPtr tlsKeySecret;
};
virObjectPtr qemuDomainStorageSourcePrivateNew(void);
qemuDomainStorageSourcePrivatePtr
qemuDomainStorageSourcePrivateFetch(virStorageSourcePtr src);
typedef struct _qemuDomainVcpuPrivate qemuDomainVcpuPrivate;
typedef qemuDomainVcpuPrivate *qemuDomainVcpuPrivatePtr;
struct _qemuDomainVcpuPrivate {
virObject parent;
pid_t tid; /* vcpu thread id */
int enable_id; /* order in which the vcpus were enabled in qemu */
int qemu_id; /* ID reported by qemu as 'CPU' in query-cpus */
char *alias;
virTristateBool halted;
/* copy of the data that qemu returned */
virJSONValuePtr props;
/* information for hotpluggable cpus */
char *type;
int socket_id;
int core_id;
int thread_id;
int node_id;
int vcpus;
};
#define QEMU_DOMAIN_VCPU_PRIVATE(vcpu) \
((qemuDomainVcpuPrivatePtr) (vcpu)->privateData)
struct qemuDomainDiskInfo {
bool removable;
bool tray;
bool tray_open;
bool empty;
int io_status;
char *nodename;
};
#define QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev) \
((qemuDomainChrSourcePrivatePtr) (dev)->privateData)
typedef struct _qemuDomainChrSourcePrivate qemuDomainChrSourcePrivate;
typedef qemuDomainChrSourcePrivate *qemuDomainChrSourcePrivatePtr;
struct _qemuDomainChrSourcePrivate {
virObject parent;
/* for char devices using secret
* NB: *not* to be written to qemu domain object XML */
qemuDomainSecretInfoPtr secinfo;
};
typedef struct _qemuDomainVsockPrivate qemuDomainVsockPrivate;
typedef qemuDomainVsockPrivate *qemuDomainVsockPrivatePtr;
struct _qemuDomainVsockPrivate {
virObject parent;
int vhostfd;
};
#define QEMU_DOMAIN_VIDEO_PRIVATE(dev) \
((qemuDomainVideoPrivatePtr) (dev)->privateData)
typedef struct _qemuDomainVideoPrivate qemuDomainVideoPrivate;
typedef qemuDomainVideoPrivate *qemuDomainVideoPrivatePtr;
struct _qemuDomainVideoPrivate {
virObject parent;
int vhost_user_fd;
};
#define QEMU_DOMAIN_GRAPHICS_PRIVATE(dev) \
((qemuDomainGraphicsPrivatePtr) (dev)->privateData)
typedef struct _qemuDomainGraphicsPrivate qemuDomainGraphicsPrivate;
typedef qemuDomainGraphicsPrivate *qemuDomainGraphicsPrivatePtr;
struct _qemuDomainGraphicsPrivate {
virObject parent;
char *tlsAlias;
qemuDomainSecretInfoPtr secinfo;
};
#define QEMU_DOMAIN_NETWORK_PRIVATE(dev) \
((qemuDomainNetworkPrivatePtr) (dev)->privateData)
typedef struct _qemuDomainNetworkPrivate qemuDomainNetworkPrivate;
typedef qemuDomainNetworkPrivate *qemuDomainNetworkPrivatePtr;
struct _qemuDomainNetworkPrivate {
virObject parent;
qemuSlirpPtr slirp;
};
#define QEMU_DOMAIN_FS_PRIVATE(dev) \
((qemuDomainFSPrivatePtr) (dev)->privateData)
typedef struct _qemuDomainFSPrivate qemuDomainFSPrivate;
typedef qemuDomainFSPrivate *qemuDomainFSPrivatePtr;
struct _qemuDomainFSPrivate {
virObject parent;
char *vhostuser_fs_sock;
};
typedef enum {
QEMU_PROCESS_EVENT_WATCHDOG = 0,
QEMU_PROCESS_EVENT_GUESTPANIC,
QEMU_PROCESS_EVENT_DEVICE_DELETED,
QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
QEMU_PROCESS_EVENT_SERIAL_CHANGED,
QEMU_PROCESS_EVENT_BLOCK_JOB,
QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE,
QEMU_PROCESS_EVENT_MONITOR_EOF,
QEMU_PROCESS_EVENT_PR_DISCONNECT,
QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
QEMU_PROCESS_EVENT_GUEST_CRASHLOADED,
QEMU_PROCESS_EVENT_LAST
} qemuProcessEventType;
struct qemuProcessEvent {
virDomainObjPtr vm;
qemuProcessEventType eventType;
int action;
int status;
void *data;
};
void qemuProcessEventFree(struct qemuProcessEvent *event);
#define QEMU_TYPE_DOMAIN_LOG_CONTEXT qemu_domain_log_context_get_type()
G_DECLARE_FINAL_TYPE(qemuDomainLogContext, qemu_domain_log_context, QEMU, DOMAIN_LOG_CONTEXT, GObject);
typedef qemuDomainLogContext *qemuDomainLogContextPtr;
typedef struct _qemuDomainSaveCookie qemuDomainSaveCookie;
typedef qemuDomainSaveCookie *qemuDomainSaveCookiePtr;
struct _qemuDomainSaveCookie {
virObject parent;
virCPUDefPtr cpu;
bool slirpHelper;
};
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuDomainSaveCookie, virObjectUnref);
typedef struct _qemuDomainXmlNsDef qemuDomainXmlNsDef;
typedef qemuDomainXmlNsDef *qemuDomainXmlNsDefPtr;
struct _qemuDomainXmlNsDef {
size_t num_args;
char **args;
unsigned int num_env;
char **env_name;
char **env_value;
size_t ncapsadd;
char **capsadd;
size_t ncapsdel;
char **capsdel;
};
typedef struct _qemuDomainJobPrivate qemuDomainJobPrivate;
typedef qemuDomainJobPrivate *qemuDomainJobPrivatePtr;
struct _qemuDomainJobPrivate {
bool spiceMigration; /* we asked for spice migration and we
* should wait for it to finish */
bool spiceMigrated; /* spice migration completed */
bool dumpCompleted; /* dump completed */
qemuMigrationParamsPtr migParams;
};
int qemuDomainObjStartWorker(virDomainObjPtr dom);
void qemuDomainObjStopWorker(virDomainObjPtr dom);
virDomainObjPtr qemuDomainObjFromDomain(virDomainPtr domain);
qemuDomainSaveCookiePtr qemuDomainSaveCookieNew(virDomainObjPtr vm);
void qemuDomainEventFlush(int timer, void *opaque);
qemuMonitorPtr qemuDomainGetMonitor(virDomainObjPtr vm)
ATTRIBUTE_NONNULL(1);
void qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
qemu: fix crash when mixing sync and async monitor jobs Currently, we attempt to run sync job and async job at the same time. It means that the monitor commands for two jobs can be run in any order. In the function qemuDomainObjEnterMonitorInternal(): if (priv->job.active == QEMU_JOB_NONE && priv->job.asyncJob) { if (qemuDomainObjBeginNestedJob(driver, obj) < 0) We check whether the caller is an async job by priv->job.active and priv->job.asynJob. But when an async job is running, and a sync job is also running at the time of the check, then priv->job.active is not QEMU_JOB_NONE. So we cannot check whether the caller is an async job in the function qemuDomainObjEnterMonitorInternal(), and must instead put the burden on the caller to tell us when an async command wants to do a nested job. Once the burden is on the caller, then only async monitor enters need to worry about whether the VM is still running; for sync monitor enter, the internal return is always 0, so lots of ignore_value can be dropped. * src/qemu/THREADS.txt: Reflect new rules. * src/qemu/qemu_domain.h (qemuDomainObjEnterMonitorAsync): New prototype. * src/qemu/qemu_process.h (qemuProcessStartCPUs) (qemuProcessStopCPUs): Add parameter. * src/qemu/qemu_migration.h (qemuMigrationToFile): Likewise. (qemuMigrationWaitForCompletion): Make static. * src/qemu/qemu_domain.c (qemuDomainObjEnterMonitorInternal): Add parameter. (qemuDomainObjEnterMonitorAsync): New function. (qemuDomainObjEnterMonitor, qemuDomainObjEnterMonitorWithDriver): Update callers. * src/qemu/qemu_driver.c (qemuDomainSaveInternal) (qemudDomainCoreDump, doCoreDump, processWatchdogEvent) (qemudDomainSuspend, qemudDomainResume, qemuDomainSaveImageStartVM) (qemuDomainSnapshotCreateActive, qemuDomainRevertToSnapshot): Likewise. * src/qemu/qemu_process.c (qemuProcessStopCPUs) (qemuProcessFakeReboot, qemuProcessRecoverMigration) (qemuProcessRecoverJob, qemuProcessStart): Likewise. * src/qemu/qemu_migration.c (qemuMigrationToFile) (qemuMigrationWaitForCompletion, qemuMigrationUpdateJobStatus) (qemuMigrationJobStart, qemuDomainMigrateGraphicsRelocate) (doNativeMigrate, doTunnelMigrate, qemuMigrationPerformJob) (qemuMigrationPerformPhase, qemuMigrationFinish) (qemuMigrationConfirm): Likewise. * src/qemu/qemu_hotplug.c: Drop unneeded ignore_value.
2011-07-28 23:18:24 +00:00
virDomainObjPtr obj)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuDomainObjExitMonitor(virQEMUDriverPtr driver,
virDomainObjPtr obj)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
G_GNUC_WARN_UNUSED_RESULT;
int qemuDomainObjEnterMonitorAsync(virQEMUDriverPtr driver,
qemu: fix crash when mixing sync and async monitor jobs Currently, we attempt to run sync job and async job at the same time. It means that the monitor commands for two jobs can be run in any order. In the function qemuDomainObjEnterMonitorInternal(): if (priv->job.active == QEMU_JOB_NONE && priv->job.asyncJob) { if (qemuDomainObjBeginNestedJob(driver, obj) < 0) We check whether the caller is an async job by priv->job.active and priv->job.asynJob. But when an async job is running, and a sync job is also running at the time of the check, then priv->job.active is not QEMU_JOB_NONE. So we cannot check whether the caller is an async job in the function qemuDomainObjEnterMonitorInternal(), and must instead put the burden on the caller to tell us when an async command wants to do a nested job. Once the burden is on the caller, then only async monitor enters need to worry about whether the VM is still running; for sync monitor enter, the internal return is always 0, so lots of ignore_value can be dropped. * src/qemu/THREADS.txt: Reflect new rules. * src/qemu/qemu_domain.h (qemuDomainObjEnterMonitorAsync): New prototype. * src/qemu/qemu_process.h (qemuProcessStartCPUs) (qemuProcessStopCPUs): Add parameter. * src/qemu/qemu_migration.h (qemuMigrationToFile): Likewise. (qemuMigrationWaitForCompletion): Make static. * src/qemu/qemu_domain.c (qemuDomainObjEnterMonitorInternal): Add parameter. (qemuDomainObjEnterMonitorAsync): New function. (qemuDomainObjEnterMonitor, qemuDomainObjEnterMonitorWithDriver): Update callers. * src/qemu/qemu_driver.c (qemuDomainSaveInternal) (qemudDomainCoreDump, doCoreDump, processWatchdogEvent) (qemudDomainSuspend, qemudDomainResume, qemuDomainSaveImageStartVM) (qemuDomainSnapshotCreateActive, qemuDomainRevertToSnapshot): Likewise. * src/qemu/qemu_process.c (qemuProcessStopCPUs) (qemuProcessFakeReboot, qemuProcessRecoverMigration) (qemuProcessRecoverJob, qemuProcessStart): Likewise. * src/qemu/qemu_migration.c (qemuMigrationToFile) (qemuMigrationWaitForCompletion, qemuMigrationUpdateJobStatus) (qemuMigrationJobStart, qemuDomainMigrateGraphicsRelocate) (doNativeMigrate, doTunnelMigrate, qemuMigrationPerformJob) (qemuMigrationPerformPhase, qemuMigrationFinish) (qemuMigrationConfirm): Likewise. * src/qemu/qemu_hotplug.c: Drop unneeded ignore_value.
2011-07-28 23:18:24 +00:00
virDomainObjPtr obj,
qemuDomainAsyncJob asyncJob)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
qemuAgentPtr qemuDomainObjEnterAgent(virDomainObjPtr obj)
ATTRIBUTE_NONNULL(1);
void qemuDomainObjExitAgent(virDomainObjPtr obj, qemuAgentPtr agent)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void qemuDomainObjEnterRemote(virDomainObjPtr obj)
ATTRIBUTE_NONNULL(1);
int qemuDomainObjExitRemote(virDomainObjPtr obj,
bool checkActive)
ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT;
virDomainDefPtr qemuDomainDefCopy(virQEMUDriverPtr driver,
virQEMUCapsPtr qemuCaps,
virDomainDefPtr src,
unsigned int flags);
int qemuDomainDefFormatBuf(virQEMUDriverPtr driver,
virQEMUCapsPtr qemuCaps,
virDomainDefPtr vm,
unsigned int flags,
virBuffer *buf);
char *qemuDomainDefFormatXML(virQEMUDriverPtr driver,
virQEMUCapsPtr qemuCaps,
virDomainDefPtr vm,
unsigned int flags);
char *qemuDomainFormatXML(virQEMUDriverPtr driver,
virDomainObjPtr vm,
unsigned int flags);
char *qemuDomainDefFormatLive(virQEMUDriverPtr driver,
virQEMUCapsPtr qemuCaps,
virDomainDefPtr def,
virCPUDefPtr origCPU,
bool inactive,
bool compatible);
void qemuDomainObjTaint(virQEMUDriverPtr driver,
virDomainObjPtr obj,
virDomainTaintFlags taint,
qemuDomainLogContextPtr logCtxt);
void qemuDomainObjCheckTaint(virQEMUDriverPtr driver,
virDomainObjPtr obj,
qemuDomainLogContextPtr logCtxt,
bool incomingMigration);
void qemuDomainObjCheckDiskTaint(virQEMUDriverPtr driver,
virDomainObjPtr obj,
virDomainDiskDefPtr disk,
qemuDomainLogContextPtr logCtxt);
void qemuDomainObjCheckHostdevTaint(virQEMUDriverPtr driver,
virDomainObjPtr obj,
virDomainHostdevDefPtr disk,
qemuDomainLogContextPtr logCtxt);
void qemuDomainObjCheckNetTaint(virQEMUDriverPtr driver,
virDomainObjPtr obj,
virDomainNetDefPtr net,
qemuDomainLogContextPtr logCtxt);
typedef enum {
QEMU_DOMAIN_LOG_CONTEXT_MODE_START,
QEMU_DOMAIN_LOG_CONTEXT_MODE_ATTACH,
QEMU_DOMAIN_LOG_CONTEXT_MODE_STOP,
} qemuDomainLogContextMode;
qemuDomainLogContextPtr qemuDomainLogContextNew(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainLogContextMode mode);
int qemuDomainLogContextWrite(qemuDomainLogContextPtr ctxt,
const char *fmt, ...) G_GNUC_PRINTF(2, 3);
ssize_t qemuDomainLogContextRead(qemuDomainLogContextPtr ctxt,
char **msg);
int qemuDomainLogContextGetWriteFD(qemuDomainLogContextPtr ctxt);
void qemuDomainLogContextMarkPosition(qemuDomainLogContextPtr ctxt);
virLogManagerPtr qemuDomainLogContextGetManager(qemuDomainLogContextPtr ctxt);
int qemuDomainLogAppendMessage(virQEMUDriverPtr driver,
virDomainObjPtr vm,
const char *fmt,
...) G_GNUC_PRINTF(3, 4);
const char *qemuFindQemuImgBinary(virQEMUDriverPtr driver);
int qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
virDomainMomentObjPtr snapshot,
virDomainXMLOptionPtr xmlopt,
const char *snapshotDir);
int qemuDomainSnapshotForEachQcow2(virQEMUDriverPtr driver,
virDomainDefPtr def,
virDomainMomentObjPtr snap,
const char *op,
bool try_all);
int qemuDomainSnapshotDiscard(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainMomentObjPtr snap,
bool update_current,
bool metadata_only);
typedef struct _virQEMUMomentRemove virQEMUMomentRemove;
typedef virQEMUMomentRemove *virQEMUMomentRemovePtr;
struct _virQEMUMomentRemove {
virQEMUDriverPtr driver;
virDomainObjPtr vm;
int err;
bool metadata_only;
virDomainMomentObjPtr current;
bool found;
int (*momentDiscard)(virQEMUDriverPtr, virDomainObjPtr,
virDomainMomentObjPtr, bool, bool);
};
int qemuDomainMomentDiscardAll(void *payload,
const char *name,
void *data);
int qemuDomainSnapshotDiscardAllMetadata(virQEMUDriverPtr driver,
virDomainObjPtr vm);
void qemuDomainRemoveInactive(virQEMUDriverPtr driver,
virDomainObjPtr vm);
void qemuDomainSetFakeReboot(virQEMUDriverPtr driver,
virDomainObjPtr vm,
bool value);
int qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
virDomainObjPtr vm,
size_t diskIndex,
bool cold_boot);
int qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
virDomainObjPtr vm,
unsigned int flags);
int qemuDomainStorageSourceValidateDepth(virStorageSourcePtr src,
int add,
const char *diskdst);
int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk,
virStorageSourcePtr disksrc,
bool report_broken);
bool qemuDomainDiskChangeSupported(virDomainDiskDefPtr disk,
virDomainDiskDefPtr orig_disk);
void qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg,
virDomainObjPtr vm,
virStorageSourcePtr src,
virStorageSourcePtr parentSrc,
uid_t *uid,
gid_t *gid);
int qemuDomainStorageFileInit(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr src,
virStorageSourcePtr parent);
char *qemuDomainStorageAlias(const char *device, int depth);
const char *
qemuDomainDiskGetTopNodename(virDomainDiskDefPtr disk)
ATTRIBUTE_NONNULL(1);
int qemuDomainDiskGetBackendAlias(virDomainDiskDefPtr disk,
virQEMUCapsPtr qemuCaps,
char **backendAlias)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
ATTRIBUTE_NONNULL(3) G_GNUC_WARN_UNUSED_RESULT;
int qemuDomainStorageSourceChainAccessAllow(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr src);
int qemuDomainStorageSourceChainAccessRevoke(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr src);
void qemuDomainStorageSourceAccessRevoke(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr elem);
int qemuDomainStorageSourceAccessAllow(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr elem,
bool readonly,
bool newSource,
bool chainTop);
int qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk,
virStorageSourcePtr src,
qemuDomainObjPrivatePtr priv,
virQEMUDriverConfigPtr cfg);
int qemuDomainCleanupAdd(virDomainObjPtr vm,
qemuDomainCleanupCallback cb);
void qemuDomainCleanupRemove(virDomainObjPtr vm,
qemuDomainCleanupCallback cb);
void qemuDomainCleanupRun(virQEMUDriverPtr driver,
virDomainObjPtr vm);
void qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv);
extern virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks;
extern virXMLNamespace virQEMUDriverDomainXMLNamespace;
extern virDomainDefParserConfig virQEMUDriverDomainDefParserConfig;
extern virDomainABIStability virQEMUDriverDomainABIStability;
extern virSaveCookieCallbacks virQEMUDriverDomainSaveCookie;
int qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
virDomainObjPtr vm, int asyncJob);
int qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver,
virDomainObjPtr vm,
int asyncJob);
bool qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
virQEMUCapsPtr qemuCaps,
virDomainDefPtr src,
virDomainDefPtr dst);
bool qemuDomainCheckABIStability(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDefPtr dst);
bool qemuDomainAgentAvailable(virDomainObjPtr vm,
bool reportError);
bool qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk);
bool qemuDomainHasBlockjob(virDomainObjPtr vm, bool copy_only)
ATTRIBUTE_NONNULL(1);
int qemuDomainAlignMemorySizes(virDomainDefPtr def);
qemu: revert latest pSeries NVDIMM design changes In [1], changes were made to remove the existing auto-alignment for pSeries NVDIMM devices. That design promotes strange situations where the NVDIMM size reported in the domain XML is different from what QEMU is actually using. We removed the auto-alignment and relied on standard size validation. However, this goes against Libvirt design philosophy of not tampering with existing guest behavior, as pointed out by Daniel in [2]. Since we can't know for sure whether there are guests that are relying on the auto-alignment feature to work, the changes made in [1] are a direct violation of this rule. This patch reverts [1] entirely, re-enabling auto-alignment for pSeries NVDIMM as it was before. Changes will be made to ease the limitations of this design without hurting existing guests. This reverts the following commits: - commit 2d93cbdea9d1b8dbf36bc0ffee6cb73d83d208c7 Revert "formatdomain.html.in: mention pSeries NVDIMM 'align down' mechanic" - commit 0ee56369c8b4f2f898b6aa1ff1f51ab033be1c02 qemu_domain.c: change qemuDomainMemoryDeviceAlignSize() return type - commit 07de813924caf37e535855541c0c1183d9d382e2 qemu_domain.c: do not auto-align ppc64 NVDIMMs - commit 0ccceaa57c50e5ee528f7073fa8723afd62b88b7 qemu_validate.c: add pSeries NVDIMM size alignment validation - commit 4fa2202d884414ad34d9952e72fb39b1d93c7e14 qemu_domain.c: make qemuDomainGetMemorySizeAlignment() public [1] https://www.redhat.com/archives/libvir-list/2020-July/msg02010.html [2] https://www.redhat.com/archives/libvir-list/2020-September/msg00572.html Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Reviewed-by: Andrea Bolognani <abologna@redhat.com>
2020-09-15 02:42:56 +00:00
int qemuDomainMemoryDeviceAlignSize(virDomainDefPtr def,
virDomainMemoryDefPtr mem);
virDomainChrDefPtr qemuFindAgentConfig(virDomainDefPtr def);
/* You should normally avoid these functions and use the variant that
* doesn't have "Machine" in the name instead. */
bool qemuDomainMachineIsARMVirt(const char *machine,
const virArch arch);
bool qemuDomainMachineIsPSeries(const char *machine,
const virArch arch);
bool qemuDomainMachineHasBuiltinIDE(const char *machine,
const virArch arch);
bool qemuDomainIsQ35(const virDomainDef *def);
bool qemuDomainIsI440FX(const virDomainDef *def);
bool qemuDomainIsS390CCW(const virDomainDef *def);
bool qemuDomainIsARMVirt(const virDomainDef *def);
bool qemuDomainIsRISCVVirt(const virDomainDef *def);
bool qemuDomainIsPSeries(const virDomainDef *def);
bool qemuDomainHasPCIRoot(const virDomainDef *def);
bool qemuDomainHasPCIeRoot(const virDomainDef *def);
bool qemuDomainHasBuiltinIDE(const virDomainDef *def);
bool qemuDomainHasBuiltinESP(const virDomainDef *def);
bool qemuDomainNeedsFDC(const virDomainDef *def);
bool qemuDomainSupportsPCI(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps);
void qemuDomainUpdateCurrentMemorySize(virDomainObjPtr vm);
unsigned long long qemuDomainGetMemLockLimitBytes(virDomainDefPtr def,
bool forceVFIO);
int qemuDomainAdjustMaxMemLock(virDomainObjPtr vm,
bool forceVFIO);
int qemuDomainAdjustMaxMemLockHostdev(virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev);
int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
const virDomainMemoryDef *mem);
bool qemuDomainSupportsNewVcpuHotplug(virDomainObjPtr vm);
bool qemuDomainHasVcpuPids(virDomainObjPtr vm);
pid_t qemuDomainGetVcpuPid(virDomainObjPtr vm, unsigned int vcpuid);
int qemuDomainValidateVcpuInfo(virDomainObjPtr vm);
int qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
virDomainObjPtr vm,
int asyncJob,
bool state);
bool qemuDomainGetVcpuHalted(virDomainObjPtr vm, unsigned int vcpu);
int qemuDomainRefreshVcpuHalted(virQEMUDriverPtr driver,
virDomainObjPtr vm,
int asyncJob);
bool qemuDomainSupportsNicdev(virDomainDefPtr def,
virDomainNetDefPtr net);
bool qemuDomainNetSupportsMTU(virDomainNetType type);
int qemuDomainSetPrivatePaths(virQEMUDriverPtr driver,
virDomainObjPtr vm);
virDomainDiskDefPtr qemuDomainDiskByName(virDomainDefPtr def, const char *name);
qemu: Create domain master key Add a masterKey and masterKeyLen to _qemuDomainObjPrivate to store a random domain master key and its length in order to support the ability to encrypt/decrypt sensitive data shared between libvirt and qemu. The key will be base64 encoded and written to a file to be used by the command line building code to share with qemu. New API's from this patch: qemuDomainGetMasterKeyFilePath: Return a path to where the key is located qemuDomainWriteMasterKeyFile: (private) Open (create/trunc) the masterKey path and write the masterKey qemuDomainMasterKeyReadFile: Using the master key path, open/read the file, and store the masterKey and masterKeyLen. Expected use only from qemuProcessReconnect qemuDomainGenerateRandomKey: (private) Generate a random key using available algorithms The key is generated either from the gnutls_rnd function if it exists or a less cryptographically strong mechanism using virGenerateRandomBytes qemuDomainMasterKeyRemove: Remove traces of the master key, remove the *KeyFilePath qemuDomainMasterKeyCreate: Generate the domain master key and save the key in the location returned by qemuDomainGetMasterKeyFilePath. This API will first ensure the QEMU_CAPS_OBJECT_SECRET is set in the capabilities. If not, then there's no need to generate the secret or file. The creation of the key will be attempted from qemuProcessPrepareHost once the libDir directory structure exists. The removal of the key will handled from qemuProcessStop just prior to deleting the libDir tree. Since the key will not be written out to the domain object XML file, the qemuProcessReconnect will read the saved file and restore the masterKey and masterKeyLen.
2016-03-29 22:22:46 +00:00
char *qemuDomainGetMasterKeyFilePath(const char *libDir);
int qemuDomainMasterKeyReadFile(qemuDomainObjPrivatePtr priv);
int qemuDomainWriteMasterKeyFile(virQEMUDriverPtr driver,
virDomainObjPtr vm);
int qemuDomainMasterKeyCreate(virDomainObjPtr vm);
qemu: Create domain master key Add a masterKey and masterKeyLen to _qemuDomainObjPrivate to store a random domain master key and its length in order to support the ability to encrypt/decrypt sensitive data shared between libvirt and qemu. The key will be base64 encoded and written to a file to be used by the command line building code to share with qemu. New API's from this patch: qemuDomainGetMasterKeyFilePath: Return a path to where the key is located qemuDomainWriteMasterKeyFile: (private) Open (create/trunc) the masterKey path and write the masterKey qemuDomainMasterKeyReadFile: Using the master key path, open/read the file, and store the masterKey and masterKeyLen. Expected use only from qemuProcessReconnect qemuDomainGenerateRandomKey: (private) Generate a random key using available algorithms The key is generated either from the gnutls_rnd function if it exists or a less cryptographically strong mechanism using virGenerateRandomBytes qemuDomainMasterKeyRemove: Remove traces of the master key, remove the *KeyFilePath qemuDomainMasterKeyCreate: Generate the domain master key and save the key in the location returned by qemuDomainGetMasterKeyFilePath. This API will first ensure the QEMU_CAPS_OBJECT_SECRET is set in the capabilities. If not, then there's no need to generate the secret or file. The creation of the key will be attempted from qemuProcessPrepareHost once the libDir directory structure exists. The removal of the key will handled from qemuProcessStop just prior to deleting the libDir tree. Since the key will not be written out to the domain object XML file, the qemuProcessReconnect will read the saved file and restore the masterKey and masterKeyLen.
2016-03-29 22:22:46 +00:00
void qemuDomainMasterKeyRemove(qemuDomainObjPrivatePtr priv);
bool qemuDomainSupportsEncryptedSecret(qemuDomainObjPrivatePtr priv);
void qemuDomainSecretInfoFree(qemuDomainSecretInfoPtr secinfo)
ATTRIBUTE_NONNULL(1);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuDomainSecretInfo, qemuDomainSecretInfoFree);
void qemuDomainSecretInfoDestroy(qemuDomainSecretInfoPtr secinfo);
void qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk)
ATTRIBUTE_NONNULL(1);
bool qemuDomainStorageSourceHasAuth(virStorageSourcePtr src)
ATTRIBUTE_NONNULL(1);
qemuDomainSecretInfoPtr
qemuDomainSecretInfoTLSNew(qemuDomainObjPrivatePtr priv,
const char *srcAlias,
const char *secretUUID);
void qemuDomainSecretHostdevDestroy(virDomainHostdevDefPtr disk)
ATTRIBUTE_NONNULL(1);
void qemuDomainSecretChardevDestroy(virDomainChrSourceDefPtr dev)
ATTRIBUTE_NONNULL(1);
int qemuDomainSecretChardevPrepare(virQEMUDriverConfigPtr cfg,
qemuDomainObjPrivatePtr priv,
const char *chrAlias,
virDomainChrSourceDefPtr dev)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_NONNULL(4);
void qemuDomainSecretDestroy(virDomainObjPtr vm)
ATTRIBUTE_NONNULL(1);
int qemuDomainSecretPrepare(virQEMUDriverPtr driver,
virDomainObjPtr vm)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuDomainDefValidateDiskLunSource(const virStorageSource *src)
ATTRIBUTE_NONNULL(1);
int qemuDomainDeviceDefValidateDisk(const virDomainDiskDef *disk,
virQEMUCapsPtr qemuCaps);
int qemuDomainPrepareChannel(virDomainChrDefPtr chr,
const char *domainChannelTargetDir)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void qemuDomainPrepareChardevSourceTLS(virDomainChrSourceDefPtr source,
virQEMUDriverConfigPtr cfg)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void qemuDomainPrepareChardevSource(virDomainDefPtr def,
virQEMUDriverConfigPtr cfg)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void qemuDomainPrepareShmemChardev(virDomainShmemDefPtr shmem)
ATTRIBUTE_NONNULL(1);
bool qemuDomainVcpuHotplugIsInOrder(virDomainDefPtr def)
ATTRIBUTE_NONNULL(1);
void qemuDomainVcpuPersistOrder(virDomainDefPtr def)
ATTRIBUTE_NONNULL(1);
int qemuDomainCheckMonitor(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob);
bool qemuDomainSupportsVideoVga(virDomainVideoDefPtr video,
virQEMUCapsPtr qemuCaps);
bool qemuDomainNeedsVFIO(const virDomainDef *def);
int qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,
char **path,
int *perms);
virDomainDiskDefPtr qemuDomainDiskLookupByNodename(virDomainDefPtr def,
virDomainBackupDefPtr backupdef,
const char *nodename,
virStorageSourcePtr *src);
char *qemuDomainDiskBackingStoreGetName(virDomainDiskDefPtr disk,
unsigned int idx);
virStorageSourcePtr qemuDomainGetStorageSourceByDevstr(const char *devstr,
virDomainDefPtr def,
virDomainBackupDefPtr backupdef);
int
qemuDomainUpdateCPU(virDomainObjPtr vm,
virCPUDefPtr cpu,
virCPUDefPtr *origCPU);
int
qemuDomainFixupCPUs(virDomainObjPtr vm,
virCPUDefPtr *origCPU);
char *
qemuDomainGetMachineName(virDomainObjPtr vm);
void
qemuDomainObjPrivateXMLFormatAllowReboot(virBufferPtr buf,
virTristateBool allowReboot);
int
qemuDomainObjPrivateXMLParseAllowReboot(xmlXPathContextPtr ctxt,
virTristateBool *allowReboot);
bool
qemuDomainCheckCCWS390AddressSupport(const virDomainDef *def,
const virDomainDeviceInfo *info,
virQEMUCapsPtr qemuCaps,
const char *devicename);
void
qemuDomainPrepareDiskSourceData(virDomainDiskDefPtr disk,
virStorageSourcePtr src);
int
qemuDomainValidateStorageSource(virStorageSourcePtr src,
virQEMUCapsPtr qemuCaps,
bool maskBlockdev);
int
qemuDomainPrepareDiskSource(virDomainDiskDefPtr disk,
qemuDomainObjPrivatePtr priv,
virQEMUDriverConfigPtr cfg);
int
qemuDomainDiskCachemodeFlags(int cachemode,
bool *writeback,
bool *direct,
bool *noflush);
int
qemuDomainPrepareHostdev(virDomainHostdevDefPtr hostdev,
qemuDomainObjPrivatePtr priv);
char * qemuDomainGetManagedPRSocketPath(qemuDomainObjPrivatePtr priv);
bool qemuDomainDefHasManagedPR(virDomainObjPtr vm);
unsigned int qemuDomainStorageIdNew(qemuDomainObjPrivatePtr priv);
void qemuDomainStorageIdReset(qemuDomainObjPrivatePtr priv);
virDomainEventResumedDetailType
qemuDomainRunningReasonToResumeEvent(virDomainRunningReason reason);
bool
qemuDomainIsUsingNoShutdown(qemuDomainObjPrivatePtr priv);
bool
qemuDomainDiskIsMissingLocalOptional(virDomainDiskDefPtr disk);
void
qemuDomainNVRAMPathFormat(virQEMUDriverConfigPtr cfg,
virDomainDefPtr def,
char **path);
void
qemuDomainNVRAMPathGenerate(virQEMUDriverConfigPtr cfg,
virDomainDefPtr def);
virDomainEventSuspendedDetailType
qemuDomainPausedReasonToSuspendedEvent(virDomainPausedReason reason);
int
qemuDomainValidateActualNetDef(const virDomainNetDef *net,
virQEMUCapsPtr qemuCaps);
int
qemuDomainSupportsCheckpointsBlockjobs(virDomainObjPtr vm)
G_GNUC_WARN_UNUSED_RESULT;
int
qemuDomainMakeCPUMigratable(virCPUDefPtr cpu);
int
qemuDomainInitializePflashStorageSource(virDomainObjPtr vm);
bool
qemuDomainDiskBlockJobIsSupported(virDomainObjPtr vm,
virDomainDiskDefPtr disk);
qemu_domain.c: NUMA CPUs auto-fill for incomplete topologies Libvirt allows the user to define an incomplete NUMA topology, where the sum of all CPUs in each cell is less than the total of VCPUs. What ends up happening is that QEMU allocates the non-enumerated CPUs in the first NUMA node. This behavior is being flagged as 'to be deprecated' at least since QEMU commit ec78f8114bc4 ("numa: use possible_cpus for not mapped CPUs check"). In [1], Maxiwell suggested that we forbid the user to define such topologies. In his review [2], Peter Krempa pointed out that we can't break existing guests, and suggested that Libvirt should emulate the QEMU behavior of putting the remaining vCPUs in the first NUMA node in these cases. This patch implements Peter Krempa's suggestion. Since we're going to most likely end up with disjointed NUMA configuration in node 0 after the auto-fill, we're making auto-fill dependent on QEMU_CAPS_NUMA. A following patch will update the documentation not just to inform about the auto-fill mechanic with incomplete NUMA topologies, but also to discourage the user to create such topologies in the future. This approach also makes Libvirt independent of whether QEMU changes its current behavior since we're either auto-filling the CPUs in node 0 or the user (hopefully) is aware that incomplete topologies, although supported in Libvirt, are to be avoided. [1] https://www.redhat.com/archives/libvir-list/2019-June/msg00224.html [2] https://www.redhat.com/archives/libvir-list/2019-June/msg00263.html Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2020-06-10 18:35:51 +00:00
int
qemuDomainDefNumaCPUsRectify(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps);
void qemuDomainRemoveInactiveJob(virQEMUDriverPtr driver,
virDomainObjPtr vm);
void qemuDomainRemoveInactiveJobLocked(virQEMUDriverPtr driver,
virDomainObjPtr vm);
int virQEMUFileOpenAs(uid_t fallback_uid,
gid_t fallback_gid,
bool dynamicOwnership,
const char *path,
int oflags,
bool *needUnlink);
int
qemuDomainOpenFile(virQEMUDriverPtr driver,
virDomainObjPtr vm,
const char *path,
int oflags,
bool *needUnlink);
int
qemuDomainFileWrapperFDClose(virDomainObjPtr vm,
virFileWrapperFdPtr fd);
int
qemuDomainInterfaceSetDefaultQDisc(virQEMUDriverPtr driver,
virDomainNetDefPtr net);
int
qemuDomainNamePathsCleanup(virQEMUDriverConfigPtr cfg,
const char *name,
bool bestEffort);