[libvirt] [PATCH v2 0/7] Add multiqueue support for macvtaps
by Michal Privoznik
Patches 1, 2, 3, 6, 7 have been ACKed in previous round. However, I did
slightly change them to reflect Laine's review suggestions.
Patch 4 has not been ACKed yet, patch 5 is new.
Michal Privoznik (7):
virNetDevMacVLanCreateWithVPortProfile: Turn vnet_hdr into flag
virNetDevMacVLanTapOpen: Slightly rework
virNetDevMacVLanTapOpen: Rework to support multiple FDs
virNetDevMacVLanTapSetup: Rework to support multiple FDs
virNetDevMacVLanTapSetup: Allow enabling of IFF_MULTI_QUEUE
virNetDevMacVLanCreateWithVPortProfile: Rework to support multiple FDs
qemu: Enable multiqueue for macvtaps
src/lxc/lxc_process.c | 3 +-
src/qemu/qemu_command.c | 65 ++++++++++------
src/qemu/qemu_command.h | 2 +
src/qemu/qemu_hotplug.c | 16 ++--
src/util/virnetdevmacvlan.c | 185 ++++++++++++++++++++++----------------------
src/util/virnetdevmacvlan.h | 7 +-
6 files changed, 153 insertions(+), 125 deletions(-)
--
2.4.10
8 years, 11 months
[libvirt] how to pass qemu drive option
by Vasiliy Tolstov
I want to pass to my drive detect-zeros=on how can i do that in libvirt?
I'm use lvm with virtio-scsi for sda disk.
--
Vasiliy Tolstov,
e-mail: v.tolstov(a)selfip.ru
8 years, 11 months
[libvirt] [PATCH] qemu_agent: fix deadlock in qemuProcessHandleAgentEOF
by Wang Yufei
We shutdown a VM A by qemu agent,meanwhile an agent EOF
of VM A happened, there's a chance that deadlock occurred:
qemuProcessHandleAgentEOF in main thread
A) priv->agent = NULL; //A happened before B
//deadlock when we get agent lock which's held by worker thread
qemuAgentClose(agent);
qemuDomainObjExitAgent called by qemuDomainShutdownFlags in worker thread
B) hasRefs = virObjectUnref(priv->agent); //priv->agent is NULL, return false
if (hasRefs)
virObjectUnlock(priv->agent); //agent lock will not be released here
So I close agent first, then set priv->agent NULL to fix the deadlock.
Signed-off-by: Wang Yufei <james.wangyufei(a)huawei.com>
Reviewed-by: Ren Guannan <renguannan(a)huawei.com>
---
src/qemu/qemu_process.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f2586a1..8c9622e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -150,11 +150,10 @@ qemuProcessHandleAgentEOF(qemuAgentPtr agent,
goto unlock;
}
+ qemuAgentClose(agent);
priv->agent = NULL;
virObjectUnlock(vm);
-
- qemuAgentClose(agent);
return;
unlock:
--
1.8.3.4
8 years, 11 months
[libvirt] Release of libvirt-1.3.0
by Daniel Veillard
So as planned, I tagged the release in git and pushed signed tarball and
rpms to the usual place:
ftp://libvirt.org/libvirt
I also pushed the associated python release for 1.3.0 though there was no
actual code change except numbering:
ftp://libvirt.org/libvirt/python
The bump in version minor number comes from the addition of the administration
API which nearly made it in 1.2.17 in the summer but was postponed since. That
is backed up by serious improvement in virtio support and logging. As usual
that release carries a sigificant amount of fixes and smaller improvements too:
Features:
- virt-admin and administration API (Erik Skultety, Martin Kletzander)
- various improvements in virtio devices support (Ján Tomko, Marc-André Lureau)
- log daemon, logging improvements and protocol (Daniel P. Berrange)
Documentation:
- libvirt: Update virDomainSetMemory description (Nikolay Shirokovskiy)
- virt-admin: Provide a man page for virt-admin (Erik Skultety)
- Enhance documentation of virDomainDetachDevice (Jiri Denemark)
- qemu: monitor: Explain logic of qemuMonitorGetCPUInfo (Peter Krempa)
- document virCommandRunRegex function (Christian Loehle)
- libvirt-domain: Fix typo in debug message (Cole Robinson)
- qemu: Explain mlock limit size more in detail (Peter Krempa)
- virsh.pod: improve attach-interface section (Pavel Hrdina)
- virnetdev: Fix function comments for virNetDevGetFeatures (John Ferlan)
- virnetdev: Document reasons for ignoring some SIOCETHTOOL errno values (John Ferlan)
Portability:
- network: selectively disable -Wcast-align in virNetDevParseDadStatus (Ian Campbell)
- log_manager: Include configmake.h last (Michal Privoznik)
- virtlogd: Fix build without DBus (Martin Kletzander)
- virtlogd: use %llu to print 64bit types (Guido Günther)
Bug Fixes:
- qemu: fix memory leak in opening log file (Daniel P. Berrange)
- qemu: Automatic SCSI controller creation in SCSI disk hotplug broken (Boris Fiuczynski)
- qemu: domain: Prevent overflows in memory alignment code (Peter Krempa)
- conf: Revert some code to resolve issues for hostdev hotplug (Boris Fiuczynski)
- virsh: report errors for empty strings (Ján Tomko)
- bridge: check for invalid MAC in networkGetDHCPLeases (Ján Tomko)
- qemu_agent: fix deadlock in qemuProcessHandleAgentEOF (Wang Yufei)
- include: Install libvirt-common.h (Martin Kletzander)
- tools: fix output of list with state-shutoff (Wei Jiangang)
- virlogd: fix crash if log file exists and it's larger the maxlen (Pavel Hrdina)
- systemd: Escape only needed characters for machined (Martin Kletzander)
- logging: remove reference to non-existent augeas files (Daniel P. Berrange)
- virtlockd: fix misc memory leaks and other bugs (Daniel P. Berrange)
- systemd: Escape machine name for machined (Martin Kletzander)
- schema: use a better regex for listen addresses (Ján Tomko)
- apparmor: add missing qemu binaries (Guido Günther)
- storage: Change virStorageBackendVolOpen to use virFileOpenAs (John Ferlan)
- storage: Really fix setting mode for backend exec in NFS root-squash env (John Ferlan)
- qemu: Add ppc64-specific math to qemuDomainGetMlockLimitBytes() (Andrea Bolognani)
- libxl: don't unlock virDomainObj if refcnt is 0 (Jim Fehlig)
- libxl: unref libxlDriverConfig object (Jim Fehlig)
- qemu: Fix build error in Coverity environment (John Ferlan)
- virSetUIDGID: Don't leak supplementary groups (Richard Weinberger)
- locking: Add io_timeout to sanlock (Michal Privoznik)
- libvirt-guests: Disable shutdown timeout (Guido Günther)
- tpm: adapt sysfs cancel path for new TPM driver (Stefan Berger)
- bhyve: monitor: do not override domain's privateData (Roman Bogorodskiy)
- storage: Don't assume storage pool exists for FC/SCSI refresh thread (John Ferlan)
- domain-conf: reorder usb controllers so the master is first (Pavel Hrdina)
- qemu: fix parsing of -sdl arg (Daniel P. Berrange)
- qemu: handle floppy disk bus when parsing command line argv (Daniel P. Berrange)
- qemu: hotplug: Fix mlock limit handling on memory hotplug (Peter Krempa)
- Revert "utils: Remove the logging of errors from virNetDevSendEthtoolIoctl" (Daniel P. Berrange)
- qemu: migration: Actually error out on unsupported migration flag (Peter Krempa)
- qemu: migration: Properly parse memory hotplug migration flag (Peter Krempa)
- network: Remove extraneous ATTRIBUTE_NONNULL for virNetDevWaitDadFinish (John Ferlan)
- virnetdev: Check correct return value for virNetDevFeatureAvailable (John Ferlan)
- storage: On 'buildVol' failure don't delete the volume (John Ferlan)
- Revert "storage: Prior to creating a volume, refresh the pool" (John Ferlan)
- qemu: Fix memory leak in qemuProcessStart (Jiri Denemark)
- qemu: Use correct type when calling qemuPrepareNVRAM (Jiri Denemark)
Improvements:
- Revert "libxl: implement virDomainInterfaceStats" (Jim Fehlig)
- rpm: explicitly enable & start virtlogd on install (Daniel P. Berrange)
- libvirtd: enable virtlockd/virtlogd socket activation on install (Daniel P. Berrange)
- logging: validate flags passed from client in virtlogd (Daniel P. Berrange)
- logging: change log protocol to be more reusable (Daniel P. Berrange)
- logging: preserve driver, dom name & uuid against log file (Daniel P. Berrange)
- qemu: include hostname in QEMU log files (Daniel P. Berrange)
- rotatingfile: mark log files as close-on-exec (Daniel P. Berrange)
- libvirtd: require virtlogd to start before libvirtd (Guido Günther)
- schema: Allow > UINT_MAX KiB of memory for NUMA nodes (Peter Krempa)
- virsh: remove custom error for cpulist from cmdIOThreadPin (Ján Tomko)
- libxl: implement virDomainInterfaceStats (Joao Martins)
- tests: Run virnetdaemontest iff WITH_YAJL (Michal Privoznik)
- admin: Distribute libvirt-admin.conf (Martin Kletzander)
- admin: Rename virAdmConnect to virAdmDaemon (Martin Kletzander)
- spec: Temporarily disable new admin-related files (Martin Kletzander)
- admin: Include admin_remote.c in the dist package (Martin Kletzander)
- build: Create needed folders without dependency tracking (Martin Kletzander)
- util: Avoid variable named 'truncate' shadowing global declaration (Martin Kletzander)
- conf: Split virDomainObjList into a separate file (Michal Privoznik)
- qemu: build command line for virtio-input-host device (Ján Tomko)
- qemu: add passed-through input devs to cgroup ACL (Ján Tomko)
- security: label the evdev for input device passthrough (Ján Tomko)
- conf: add XML for input device passthrough (Ján Tomko)
- qemu: add capability for virtio-input-host-device (Ján Tomko)
- qemu: build command line for virtio input devices (Ján Tomko)
- conf: parse and format virtio input bus in domain XML (Ján Tomko)
- qemu: add capabilities for virtio input devices (Ján Tomko)
- admin: Introduce virAdmConnectGetLibVersion (Erik Skultety)
- admin: Add support for connection close callbacks (Erik Skultety)
- admin: Add support for URI aliases (Erik Skultety)
- livirt: Move URI alias matching to util (Erik Skultety)
- admin: Add URI support and introduce virAdmGetDefaultURI (Erik Skultety)
- admin: Do not generate remoteAdminConnect{Open,Close} (Erik Skultety)
- admin: Move remote admin API version to a separate module (Erik Skultety)
- admin: Introduce virAdmConnectIsAlive (Erik Skultety)
- virt-admin: Introduce first working skeleton (Erik Skultety)
- admin: introduce virAdmGetVersion (Erik Skultety)
- libvirt: Move config getters to util (Erik Skultety)
- admin: Introduce libvirt-admin.conf (Erik Skultety)
- libvirt: introduce libvirt/libvirt-common.h.in (Erik Skultety)
- qemu: add virtio-gpu virgl support (Marc-André Lureau)
- qemu: add virtio video device (Marc-André Lureau)
- domain: replace bool accel{2d, 3d} with a tristate (Marc-André Lureau)
- Replace support{2d,3d} with accel{2d,3d} (Marc-André Lureau)
- logging: avoid variables called 'daemon' due to function clash (Daniel P. Berrange)
- logging: inhibit virtlogd shutdown while log files are open (Daniel P. Berrange)
- qemu: add support for sending QEMU stdout/stderr to virtlogd (Daniel P. Berrange)
- qemu: convert monitor to use qemuDomainLogContextPtr indirectly (Daniel P. Berrange)
- qemu: convert process stop/attach to use qemuDomainLogContextPtr (Daniel P. Berrange)
- qemu: convert qemuLogOperation to take a qemuDomainLogContextPtr (Daniel P. Berrange)
- qemu: change qemuDomainTaint APIs to accept qemuDomainLogContextPtr (Daniel P. Berrange)
- qemu: convert log file creation to use qemuDomainLogContextPtr (Daniel P. Berrange)
- qemu: introduce a qemuDomainLogContext object (Daniel P. Berrange)
- qemu: unify code for reporting errors from QEMU log files (Daniel P. Berrange)
- qemu: remove writing to QEMU log file for rename operation (Daniel P. Berrange)
- logging: add client for virtlogd daemon (Daniel P. Berrange)
- logging: introduce log handling protocol (Daniel P. Berrange)
- Import stripped down virtlockd code as basis of virtlogd (Daniel P. Berrange)
- util: add APIs for reading/writing from/to rotating files (Daniel P. Berrange)
- virsh: Try to keep printed XML pretty with change-media (Martin Kletzander)
- qemu: Use qemuProcessLaunch in migration Prepare phase (Jiri Denemark)
- qemu: Skip starting NBD servers for offline migration (Jiri Denemark)
- qemu: Kill QEMU process if Prepare phase fails (Jiri Denemark)
- qemu: Separate incoming URI generation from qemuMigrationPrepareAny (Jiri Denemark)
- qemu: Introduce qemuProcessFinishStartup (Jiri Denemark)
- qemu: Introduce qemuProcessLaunch (Jiri Denemark)
- qemu: Introduce qemuProcessInit (Jiri Denemark)
- conf: reject multiple panic devices of same model (Dmitry Andreev)
- Allow multiple panic devices (Dmitry Andreev)
- qemu: add support for hv_crash feature as a panic device (Dmitry Andreev)
- tests: add tests for the new panic device attribute - 'model' (Dmitry Andreev)
- conf: add 'model' attribute for panic device with values isa, pseries, hyperv (Dmitry Andreev)
- conf: refactor code for checking ABI stability of panic device (Dmitry Andreev)
- nodedev: report maxCount for virtual_functions capability (Laine Stump)
- conf: support reporting maxCount attribute for virtual_functions cap (Laine Stump)
- Post-release version bump to 1.3.0 (Pavel Hrdina)
- conf: Drop useless check when parsing cpu scheduler info (Peter Krempa)
- qemu: pass the asyncJob to qemuProcessStartCPUs (Ján Tomko)
- xenapi: Refactor extraction of vcpu count (Peter Krempa)
- phyp: Refactor extraction of vcpu count (Peter Krempa)
- openvz: Refactor extraction of vcpu count (Peter Krempa)
- hyperv: Allocate 'def' via virDomainDefNew (Peter Krempa)
- qemuSetupChrSourceCgroup: rename dev to source (Ján Tomko)
- Simplify qemuSetupChrSourceCgroup and its callers (Ján Tomko)
- rename qemuSetupHostdevCGroup to qemuSetupHostdevCgroup (Ján Tomko)
- qemu: handle more machines with a single builtin IDE controller (Guido Günther)
- qemu: Always set locked memory limit for ppc64 domains (Andrea Bolognani)
- qemu: Use qemuDomainRequiresMlock() when attaching PCI hostdev (Andrea Bolognani)
- qemu: Use qemuDomainRequiresMlock() in qemuBuildCommandLine() (Andrea Bolognani)
- process: Log when limiting the amount of locked memory (Andrea Bolognani)
- vz: implementation of domainReboot callback (Mikhail Feoktistov)
- vz: allow only en-us keymap for VNC (Mikhail Feoktistov)
- qemu: Close logfd when closing monitor (Jiri Denemark)
- qemu: Do not infer flags from other qemuProcessStart arguments (Jiri Denemark)
- qemu: Introduce qemuProcessMakeDir (Jiri Denemark)
- qemu: Separate balloon code from qemuProcessStart (Jiri Denemark)
- qemu: Enter monitor within qemuProcessSetLinkStates (Jiri Denemark)
- qemu: Separate raw IO code from qemuProcessStart (Jiri Denemark)
- qemu: Separate graphics handling code from qemuProcessStart (Jiri Denemark)
- qemu: Separate hook handling code from qemuProcessStart (Jiri Denemark)
- qemu: Rename stdin_{fd,path} in qemuProcessStart (Jiri Denemark)
- qemu: Use -incoming defer for migrations (Jiri Denemark)
- qemu: Add APIs for migrate-incoming QMP command (Jiri Denemark)
- qemu: Always set async job when starting a domain (Jiri Denemark)
- qemu: Introduce qemuProcessIncomingDef (Jiri Denemark)
- qemu: Move incoming URI code to qemu_migration (Jiri Denemark)
- qemu: Don't generate migration URI in qemuBuildCommandLine (Jiri Denemark)
- qemu: Refactor the code to build -incoming command line (Jiri Denemark)
- qemu: Refactor waiting for completed migration on destination (Jiri Denemark)
- util: add virDiskNameParse to handle disk and partition idx (Joao Martins)
- libxl: implement virDomainMemorystats (Joao Martins)
- lxc: Bind mount container TTYs (Richard Weinberger)
- lxc: Don't make container's TTY a controlling TTY (Richard Weinberger)
- qemu: ppc64: Support memory hotplug without NUMA enabled (Peter Krempa)
- qemu: command: Prepare memory device def formatter for missing target node (Peter Krempa)
- conf: Prepare making memory device target node optional (Peter Krempa)
- qemu: command: Move dimm device checks from formatter to checker (Peter Krempa)
- qemu: domain: Add common function to perform memory hotplug checks (Peter Krempa)
- qemu: command: Always execute memory device formatter (Peter Krempa)
- qemu: command: Make qemuBuildMemoryBackendStr usable without NUMA (Peter Krempa)
- libxl: implement virDomainGetCPUStats (Joao Martins)
- syntax-check: Add prohibit_space_in_label rule (Andrea Bolognani)
- util: remove unnecessary needSize (Chen Hanxiao)
- storage: Introduce virStoragePoolObjFindPoolByUUID (John Ferlan)
- storage: Change cbdata scsi refresh thread field name (John Ferlan)
- storage: Make active boolean (John Ferlan)
- qemu: domain: Restructurate control flow in qemuDomainGetMlockLimitBytes (Peter Krempa)
- qemu: Fix job entry debug message (Jiri Denemark)
- tests: Add QEMU 2.4.0 capabilities (Jiri Denemark)
- tests: Remove qemuxmlnstest (Jiri Denemark)
- qemu: Fix style in qemuProcessStart (Jiri Denemark)
- security: Cleanup DAC driver (Jiri Denemark)
- domain-conf: cleanup controller insert function (Pavel Hrdina)
- virsh-domain: update attach-interface to support type=hostdev (Pavel Hrdina)
- vz: support cpu time in driver's domainGetInfo (Nikolay Shirokovskiy)
- qemu: assume various QEMU 0.10 features are always available (Daniel P. Berrange)
- qemu: assume -vga is always available (Daniel P. Berrange)
- qemu: assume -drive format is always available (Daniel P. Berrange)
- qemu: assume -drive cache always uses v2 option names (Daniel P. Berrange)
- qemu: assume support for all migration protocols except rdma (Daniel P. Berrange)
- qemu: assume vnet-hdr feature is always available (Daniel P. Berrange)
- qemu: really remove last traces of Xenner support (Daniel P. Berrange)
- qemu: assume -uuid is always available (Daniel P. Berrange)
- qemu: assume -name is always available (Daniel P. Berrange)
- qemu: assume -drive argument is always available (Daniel P. Berrange)
- qemu: handle USB bus in qemuAssignDeviceDiskAliasFixed() (Daniel P. Berrange)
- qemu: assume -no-reboot is always available (Daniel P. Berrange)
- qemu: assume 'info chardev' is always available (Daniel P. Berrange)
- qemu: assume -vnc arg always takes a ':' (Daniel P. Berrange)
- qemu: remove all support for kQEMU (Daniel P. Berrange)
- qemu: mandate QEMU version 0.12.0 or newer (Daniel P. Berrange)
- qemu: hotplug: Reject VFIO hotplug if setting RLIMIT_MEMLOCK fails (Peter Krempa)
- qemu: Extract logic to determine the mlock limit size for VFIO (Peter Krempa)
- conf: Make @def const in virDomainDefGetMemoryInitial (Peter Krempa)
- tests: redo test argv file line wrapping (Daniel P. Berrange)
- virnetdev: Use virNetDevSetupControl in virNetDevSendEthtoolIoctl (John Ferlan)
- virnetdev: Check for root in virNetDevGetFeatures (John Ferlan)
- qemu: add /usr/lib to AC_PATH_PROG for qemu-bridge-helper (Michel Normand)
- storage: Pull volume removal from pool in storageVolDeleteInternal (John Ferlan)
- storage: Cleanup failures in virStorageBackendCreateRaw (John Ferlan)
- storage: Cleanup failures virStorageBackendCreateExecCommand (John Ferlan)
- storage: Fix setting mode in virStorageBackendCreateExecCommand (John Ferlan)
- Remove new lines from log messages (Jiri Denemark)
- qemu: Introduce cleanup label in qemuProcessStart (Jiri Denemark)
- qemu: Rename ret variable in qemuProcessStart (Jiri Denemark)
- qemu: Rename cleanup label in qemuProcessStart (Jiri Denemark)
So thanks everybody for helping with this release, be it with patches, ideas,
reports, documentation, etc...
As a reminder next release supposedly 1.3.1 will come mid-January due to the
end of year slowdown, and then 1.3.2 at the end or February.
Enjoy !
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
8 years, 11 months
[libvirt] [PATCH] virNetDevMacVLanTapSetup: Work around older systems
by Michal Privoznik
Some older systems, e.g. RHEL-6 do not have IFF_MULTI_QUEUE flag
which we use to enable multiqueue feature. Therefore one gets the
following compile error there:
CC util/libvirt_util_la-virnetdevmacvlan.lo
util/virnetdevmacvlan.c: In function 'virNetDevMacVLanTapSetup':
util/virnetdevmacvlan.c:338: error: 'IFF_MULTI_QUEUE' undeclared (first use in this function)
util/virnetdevmacvlan.c:338: error: (Each undeclared identifier is reported only once
util/virnetdevmacvlan.c:338: error: for each function it appears in.)
make[3]: *** [util/libvirt_util_la-virnetdevmacvlan.lo] Error 1
So, whenever user wants us to enable the feature on such systems,
we will just throw a runtime error instead.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/util/virnetdevmacvlan.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index d8d1d90..28c9f22 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -307,49 +307,57 @@ static int
virNetDevMacVLanTapSetup(int *tapfd, size_t tapfdSize, bool vnet_hdr, bool multiqueue)
{
unsigned int features;
struct ifreq ifreq;
short new_flags = 0;
size_t i;
for (i = 0; i < tapfdSize; i++) {
memset(&ifreq, 0, sizeof(ifreq));
if (ioctl(tapfd[i], TUNGETIFF, &ifreq) < 0) {
virReportSystemError(errno, "%s",
_("cannot get interface flags on macvtap tap"));
return -1;
}
new_flags = ifreq.ifr_flags;
if (vnet_hdr) {
if (ioctl(tapfd[i], TUNGETFEATURES, &features) < 0) {
virReportSystemError(errno, "%s",
_("cannot get feature flags on macvtap tap"));
return -1;
}
if (features & IFF_VNET_HDR)
new_flags |= IFF_VNET_HDR;
} else {
new_flags &= ~IFF_VNET_HDR;
}
+#ifdef IFF_MULTI_QUEUE
if (multiqueue)
new_flags |= IFF_MULTI_QUEUE;
else
new_flags &= ~IFF_MULTI_QUEUE;
+#else
+ if (multiqueue) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Multiqueue devices are not supported on this system"));
+ return -1;
+ }
+#endif
if (new_flags != ifreq.ifr_flags) {
ifreq.ifr_flags = new_flags;
if (ioctl(tapfd[i], TUNSETIFF, &ifreq) < 0) {
virReportSystemError(errno, "%s",
_("unable to set vnet or multiqueue flags on macvtap"));
return -1;
}
}
}
return 0;
}
--
2.4.10
8 years, 11 months
[libvirt] [PATCH] CVE-2015-5313: storage: don't allow '/' in filesystem volume names
by Eric Blake
The libvirt file system storage driver determines what file to
act on by concatenating the pool location with the volume name.
If a user is able to pick names like "../../../etc/passwd", then
they can escape the bounds of the pool. For that matter,
virStoragePoolListVolumes() doesn't descend into subdirectories,
so a user really shouldn't use a name with a slash.
Normally, only privileged users can coerce libvirt into creating
or opening existing files using the virStorageVol APIs; and such
users already have full privilege to create any domain XML (so it
is not an escalation of privilege). But in the case of
fine-grained ACLs, it is feasible that a user can be granted
storage_vol:create but not domain:write, and it violates
assumptions if such a user can abuse libvirt to access files
outside of the storage pool.
Therefore, prevent all use of volume names that contain "/",
whether or not such a name is actually attempting to escape the
pool.
This changes things from:
$ virsh vol-create-as default ../../../../../../etc/haha --capacity 128
Vol ../../../../../../etc/haha created
$ rm /etc/haha
to:
$ virsh vol-create-as default ../../../../../../etc/haha --capacity 128
error: Failed to create vol ../../../../../../etc/haha
error: Requested operation is not valid: volume name '../../../../../../etc/haha' cannot contain '/'
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
This has been reviewed on the libvirt security list, where it
was assigned a CVE. Fortunately, this could only be used for
an escalation of privileges under fine-grained ACLs (which is
not an out-of-the-box config).
I will go ahead and push this to master as well as all the
active maint branches back to the introduction of ACLs.
src/storage/storage_backend_fs.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index c71c724..bb3b62a 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1,7 +1,7 @@
/*
* storage_backend_fs.c: storage backend for FS and directory handling
*
- * Copyright (C) 2007-2014 Red Hat, Inc.
+ * Copyright (C) 2007-2015 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -1057,6 +1057,14 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
else
vol->type = VIR_STORAGE_VOL_FILE;
+ /* Volumes within a directory pools are not recursive; do not
+ * allow escape to ../ or a subdir */
+ if (strchr(vol->name, '/')) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("volume name '%s' cannot contain '/'"), vol->name);
+ return -1;
+ }
+
VIR_FREE(vol->target.path);
if (virAsprintf(&vol->target.path, "%s/%s",
pool->def->target.path,
--
2.4.3
8 years, 11 months
[libvirt] [PATCH] storage: Attempt to refresh volume after successful wipe volume
by John Ferlan
https://bugzilla.redhat.com/show_bug.cgi?id=1270709
When a volume wipe is successful, a volume refresh should be done afterwards
to update any volume data that may be used in future volume commands, such as
volume resize. For a raw file volume, a wipe would truncate the file and
a followup volume resize the capacity may fail because the volume target
allocation isn't updated to reflect the wipe activity.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/storage/storage_driver.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index bbf21f6..2e59e39 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2436,7 +2436,19 @@ storageVolWipePattern(virStorageVolPtr obj,
goto cleanup;
}
- ret = backend->wipeVol(obj->conn, pool, vol, algorithm, flags);
+ if ((ret = backend->wipeVol(obj->conn, pool, vol, algorithm, flags)) < 0)
+ goto cleanup;
+
+ /* Best effort to refresh the volume data. If unsuccessful, we've already
+ * wiped the data so there's no going back on that. Best we can do is
+ * provide some details over what happened and move on
+ */
+ if (backend->refreshVol &&
+ backend->refreshVol(obj->conn, pool, vol) < 0) {
+ VIR_WARN("failed to refresh volume '%s' info after volume wipe",
+ vol->name);
+ virResetLastError();
+ }
cleanup:
virStoragePoolObjUnlock(pool);
--
2.5.0
8 years, 11 months
[libvirt] [PATCH 00/10] VFIO fixes for PCI devices
by Andrea Bolognani
This series is my attempt at fixing
https://bugzilla.redhat.com/show_bug.cgi?id=1272300
In its current state, it's missing test cases covering the new
functionality[1] and it's known not to handle properly one
situation[2], but I'd like to get some feedback on my current
work and now that I have something to show for it feels like
a good time.
I'm already working on the missing bits and they will either
be included in the next revision or sent as separate series
later on.
The problem being solved is that, when using VFIO, IOMMU group
ownership can't be shared, eg. two devices that are in the
same IOMMU group can't be assigned to different guests, or to
the host and a guest. If that happens, the host will probably
crash.
The series deals with this issue by making sure safety
conditions are met before detaching devices from the host or
reattaching them to the host. In praticular, when we're asked
to reattach a device to the host but doing so would lead to
sharing IOMMU group ownership, we delay the operation until
we can guarantee this will not cause problems. As a nice side
effect of the changes we check for this when starting a guest
too, instead of assuming it will work and having QEMU error
out immediately afterwards.
Patches are organized as follows:
1-2: Minor cleanups that make implicit / confusing stuff
explicit / less confusing
3: Convert a string field used as an enumeration to a
proper enumeration
4: Introduce a simple helper function used later on
5-6: Rewrite the checks used when detaching devices from
the host. With this patches applied, the behaviour
is basically the same as before, except for the nice
little extra detailed above
7-9: Implement the delay when reattaching devices to the
host, thus preventing the crash and fixing the bug
10: Spit and polish
Cheers.
[1] Luckily, it doesn't break the existing tests either
[2] If you call 'virsh nodedev-reattach' on a device that's
assigned to a guest, libvirt won't stop you and you will
end up crashing your system
Andrea Bolognani (10):
pci: Remove redundant parameter from virPCIDeviceBindToStub()
pci: Remove 'reprobe' parameter from virPCIDeviceUnbind()
pci: Introduce virPCIStubDriver enumeration
pci: Introduce virPCIDeviceIOMMUGroupIterate()
hostdev: Simplify virHostdevIsPCIDeviceUsed()
hostdev: Check for safety before detaching VFIO devices
hostdev: Delay reattach of VFIO devices
hostdev: Clean up delayed VFIO devices
hostdev: Devices have already been marked as inactive
hostdev: Tidy up after changes to VFIO device handling
src/libvirt_private.syms | 3 +
src/libxl/libxl_driver.c | 3 +-
src/qemu/qemu_driver.c | 6 +-
src/util/virhostdev.c | 410 ++++++++++++++++++++++++++++++++++-------------
src/util/virpci.c | 125 +++++++++------
src/util/virpci.h | 26 ++-
src/xen/xen_driver.c | 3 +-
tests/virhostdevtest.c | 5 +-
tests/virpcitest.c | 35 ++--
9 files changed, 427 insertions(+), 189 deletions(-)
--
2.5.0
8 years, 11 months
[libvirt] [PATCH 0/6] Memory locking limit improvements
by Andrea Bolognani
As noticed by Peter[1], the memory locking limit for the
QEMU process is increased before assigning a VFIO device to
a guest, but it might not be decreased when returning said
device to the host.
This series fixes this inconsistent behaviour and cleans up
the code a little bit along the way.
The idea is to introduce a new, smarter function called
qemuDomainAdjustMaxMemLock() that does The Right Thing™ and
increases the limit when required, while at the same time
storing the original value. This way, when memory locking
is no longer needed, it can restore it.
I've tested this both on x86 and ppc64, both by removing
devices that were assigned in the domain XML and devices
that I had hotplugged.
Patches 1-2 lay some groundwork by allowing retrieval of
the memory locking limit for a process.
Patches 3-4 add qemuDomainAdjustMaxMemLock() and use it
where appropriate in the existing code.
Patch 5 adds one more use of the function, after a PCI
hostdev has been detached from the guest.
Patch 6 replaces the use of Mlock with MemLock. Suggestions
on how to further improve the names of those functions is
very welcome, this is just a first step in the right
direction.
Cheers.
[1] https://www.redhat.com/archives/libvir-list/2015-November/msg00642.html
Andrea Bolognani (6):
process: Allow virProcessPrLimit() to get current limit
process: Add virProcessGetMaxMemLock()
qemu: Add qemuDomainAdjustMaxMemLock()
qemu: Use qemuDomainAdjustMaxMemLock()
qemu: Reduce memlock limit after detaching hostdev
qemu: Replace Mlock with MemLock in function names
configure.ac | 2 +-
src/conf/domain_conf.h | 3 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 4 ++--
src/qemu/qemu_domain.c | 56 +++++++++++++++++++++++++++++++++++++++++++---
src/qemu/qemu_domain.h | 5 +++--
src/qemu/qemu_hotplug.c | 46 ++++++++++++++++----------------------
src/util/virprocess.c | 58 +++++++++++++++++++++++++++++++++++++++++++-----
src/util/virprocess.h | 2 ++
9 files changed, 136 insertions(+), 41 deletions(-)
--
2.5.0
8 years, 11 months
[libvirt] [PATCH] hypervisor driver for Jailhouse
by Christian Loehle
>From README:
The jailhouse hypervisor driver for the libvirt project aims to provide
rudimentary support for managing jailhouse with the libvirt library. The
main advantage of this is the possibility to use virt-manager as a GUI
to manage Jailhouse cells. Thus the driver is mainly built around the
API calls that virt-manager uses and needs.
Due to the concept of Jailhouse a lot of libvirt functions can't be
realized, so this driver isn't as full-featured as upstream drivers of
the libvirt project.
Currently the driver relies on the Jailhouse binary, which has to be
passed when connecting a libvirt client to it(e.g. virt-manager -c
jailhouse:///path/to/jailhouse/tools/jailhouse). This has the advantage
that remote support can be easily done by not passing the original
Jailhouse binary, but an executable that redirects its parameters
through ssh to the real Jailhouse binary and outputs that output. Be
aware though that the driver doesn't store any information about cells,
so most API calls use "jailhouse cell list" every time they're called to
get the current state.
I would like to get Jailhouse support upstream, any feedback is greatly
appreciated.
--
Christian Loehle
diff --git a/configure.ac b/configure.ac
index f481c50..8b68828 100644
--- a/configure.ac
+++ b/configure.ac
@@ -563,6 +563,10 @@ AC_ARG_WITH([hyperv],
[AS_HELP_STRING([--with-hyperv],
[add Hyper-V support @<:@default=check@:>@])])
m4_divert_text([DEFAULTS], [with_hyperv=check])
+AC_ARG_WITH([jailhouse],
+ [AS_HELP_STRING([--with-jailhouse],
+ [add Jailhouse support @<:@default=yes@:>@])])
+m4_divert_text([DEFAULTS], [with_jailhouse=yes])
AC_ARG_WITH([test],
[AS_HELP_STRING([--with-test],
[add test driver support @<:@default=yes@:>@])])
@@ -722,6 +726,16 @@ AM_CONDITIONAL([WITH_VMWARE], [test "$with_vmware"
= "yes"])
dnl
+dnl Checks for the Jailhouse driver
+dnl
+
+if test "$with_jailhouse" = "yes"; then
+ AC_DEFINE_UNQUOTED([WITH_JAILHOUSE], 1, [whether Jailhouse driver
is enabled])
+fi
+AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"])
+
+
+dnl
dnl check for XDR
dnl
@@ -1087,6 +1101,12 @@ dnl
LIBVIRT_DRIVER_CHECK_BHYVE
dnl
+dnl Checks for Jailhouse driver
+dnl
+
+AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"])
+
+dnl
dnl check for shell that understands <> redirection without truncation,
dnl needed by src/qemu/qemu_monitor_{text,json}.c.
dnl
@@ -2830,6 +2850,7 @@ AC_MSG_NOTICE([ ESX: $with_esx])
AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
LIBVIRT_DRIVER_RESULT_VZ
LIBVIRT_DRIVER_RESULT_BHYVE
+AC_MSG_NOTICE([Jailhouse: $with_jailhouse])
AC_MSG_NOTICE([ Test: $with_test])
AC_MSG_NOTICE([ Remote: $with_remote])
AC_MSG_NOTICE([ Network: $with_network])
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index f716cb9..c8fe2d3 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -127,6 +127,7 @@ typedef enum {
VIR_FROM_POLKIT = 60, /* Error from polkit code */
VIR_FROM_THREAD = 61, /* Error from thread utils */
VIR_FROM_ADMIN = 62, /* Error from admin backend */
+ VIR_FROM_JAILHOUSE = 63, /* Error from Jailhouse driver */
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_DOMAIN_LAST
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0cc5b99..2b144bf 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -59,6 +59,7 @@ src/hyperv/hyperv_wmi.c
src/interface/interface_backend_netcf.c
src/interface/interface_backend_udev.c
src/internal.h
+src/jailhouse/jailhouse_driver.c
src/libvirt.c
src/libvirt-admin.c
src/libvirt-domain.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 99b4993..10d59de 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -578,6 +578,7 @@ DRIVER_SOURCE_FILES = \
$(VMWARE_DRIVER_SOURCES) \
$(XEN_DRIVER_SOURCES) \
$(XENAPI_DRIVER_SOURCES) \
+ $(JAILHOUSE_DRIVER_SOURCES) \
$(NULL)
STATEFUL_DRIVER_SOURCE_FILES = \
@@ -860,6 +861,11 @@ BHYVE_DRIVER_SOURCES = \
bhyve/bhyve_utils.h \
$(NULL)
+JAILHOUSE_DRIVER_SOURCES = \
+ jailhouse/jailhouse_driver.c \
+ jailhouse/jailhouse_driver.h \
+ $(NULL)
+
NETWORK_DRIVER_SOURCES = \
network/bridge_driver.h network/bridge_driver.c \
network/bridge_driver_platform.h \
@@ -1436,6 +1442,14 @@ libvirt_driver_vz_la_LIBADD =
$(PARALLELS_SDK_LIBS) $(LIBNL_LIBS)
libvirt_driver_vz_la_SOURCES = $(VZ_DRIVER_SOURCES)
endif WITH_VZ
+if WITH_JAILHOUSE
+noinst_LTLIBRARIES += libvirt_driver_jailhouse.la
+libvirt_la_BUILT_LIBADD += libvirt_driver_jailhouse.la
+libvirt_driver_jailhouse_la_CFLAGS = \
+ -I$(srcdir)/conf $(AM_CFLAGS)
+libvirt_driver_jailhouse_la_SOURCES = $(JAILHOUSE_DRIVER_SOURCES)
+endif WITH_JAILHOUSE
+
if WITH_BHYVE
noinst_LTLIBRARIES += libvirt_driver_bhyve_impl.la
libvirt_driver_bhyve_la_SOURCES =
@@ -1801,6 +1815,7 @@ EXTRA_DIST += \
$(HYPERV_DRIVER_EXTRA_DIST) \
$(VZ_DRIVER_SOURCES) \
$(BHYVE_DRIVER_SOURCES) \
+ $(JAILHOUSE_DRIVER_SOURCES) \
$(NETWORK_DRIVER_SOURCES) \
$(INTERFACE_DRIVER_SOURCES) \
$(STORAGE_DRIVER_SOURCES) \
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2edf123..00d17e9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -121,7 +121,8 @@ VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
"phyp",
"parallels",
"bhyve",
- "vz")
+ "vz",
+ "jailhouse")
VIR_ENUM_IMPL(virDomainOS, VIR_DOMAIN_OSTYPE_LAST,
"hvm",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f10b534..27beef0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -225,6 +225,7 @@ typedef enum {
VIR_DOMAIN_VIRT_PARALLELS,
VIR_DOMAIN_VIRT_BHYVE,
VIR_DOMAIN_VIRT_VZ,
+ VIR_DOMAIN_VIRT_JAILHOUSE,
VIR_DOMAIN_VIRT_LAST
} virDomainVirtType;
diff --git a/src/jailhouse/README b/src/jailhouse/README
new file mode 100644
index 0000000..564cfbd
--- /dev/null
+++ b/src/jailhouse/README
@@ -0,0 +1,3 @@
+The jailhouse hypervisor driver for the libvirt project aims to provide
rudimentary support for managing jailhouse with the libvirt library. The
main advantage of this is the possibility to use virt-manager as a GUI
to manage Jailhouse cells. Thus the driver is mainly built around the
API calls that virt-manager uses and needs.
+Due to the concept of Jailhouse a lot of libvirt functions can't be
realized, so this driver isn't as full-featured as upstream drivers of
the libvirt project.
+Currently the driver relies on the Jailhouse binary, which has to be
passed when connecting a libvirt client to it(e.g. virt-manager -c
jailhouse:///path/to/jailhouse/tools/jailhouse). This has the advantage
that remote support can be easily done by not passing the original
Jailhouse binary, but an executable that redirects its parameters
through ssh to the real Jailhouse binary and outputs that output. Be
aware though that the driver doesn't store any information about cells,
so most API calls use "jailhouse cell list" every time they're called to
get the current state.
diff --git a/src/jailhouse/jailhouse_driver.c
b/src/jailhouse/jailhouse_driver.c
new file mode 100644
index 0000000..21acbba
--- /dev/null
+++ b/src/jailhouse/jailhouse_driver.c
@@ -0,0 +1,614 @@
+/*
+ * jailhouse_driver.c: hypervisor driver for managing Jailhouse cells
+ *
+ * Copyright (C) 2015 Linutronix GmbH
+ *
+ * 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/>.
+ *
+ * Author: Christian Loehle
+ */
+
+#include <config.h>
+#include <string.h>
+#include "jailhouse_driver.h"
+#include "datatypes.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virlog.h"
+#include "vircommand.h"
+#include "virxml.h"
+#include "configmake.h"
+#include "virfile.h"
+#include "virtypedparam.h"
+#include "virstring.h"
+#include "nodeinfo.h"
+
+#define VIR_FROM_THIS VIR_FROM_JAILHOUSE
+
+#define IDLENGTH 8
+#define NAMELENGTH 24
+#define STATELENGTH 16
+#define CPULENGTH 24
+#define STATERUNNING 0
+#define STATERUNNINGSTRING "running "
+#define STATERUNNINGLOCKED 1
+#define STATERUNNINGLOCKEDSTRING "running/locked "
+#define STATESHUTDOWN 2
+#define STATESHUTDOWNSTRING "shut down "
+#define STATEFAILED 3
+#define STATEFAILEDSTRING "failed "
+#define JAILHOUSEVERSIONOUTPUT "Jailhouse management tool"
+
+/*
+ * The driver requeries the cells on most calls, it stores the result
of the last query, so it can copy the UUIDs in the new query if the cell
is the same(otherwise it just generates a new one)
+ * not preserving the UUID results in a lot of bugs in libvirts clients.
+ */
+struct jailhouse_driver {
+ char *binary;
+ size_t lastQueryCellsCount;
+ struct jailhouse_cell* lastQueryCells;
+};
+
+/*
+ * CPUs are currently unused but this might change
+ */
+struct jailhouse_cell {
+ int id;
+ char name[NAMELENGTH+1];
+ int state;
+ int *assignedCPUs; //Don't use cpumask because remote system might
have different # of cpus
+ int assignedCPUsLength;
+ int *failedCPUs;
+ int failedCPUsLength;
+ unsigned char uuid[VIR_UUID_BUFLEN];
+};
+
+/*
+ * helper function that returns the number as an integer and sets i to
be the first char after the number
+ */
+static int
+charsToInt(char* chars, size_t *i)
+{
+ int result = 0;
+ while (chars[*i] != ',' && chars[*i] != '-' && chars[*i] != ' ') {
+ result *= 10;
+ result += chars[*i] - '0';
+ (*i)++;
+ }
+ return result;
+}
+
+/*
+ * Takes a string in the format of "jailhouse cell list" as input,
+ * allocates an int array in which every CPU is explicitly listed and
saves a pointer in cpusptr
+ */
+static size_t
+parseCPUs(char* output, int **cpusptr)
+{
+ size_t i;
+ size_t count = 1;
+ int number;
+ int* cpus;
+ if (output[0] == ' ') {
+ *cpusptr = NULL;
+ return 0;
+ }
+ for (i = 0; i<CPULENGTH; i++) {
+ number = charsToInt(output, &i);
+ if (output[i] == ',') {
+ count++;
+ } else if (output[i] == '-') {
+ i++;
+ count += charsToInt(output, &i) - number;
+ }
+ }
+ if (VIR_ALLOC_N(cpus, count)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to allocate CPUs array of size %zu"), count);
+ return 0;
+ }
+ size_t j = 0;
+ i = 0;
+ while (output[i] != ' ') {
+ number = charsToInt(output, &i);
+ if (output[i] == ',' || output[i] == ' ') {
+ cpus[j++] = number;
+ } else if (output[i] == '-') {
+ i++;
+ int nextNumber = charsToInt(output, &i);
+ for (; number <= nextNumber; number++) cpus[j++] = number;
+ }
+ i++;
+ }
+ *cpusptr = cpus;
+ return count;
+}
+
+/*
+ * calls "jailhouse cell list" and parses the output in an array of
jailhouse_cell
+ */
+static size_t
+parseListOutput(virConnectPtr conn, struct jailhouse_cell **parsedOutput)
+{
+ virCommandPtr cmd = virCommandNew(((struct jailhouse_driver
*)conn->privateData)->binary);
+ virCommandAddArg(cmd, "cell");
+ virCommandAddArg(cmd, "list");
+ virCommandAddEnvPassCommon(cmd);
+ char *output;
+ virCommandSetOutputBuffer(cmd, &output);
+ size_t count = -1; // Don't count table header line
+ size_t i = 0;
+ if (virCommandRun(cmd, NULL) < 0)
+ goto error;
+ while (output[i] != '\0') {
+ if (output[i] == '\n') count++;
+ i++;
+ }
+ if (VIR_ALLOC_N(*parsedOutput, count)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to allocate jailhouse_cell array of size
%zu"), count);
+ goto error;
+ }
+ if (*parsedOutput == NULL)
+ goto error;
+ i = 0;
+ size_t j;
+ while (output[i++] != '\n'); // Skip table header line
+ for (j = 0; j < count; j++) {
+ size_t k;
+ for (k = 0; k <= IDLENGTH; k++) // char after number needs to
be NUL for virStrToLong
+ if (output[i+k] == ' ') {
+ output[i+k] = '\0';
+ break;
+ }
+ char c = output[i+IDLENGTH];
+ output[i+IDLENGTH] = '\0'; // in case ID is 8 chars long, so
beginning of name won't get parsed
+ if (virStrToLong_i(output+i, NULL, 0, &(*parsedOutput)[j].id))
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to parse id to long: %s"), output+i);
+ output[i+IDLENGTH] = c;
+ i += IDLENGTH;
+ if (virStrncpy((*parsedOutput)[j].name, output+i, NAMELENGTH,
NAMELENGTH+1) == NULL)
+ // should never happen
+ goto error;
+ (*parsedOutput)[j].name[NAMELENGTH] = '\0';
+ for (k = 0; k < NAMELENGTH; k++)
+ if ((*parsedOutput)[j].name[k] == ' ')
+ break;
+ (*parsedOutput)[j].name[k] = '\0';
+ i += NAMELENGTH;
+ if (STREQLEN(output+i, STATERUNNINGSTRING, STATELENGTH))
(*parsedOutput)[j].state = STATERUNNING;
+ else if (STREQLEN(output+i, STATESHUTDOWNSTRING, STATELENGTH))
(*parsedOutput)[j].state = STATESHUTDOWN;
+ else if (STREQLEN(output+i, STATEFAILEDSTRING, STATELENGTH))
(*parsedOutput)[j].state = STATEFAILED;
+ else if (STREQLEN(output+i, STATERUNNINGLOCKEDSTRING,
STATELENGTH)) (*parsedOutput)[j].state = STATERUNNINGLOCKED;
+ i += STATELENGTH;
+ (*parsedOutput)[j].assignedCPUsLength = parseCPUs(output+i,
&((*parsedOutput)[j].assignedCPUs));
+ i += CPULENGTH;
+ (*parsedOutput)[j].failedCPUsLength = parseCPUs(output+i,
&((*parsedOutput)[j].failedCPUs));
+ i += CPULENGTH;
+ i++; // skip \n
+ }
+ VIR_FREE(output);
+ return count;
+ error:
+ for (i = 0; i < count; i++) {
+ VIR_FREE((*parsedOutput)[i].assignedCPUs);
+ VIR_FREE((*parsedOutput)[i].failedCPUs);
+ }
+ VIR_FREE(*parsedOutput);
+ *parsedOutput = NULL;
+ VIR_FREE(output);
+ output = NULL;
+ return -1;
+}
+
+/*
+ * Returns the libvirts equivalent of the cell state passed to it
+ */
+static virDomainState
+cellToVirDomainState(struct jailhouse_cell *cell)
+{
+ switch (cell->state) {
+ case STATERUNNING: return VIR_DOMAIN_RUNNING;
+ case STATERUNNINGLOCKED: return VIR_DOMAIN_RUNNING;
+ case STATESHUTDOWN: return VIR_DOMAIN_SHUTOFF;
+ case STATEFAILED: return VIR_DOMAIN_CRASHED;
+ default: return VIR_DOMAIN_NOSTATE;
+ }
+}
+
+/*
+ * Returns a new virDomainPtr filled with the data of the jailhouse_cell
+ */
+static virDomainPtr
+cellToVirDomainPtr(virConnectPtr conn, struct jailhouse_cell *cell)
+{
+ virDomainPtr dom = virGetDomain(conn, cell->name, cell->uuid);
+ dom->id = cell->id;
+ return dom;
+}
+
+/*
+ * Check cells for cell and copies UUID if found, otherwise generates
a new one, this is to preserve UUID in libvirt
+ */
+static void setUUID(struct jailhouse_cell *cells, size_t count, struct
jailhouse_cell* cell) {
+ size_t i;
+ for (i = 0; i < count; i++) {
+ if (strncmp(cells[i].name, cell->name, NAMELENGTH+1))
+ continue;
+ memcpy(cell->uuid, cells[i].uuid, VIR_UUID_BUFLEN);
+ return;
+ }
+ virUUIDGenerate(cell->uuid);
+}
+
+/*
+ * Frees the old list of cells, gets the new one and preserves UUID if
cells were present in the old
+ */
+static void
+getCurrentCellList(virConnectPtr conn)
+{
+ size_t lastCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ struct jailhouse_cell *lastCells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ struct jailhouse_cell *cells = NULL;
+ size_t i;
+ size_t count = parseListOutput(conn, &cells);
+ for (i = 0; i < count; i++)
+ setUUID(lastCells, lastCount, cells+i);
+ for (i = 0; i < lastCount; i++) {
+ VIR_FREE(lastCells[i].assignedCPUs);
+ VIR_FREE(lastCells[i].failedCPUs);
+ }
+ VIR_FREE(lastCells);
+ ((struct jailhouse_driver *)conn->privateData)->lastQueryCells = cells;
+ ((struct jailhouse_driver *)conn->privateData)->lastQueryCellsCount
= count;
+}
+
+/*
+ * Converts libvirts virDomainPtr to the internal jailhouse_cell by
parsing the "jailhouse cell list" output
+ * and looking up the name of the virDomainPtr, returns NULL if cell
is no longer present
+ */
+static struct jailhouse_cell *
+virDomainPtrToCell(virDomainPtr dom)
+{
+ getCurrentCellList(dom->conn);
+ size_t cellsCount = ((struct jailhouse_driver
*)dom->conn->privateData)->lastQueryCellsCount;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)dom->conn->privateData)->lastQueryCells;
+ size_t i;
+ for (i = 0; i < cellsCount; i++)
+ if (dom->id == cells[i].id)
+ return cells+i;
+ return NULL;
+}
+
+static virDrvOpenStatus
+jailhouseConnectOpen(virConnectPtr conn, virConnectAuthPtr auth
ATTRIBUTE_UNUSED, unsigned int flags)
+{
+ virCheckFlags(0, VIR_DRV_OPEN_ERROR);
+ if (conn->uri->scheme == NULL ||
+ STRNEQ(conn->uri->scheme, "jailhouse"))
+ return VIR_DRV_OPEN_DECLINED;
+ char* binary;
+ if (conn->uri->path == NULL) {
+ if (VIR_STRDUP(binary, "jailhouse") != 1)
+ return VIR_DRV_OPEN_ERROR;
+ } else {
+ if (!virFileIsExecutable(conn->uri->path)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Path '%s', is not a valid executable file."),
+ conn->uri->path);
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (VIR_STRDUP(binary, conn->uri->path) != 1)
+ return VIR_DRV_OPEN_ERROR;
+ }
+ virCommandPtr cmd = virCommandNew(binary);
+ virCommandAddArg(cmd, "--version");
+ virCommandAddEnvPassCommon(cmd);
+ char *output;
+ virCommandSetOutputBuffer(cmd, &output);
+ if (virCommandRun(cmd, NULL) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Executing '%s --version' failed."),
+ conn->uri->path);
+ VIR_FREE(output);
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (STRNEQLEN(JAILHOUSEVERSIONOUTPUT, output,
strlen(JAILHOUSEVERSIONOUTPUT))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%s doesn't seem to be a correct Jailhouse
binary."),
+ conn->uri->path);
+ VIR_FREE(output);
+ return VIR_DRV_OPEN_ERROR;
+ }
+ VIR_FREE(output);
+ struct jailhouse_driver *driver;
+ if (VIR_ALLOC(driver))
+ return VIR_DRV_OPEN_ERROR;
+ driver->binary = binary;
+ driver->lastQueryCells = NULL;
+ driver->lastQueryCellsCount = 0;
+ conn->privateData = driver;
+ return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int
+jailhouseConnectClose(virConnectPtr conn)
+{
+ size_t i;
+ size_t cellsCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ for (i = 0; i < cellsCount; i++) {
+ VIR_FREE(cells[i].assignedCPUs);
+ VIR_FREE(cells[i].failedCPUs);
+ }
+ VIR_FREE(cells);
+ VIR_FREE(((struct jailhouse_driver *)conn->privateData)->binary);
+ VIR_FREE(conn->privateData);
+ conn->privateData = NULL;
+ return 0;
+}
+
+static int
+jailhouseConnectNumOfDomains(virConnectPtr conn)
+{
+ getCurrentCellList(conn);
+ return ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+}
+
+static int
+jailhouseConnectListDomains(virConnectPtr conn, int * ids, int maxids)
+{
+ getCurrentCellList(conn);
+ size_t cellsCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ size_t i;
+ for (i = 0; i < maxids && i < cellsCount; i++)
+ ids[i] = cells[i].id;
+ return i;
+}
+
+static int
+jailhouseConnectListAllDomains(virConnectPtr conn, virDomainPtr **
domains, unsigned int flags)
+{
+ virCheckFlags(VIR_CONNECT_LIST_DOMAINS_ACTIVE, 0);
+ getCurrentCellList(conn);
+ size_t cellsCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ if (cellsCount == -1)
+ goto error;
+ if (VIR_ALLOC_N(*domains, cellsCount+1)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to allocate virDomainPtr array of size
%zu"), cellsCount+1);
+ goto error;
+ }
+ size_t i;
+ for (i = 0; i < cellsCount; i++)
+ (*domains)[i] = cellToVirDomainPtr(conn, cells+i);
+ (*domains)[cellsCount] = NULL;
+ return cellsCount;
+ error:
+ *domains = NULL;
+ return -1;
+}
+
+static virDomainPtr
+jailhouseDomainLookupByID(virConnectPtr conn, int id)
+{
+ getCurrentCellList(conn);
+ size_t cellsCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ if (cellsCount == -1)
+ return NULL;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ size_t i;
+ for (i = 0; i < cellsCount; i++)
+ if (cells[i].id == id)
+ return cellToVirDomainPtr(conn, cells+i);
+ virReportError(VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+}
+
+static virDomainPtr
+jailhouseDomainLookupByName(virConnectPtr conn, const char *lookupName)
+{
+ getCurrentCellList(conn);
+ size_t cellsCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ if (cellsCount == -1)
+ return NULL;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ size_t i;
+ for (i = 0; i < cellsCount; i++)
+ if (STREQ(cells[i].name, lookupName))
+ return cellToVirDomainPtr(conn, cells+i);
+ virReportError(VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+}
+
+static virDomainPtr
+jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char * uuid)
+{
+ getCurrentCellList(conn);
+ size_t cellsCount = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCellsCount;
+ if (cellsCount == -1)
+ return NULL;
+ struct jailhouse_cell *cells = ((struct jailhouse_driver
*)conn->privateData)->lastQueryCells;
+ size_t i;
+ for (i = 0; i < cellsCount; i++)
+ if (memcmp(cells[i].uuid, (const char*)uuid, VIR_UUID_BUFLEN) == 0)
+ return cellToVirDomainPtr(conn, cells+i);
+ virReportError(VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+}
+
+/*
+ * There currently is no straightforward way for the driver to
retrieve those,
+ * so maxMem, memory and cpuTime have dummy values
+ */
+static int
+jailhouseDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+ struct jailhouse_cell *cell = virDomainPtrToCell(domain);
+ if (cell == NULL)
+ return -1;
+ info->state = cellToVirDomainState(cell);
+ info->maxMem = 1;
+ info->memory = 1;
+ info->nrVirtCpu = cell->assignedCPUsLength;
+ info->cpuTime = 1;
+ return 0;
+}
+
+static int
+jailhouseDomainGetState(virDomainPtr domain, int *state,
+ int *reason ATTRIBUTE_UNUSED, unsigned int flags)
+{
+ virCheckFlags(0, 0);
+ struct jailhouse_cell *cell = virDomainPtrToCell(domain);
+ if (cell == NULL)
+ return -1;
+ *state = cellToVirDomainState(cell);
+ return 0;
+}
+
+static int
+jailhouseDomainShutdown(virDomainPtr domain)
+{
+ virCommandPtr cmd = virCommandNew(((struct jailhouse_driver
*)domain->conn->privateData)->binary);
+ virCommandAddArg(cmd, "cell");
+ virCommandAddArg(cmd, "shutdown");
+ char buf[IDLENGTH+1];
+ snprintf(buf, IDLENGTH+1, "%d", domain->id);
+ virCommandAddArg(cmd, buf);
+ virCommandAddEnvPassCommon(cmd);
+ int resultcode = virCommandRun(cmd, NULL);
+ if (resultcode < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * CAREFUL, this is the Jailhouse destroy, not the libvirt destroy,
cell will be deleted and would need to be created and loaded again.
+ * This is implemented anyway, so libvirt clients have an option to
use jailhouse destroy too.
+ */
+static int
+jailhouseDomainDestroy(virDomainPtr domain)
+{
+ virCommandPtr cmd = virCommandNew(((struct jailhouse_driver
*)domain->conn->privateData)->binary);
+ virCommandAddArg(cmd, "cell");
+ virCommandAddArg(cmd, "destroy");
+ char buf[IDLENGTH+1];
+ snprintf(buf, IDLENGTH+1, "%d", domain->id);
+ virCommandAddArg(cmd, buf);
+ virCommandAddEnvPassCommon(cmd);
+ int resultcode = virCommandRun(cmd, NULL);
+ if (resultcode < 0)
+ return -1;
+ return 0;
+}
+
+static int
+jailhouseDomainCreate(virDomainPtr domain)
+{
+ virCommandPtr cmd = virCommandNew(((struct jailhouse_driver
*)domain->conn->privateData)->binary);
+ virCommandAddArg(cmd, "cell");
+ virCommandAddArg(cmd, "start");
+ char buf[IDLENGTH+1];
+ snprintf(buf, IDLENGTH+1, "%d", domain->id);
+ virCommandAddArg(cmd, buf);
+ virCommandAddEnvPassCommon(cmd);
+ int resultcode = virCommandRun(cmd, NULL);
+ if (resultcode < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * There currently is no reason why it shouldn't be
+ */
+static int
+jailhouseConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+static int
+jailhouseNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
virNodeInfoPtr info)
+{
+ return nodeGetInfo(NULL, info);
+}
+
+/*
+ * Returns a dummy capabilities XML for virt-manager
+ */
+static char *
+jailhouseConnectGetCapabilities(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ char* caps;
+ if (VIR_STRDUP(caps, "<capabilities></capabilities>") != 1)
+ return NULL;
+ return caps;
+}
+
+/*
+ * Returns a dummy XML for virt-manager
+ */
+static char *
+jailhouseDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
+{
+ virCheckFlags(0, NULL);
+ char buf[200];
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ virDomainGetUUIDString(domain, uuid);
+ snprintf(buf, 200, "<domain type =\"jailhouse\">\n\
+ <name>%s</name>\n\
+ <uuid>%s</uuid>\n\
+ </domain>", domain->name, uuid);
+ char* result;
+ if (VIR_STRDUP(result, buf) != 1)
+ return NULL;
+ return result;
+}
+
+static virHypervisorDriver jailhouseHypervisorDriver = {
+ .name = "jailhouse",
+ .connectOpen = jailhouseConnectOpen, /* 1.2.22 */
+ .connectClose = jailhouseConnectClose, /* 1.2.22 */
+ .connectGetCapabilities = jailhouseConnectGetCapabilities, /* 1.2.22 */
+ .connectNumOfDomains = jailhouseConnectNumOfDomains, /* 1.2.22 */
+ .connectListDomains = jailhouseConnectListDomains, /* 1.2.22 */
+ .connectIsAlive = jailhouseConnectIsAlive, /* 1.2.22 */
+ .connectListAllDomains = jailhouseConnectListAllDomains, /* 1.2.22 */
+ .domainLookupByID = jailhouseDomainLookupByID, /* 1.2.22 */
+ .domainLookupByName = jailhouseDomainLookupByName, /* 1.2.22 */
+ .domainLookupByUUID = jailhouseDomainLookupByUUID, /* 1.2.22 */
+ .domainGetInfo = jailhouseDomainGetInfo, /* 1.2.22 */
+ .domainGetState = jailhouseDomainGetState, /* 1.2.22 */
+ .domainGetXMLDesc = jailhouseDomainGetXMLDesc, /* 1.2.22 */
+ .domainShutdown = jailhouseDomainShutdown, /* 1.2.22 */
+ .domainDestroy = jailhouseDomainDestroy, /* 1.2.22 */
+ .domainCreate = jailhouseDomainCreate, /* 1.2.22 */
+ .nodeGetInfo = jailhouseNodeGetInfo /* 1.2.22 */
+};
+
+static virConnectDriver jailhouseConnectDriver = {
+ .hypervisorDriver = &jailhouseHypervisorDriver,
+};
+
+int
+jailhouseRegister(void)
+{
+ return virRegisterConnectDriver(&jailhouseConnectDriver,
+ false);
+}
diff --git a/src/jailhouse/jailhouse_driver.h
b/src/jailhouse/jailhouse_driver.h
new file mode 100644
index 0000000..47c17e7
--- /dev/null
+++ b/src/jailhouse/jailhouse_driver.h
@@ -0,0 +1,28 @@
+/*
+ * jailhouse_driver.h: hypervisor driver for managing Jailhouse cells
+ *
+ * Copyright (C) 2015 Linutronix GmbH
+ *
+ * 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/>.
+ *
+ * Author: Christian Loehle
+ */
+
+#ifndef JAILHOUSE_DRIVER_H
+# define JAILHOUSE_DRIVER_H
+
+int jailhouseRegister(void);
+
+#endif
diff --git a/src/libvirt.c b/src/libvirt.c
index 25a0040..7626353 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -98,6 +98,9 @@
#ifdef WITH_BHYVE
# include "bhyve/bhyve_driver.h"
#endif
+#ifdef WITH_JAILHOUSE
+# include "jailhouse/jailhouse_driver.h"
+#endif
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -437,12 +440,17 @@ virGlobalInit(void)
if (vzRegister() == -1)
goto error;
# endif
+#ifdef WITH_JAILHOUSE
+ if (jailhouseRegister() == -1)
+ goto error;
+#endif
#endif
#ifdef WITH_REMOTE
if (remoteRegister() == -1)
goto error;
#endif
+
return;
error:
@@ -1167,6 +1175,9 @@ do_open(const char *name,
#ifndef WITH_VZ
STRCASEEQ(ret->uri->scheme, "parallels") ||
#endif
+#ifndef WITH_JAILHOUSE
+ STRCASEEQ(ret->uri->scheme, "jailhouse") ||
+#endif
false)) {
virReportErrorHelper(VIR_FROM_NONE, VIR_ERR_CONFIG_UNSUPPORTED,
__FILE__, __FUNCTION__, __LINE__,
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 6dc05f4..0d480c0 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -134,6 +134,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
"Polkit", /* 60 */
"Thread jobs",
"Admin Interface",
+ "Jailhouse Driver",
)
8 years, 11 months