Signed-off-by: Ján Tomko <jtomko(a)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