[libvirt PATCHv2 5/5] qemu: implement virtiofs hotunplug

2021-10-06 Thread Ján Tomko
Signed-off-by: Ján Tomko 
---
 src/conf/domain_conf.c   | 24 +++
 src/conf/domain_conf.h   |  2 +
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_hotplug.c  | 87 +++-
 4 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b8370f6950..057dbf91a5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -28829,6 +28829,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 c23c233184..1fcef7b0e1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3757,6 +3757,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 fd0eea0777..687a3bbc4c 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 73e5a39852..0947243c16 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5183,6 +5183,51 @@ 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) {
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("only virtiofs filesystems can be hotplugged"));
+return -1;
+}
+
+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)
+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,
@@ -5221,6 +5266,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:
@@ -5228,7 +5277,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:
@@ -5326,9 +5374,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_DEVI

Re: [libvirt PATCHv2 5/5] qemu: implement virtiofs hotunplug

2021-10-07 Thread Peter Krempa
On Wed, Oct 06, 2021 at 12:20:23 +0200, Ján Tomko wrote:
> Signed-off-by: Ján Tomko 
> ---
>  src/conf/domain_conf.c   | 24 +++
>  src/conf/domain_conf.h   |  2 +
>  src/libvirt_private.syms |  1 +
>  src/qemu/qemu_hotplug.c  | 87 +++-
>  4 files changed, 112 insertions(+), 2 deletions(-)
> 
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index b8370f6950..057dbf91a5 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -28829,6 +28829,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 c23c233184..1fcef7b0e1 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -3757,6 +3757,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 fd0eea0777..687a3bbc4c 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 73e5a39852..0947243c16 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -5183,6 +5183,51 @@ 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) {
> +virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> +   _("only virtiofs filesystems can be hotplugged"));
> +return -1;
> +}

This is not really what I meant. This function is called after the
device was already unplugged so this check here is nonsensical.

If I start qemu with a p9fs


  
  
  
  


which results into:

-fsdev local,security_model=mapped,id=fsdev-fs0,path=/tmp \
-device virtio-9p-pci,id=fs0,fsdev=fsdev-fs0,mount_tag=asdf,bus=pci.0,addr=0xd \

And I then unplug it, either from the guest or via 'virsh
qemu-monitor-command' I then still get the 'DEVICE_DELETED' event:

2021-10-07 07:54:11.376+: 2851053: debug : qemuMonitorJSONIOProcessLine:222 
: Line [{"timestamp": {"seconds": 1633593251, "microseconds": 376384}, "event": 
"DEVICE_DELETED", "data": {"path": "/machine/peripheral/fs0/virtio-backend"}}]

So the device clearly can be unplugged and the error message is simply
a lie.

While the 'fsdev' part probably can't be unplugged and thus we probably
can't do anything about it, the device frontend was already deleted and
thus we should remove it from the XML.