[libvirt PATCHv3 2/2] qemu: implement virtiofs hotunplug

Ján Tomko jtomko at redhat.com
Tue Oct 12 12:14:44 UTC 2021


Signed-off-by: Ján Tomko <jtomko at redhat.com>
---
 src/conf/domain_conf.c   | 24 ++++++++++++
 src/conf/domain_conf.h   |  2 +
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_hotplug.c  | 83 +++++++++++++++++++++++++++++++++++++++-
 4 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4799070bc4..db42918d79 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -28918,6 +28918,30 @@ virDomainFSRemove(virDomainDef *def, size_t i)
     return fs;
 }
 
+ssize_t
+virDomainFSDefFind(virDomainDef *def,
+                   virDomainFSDef *fs)
+{
+    size_t i = 0;
+
+    for (i = 0; i < def->nfss; i++) {
+        virDomainFSDef *tmp = def->fss[i];
+
+        if (fs->dst && STRNEQ_NULLABLE(fs->dst, tmp->dst))
+            continue;
+
+        if (fs->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+            !virDomainDeviceInfoAddressIsEqual(&fs->info, &tmp->info))
+            continue;
+
+        if (fs->info.alias && STRNEQ_NULLABLE(fs->info.alias, tmp->info.alias))
+            continue;
+
+        return i;
+    }
+    return -1;
+}
+
 virDomainFSDef *
 virDomainGetFilesystemForTarget(virDomainDef *def,
                                 const char *target)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c1871b1757..79a27a0a36 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3765,6 +3765,8 @@ virDomainFSDef *virDomainGetFilesystemForTarget(virDomainDef *def,
 int virDomainFSInsert(virDomainDef *def, virDomainFSDef *fs);
 int virDomainFSIndexByName(virDomainDef *def, const char *name);
 virDomainFSDef *virDomainFSRemove(virDomainDef *def, size_t i);
+ssize_t virDomainFSDefFind(virDomainDef *def,
+                           virDomainFSDef *fs);
 
 unsigned int virDomainVideoDefaultRAM(const virDomainDef *def,
                                       const virDomainVideoType type);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 516b3692b2..c5d788285e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -410,6 +410,7 @@ virDomainFeatureTypeFromString;
 virDomainFeatureTypeToString;
 virDomainFSAccessModeTypeToString;
 virDomainFSCacheModeTypeToString;
+virDomainFSDefFind;
 virDomainFSDefFree;
 virDomainFSDefNew;
 virDomainFSDriverTypeToString;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 5289b57f04..b113a5bc1e 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5206,6 +5206,47 @@ qemuDomainRemoveRedirdevDevice(virQEMUDriver *driver,
 }
 
 
+static int
+qemuDomainRemoveFSDevice(virQEMUDriver *driver,
+                         virDomainObj *vm,
+                         virDomainFSDef *fs)
+{
+    g_autofree char *charAlias = NULL;
+    qemuDomainObjPrivate *priv = vm->privateData;
+    ssize_t idx;
+    int rc = 0;
+
+    VIR_DEBUG("Removing FS device %s from domain %p %s",
+              fs->info.alias, vm, vm->def->name);
+
+    if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
+        charAlias = qemuDomainGetVhostUserChrAlias(fs->info.alias);
+
+        qemuDomainObjEnterMonitor(driver, vm);
+
+        if (qemuMonitorDetachCharDev(priv->mon, charAlias) < 0)
+            rc = -1;
+
+        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            return -1;
+    }
+
+    virDomainAuditFS(vm, fs, NULL, "detach", rc == 0);
+
+    if (rc < 0)
+        return -1;
+
+    if (!fs->sock && fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS)
+        qemuVirtioFSStop(driver, vm, fs);
+
+    if ((idx = virDomainFSDefFind(vm->def, fs)) >= 0)
+        virDomainFSRemove(vm->def, idx);
+    qemuDomainReleaseDeviceAddress(vm, &fs->info);
+    virDomainFSDefFree(fs);
+    return 0;
+}
+
+
 static void
 qemuDomainRemoveAuditDevice(virDomainObj *vm,
                             virDomainDeviceDef *detach,
@@ -5244,6 +5285,10 @@ qemuDomainRemoveAuditDevice(virDomainObj *vm,
         virDomainAuditRedirdev(vm, detach->data.redirdev, "detach", success);
         break;
 
+    case VIR_DOMAIN_DEVICE_FS:
+        virDomainAuditFS(vm, detach->data.fs, NULL, "detach", success);
+        break;
+
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_CONTROLLER:
     case VIR_DOMAIN_DEVICE_WATCHDOG:
@@ -5251,7 +5296,6 @@ qemuDomainRemoveAuditDevice(virDomainObj *vm,
         /* These devices don't have associated audit logs */
         break;
 
-    case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_SOUND:
     case VIR_DOMAIN_DEVICE_VIDEO:
     case VIR_DOMAIN_DEVICE_GRAPHICS:
@@ -5349,9 +5393,13 @@ qemuDomainRemoveDevice(virQEMUDriver *driver,
             return -1;
         break;
 
+    case VIR_DOMAIN_DEVICE_FS:
+        if (qemuDomainRemoveFSDevice(driver, vm, dev->data.fs) < 0)
+            return -1;
+        break;
+
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_LEASE:
-    case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_SOUND:
     case VIR_DOMAIN_DEVICE_VIDEO:
     case VIR_DOMAIN_DEVICE_GRAPHICS:
@@ -6046,6 +6094,31 @@ qemuDomainDetachPrepVsock(virDomainObj *vm,
 }
 
 
+static int
+qemuDomainDetachPrepFS(virDomainObj *vm,
+                       virDomainFSDef *match,
+                       virDomainFSDef **detach)
+{
+    ssize_t idx;
+
+    if ((idx = virDomainFSDefFind(vm->def, match)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("matching filesystem not found"));
+        return -1;
+    }
+
+    if (vm->def->fss[idx]->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("only virtiofs filesystems can be hotplugged"));
+        return -1;
+    }
+
+    *detach = vm->def->fss[idx];
+
+    return 0;
+}
+
+
 static int
 qemuDomainDetachDeviceLease(virQEMUDriver *driver,
                             virDomainObj *vm,
@@ -6167,6 +6240,12 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
         break;
 
     case VIR_DOMAIN_DEVICE_FS:
+        if (qemuDomainDetachPrepFS(vm, match->data.fs,
+                                   &detach.data.fs) < 0) {
+            return -1;
+        }
+        break;
+
     case VIR_DOMAIN_DEVICE_SOUND:
     case VIR_DOMAIN_DEVICE_VIDEO:
     case VIR_DOMAIN_DEVICE_GRAPHICS:
-- 
2.31.1




More information about the libvir-list mailing list