[PATCH v2 3/3] qemu: Setup host side of VDPA device for block copy

2023-10-26 Thread Peter Krempa
Setup the VDPA bits of the appropriate part of the image chain for block
copy.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c  |  4 
 src/qemu/qemu_driver.c | 12 
 2 files changed, 16 insertions(+)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 41038fb994..42c12a5e9b 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -23,6 +23,7 @@
 #include "qemu_domain.h"
 #include "qemu_alias.h"
 #include "qemu_security.h"
+#include "qemu_process.h"

 #include "storage_source.h"
 #include "viralloc.h"
@@ -3675,6 +3676,9 @@ qemuBlockPivot(virDomainObj *vm,
 virQEMUCapsGet(priv->qemuCaps, 
QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY) &&
 virStorageSourceHasBacking(disk->mirror)) {

+if (qemuProcessPrepareHostStorageSourceChain(vm, 
disk->mirror->backingStore) < 0)
+return -1;
+
 if (!(chainattachdata = 
qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->mirror->backingStore)))
 return -1;

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 86da8da777..d00d2a27c6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14290,10 +14290,16 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
 if (virQEMUCapsGet(priv->qemuCaps, 
QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY)) {
 g_autoptr(virStorageSource) terminator = virStorageSourceNew();

+if (qemuProcessPrepareHostStorageSource(vm, mirror) < 0)
+goto endjob;
+
 if (!(data = 
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror,
  
terminator)))
 goto endjob;
 } else {
+if (qemuProcessPrepareHostStorageSourceChain(vm, mirror) < 0)
+goto endjob;
+
 if (!(data = 
qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror)))
 goto endjob;
 }
@@ -14308,6 +14314,9 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
 if (mirror_shallow) {
 /* if external backing store is populated we'll need to open it */
 if (virStorageSourceHasBacking(mirror)) {
+if (qemuProcessPrepareHostStorageSourceChain(vm, 
mirror->backingStore) < 0)
+goto endjob;
+
 if (!(data = 
qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror->backingStore)))
 goto endjob;

@@ -14321,6 +14330,9 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
 mirrorBacking = mirror->backingStore;
 }

+if (qemuProcessPrepareHostStorageSource(vm, mirror) < 0)
+goto endjob;
+
 if (!(crdata = 
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror,

mirrorBacking)))
 goto endjob;
-- 
2.41.0



[PATCH v2 1/3] qemu: process: Extract host setup of disk device into helpers

2023-10-26 Thread Peter Krempa
Currently the code sets up only VDPA backends but will be used later in
hotplug code too.

This patch also uses normal forward iteration in the loop in
qemuProcessPrepareHostStorage as we don't need to remove disks from the
disk list at that point.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_process.c | 76 -
 src/qemu/qemu_process.h |  7 
 2 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 63c0c62a46..1ef032dbd2 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6777,6 +6777,69 @@ qemuProcessPrepareHostStorageSourceVDPA(virStorageSource 
*src,
 }


+/**
+ * See qemuProcessPrepareHostStorageSourceChain
+ */
+int
+qemuProcessPrepareHostStorageSource(virDomainObj *vm,
+virStorageSource *src)
+{
+/* connect to any necessary vdpa block devices */
+if (qemuProcessPrepareHostStorageSourceVDPA(src, vm->privateData) < 0)
+return -1;
+
+return 0;
+}
+
+
+/**
+ * qemuProcessPrepareHostStorageSourceChain:
+ *
+ * @vm: domain object
+ * @chain: source chain
+ *
+ * Prepare the host side of a disk for use with the VM. Note that this function
+ * accesses host resources.
+ */
+int
+qemuProcessPrepareHostStorageSourceChain(virDomainObj *vm,
+ virStorageSource *chain)
+{
+virStorageSource *n;
+
+for (n = chain; virStorageSourceIsBacking(n); n = n->backingStore) {
+if (qemuProcessPrepareHostStorageSource(vm, n) < 0)
+return -1;
+}
+
+return 0;
+}
+
+
+/**
+ * qemuProcessPrepareHostStorageDisk:
+ *
+ * @vm: domain object
+ * @disk: disk definition object
+ *
+ * Prepare the host side of a disk for use with the VM. Note that this function
+ * accesses host resources.
+ *
+ * Note that this function does not call qemuDomainDetermineDiskChain as that 
is
+ * needed in qemuProcessPrepareHostStorage to remove disks based on the startup
+ * policy, thus other callers need to call it explicitly.
+ */
+int
+qemuProcessPrepareHostStorageDisk(virDomainObj *vm,
+  virDomainDiskDef *disk)
+{
+if (qemuProcessPrepareHostStorageSourceChain(vm, disk->src) < 0)
+return -1;
+
+return 0;
+}
+
+
 static int
 qemuProcessPrepareHostStorage(virQEMUDriver *driver,
   virDomainObj *vm,
@@ -6813,16 +6876,11 @@ qemuProcessPrepareHostStorage(virQEMUDriver *driver,
 return -1;
 }

-/* connect to any necessary vdpa block devices */
-for (i = vm->def->ndisks; i > 0; i--) {
-size_t idx = i - 1;
-virDomainDiskDef *disk = vm->def->disks[idx];
-virStorageSource *src;
+for (i = 0; i < vm->def->ndisks; i++) {
+virDomainDiskDef *disk = vm->def->disks[i];

-for (src = disk->src; virStorageSourceIsBacking(src); src = 
src->backingStore) {
-if (qemuProcessPrepareHostStorageSourceVDPA(src, vm->privateData) 
< 0)
-return -1;
-}
+if (qemuProcessPrepareHostStorageDisk(vm, disk) < 0)
+return -1;
 }

 return 0;
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index ef05b46892..c1ea949215 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -133,6 +133,13 @@ int qemuProcessPrepareHost(virQEMUDriver *driver,
virDomainObj *vm,
unsigned int flags);

+int qemuProcessPrepareHostStorageSource(virDomainObj *vm,
+virStorageSource *src);
+int qemuProcessPrepareHostStorageSourceChain(virDomainObj *vm,
+ virStorageSource *chain);
+int qemuProcessPrepareHostStorageDisk(virDomainObj *vm,
+  virDomainDiskDef *disk);
+
 int qemuProcessDeleteThreadContext(virDomainObj *vm);

 int qemuProcessLaunch(virConnectPtr conn,
-- 
2.41.0



[PATCH v2 2/3] qemu: hotplug: Setup host side of VDPA device for disk hotplug

2023-10-26 Thread Peter Krempa
The code which opens the VDPA device and prepares it for FD passing was
not called in the hotplug code path, preventing hotplug of VDPA disks
with:

 error: internal error: argument key 'path' must not have null value

Use the new helper qemuProcessPrepareHostStorageDisk to setup the VDPA
definition.

Closes: https://gitlab.com/libvirt/libvirt/-/issues/539
Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_hotplug.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1f7f5bdd26..fec7c4be4e 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1007,6 +1007,9 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver 
*driver,
 if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL) < 0)
 goto cleanup;

+if (qemuProcessPrepareHostStorageDisk(vm, disk) < 0)
+goto cleanup;
+
 if (qemuHotplugAttachManagedPR(vm, disk->src, VIR_ASYNC_JOB_NONE) < 0)
 goto cleanup;

-- 
2.41.0



[PATCH v2 0/3] qemu: Fix hotplug and blockcopy to VDPA disks

2023-10-26 Thread Peter Krempa
Content-type: text/plain

v2:
- also deal with blockcopy (requires more helpers)


Peter Krempa (3):
  qemu: process: Extract host setup of disk device into helpers
  qemu: hotplug: Setup host side of VDPA device for disk hotplug
  qemu: Setup host side of VDPA device for block copy

 src/qemu/qemu_block.c   |  4 +++
 src/qemu/qemu_driver.c  | 12 +++
 src/qemu/qemu_hotplug.c |  3 ++
 src/qemu/qemu_process.c | 76 -
 src/qemu/qemu_process.h |  7 
 5 files changed, 93 insertions(+), 9 deletions(-)

-- 
2.41.0



Re: [PATCH 0/2] qemu: Fix hotplug of VDPA disks

2023-10-26 Thread Peter Krempa
On Thu, Oct 26, 2023 at 15:15:15 +0200, Peter Krempa wrote:
> Peter Krempa (2):
>   qemu: process: Extract host setup of disk device into a helper
>   qemu: hotplug: Setup host side of VDPA device for disk hotplug
> 
>  src/qemu/qemu_hotplug.c |  3 +++
>  src/qemu/qemu_process.c | 42 -
>  src/qemu/qemu_process.h |  3 +++
>  3 files changed, 39 insertions(+), 9 deletions(-)

I'll be posting a v2 to properly address also block copy.



[PATCH 1/2] qemu: process: Extract host setup of disk device into a helper

2023-10-26 Thread Peter Krempa
Currently the code sets up only VDPA backends but will be used later in
hotplug code too.

This patch also uses normal forward iteration in the loop in
qemuProcessPrepareHostStorage as we don't need to remove disks from the
disk list at that point.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_process.c | 42 -
 src/qemu/qemu_process.h |  3 +++
 2 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 63c0c62a46..b420ec283d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6777,6 +6777,35 @@ qemuProcessPrepareHostStorageSourceVDPA(virStorageSource 
*src,
 }


+/**
+ * qemuProcessPrepareHostStorageDisk:
+ *
+ * @vm: domain object
+ * @disk: disk definition object
+ *
+ * Prepare the host side of a disk for use with the VM. Note that this function
+ * accesses host resources.
+ *
+ * Note that this function does not call qemuDomainDetermineDiskChain as that 
is
+ * needed in qemuProcessPrepareHostStorage to remove disks based on the startup
+ * policy, thus other callers need to call it explicitly.
+ */
+int
+qemuProcessPrepareHostStorageDisk(virDomainObj *vm,
+  virDomainDiskDef *disk)
+{
+virStorageSource *n;
+
+for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
+/* connect to any necessary vdpa block devices */
+if (qemuProcessPrepareHostStorageSourceVDPA(n, vm->privateData) < 0)
+return -1;
+}
+
+return 0;
+}
+
+
 static int
 qemuProcessPrepareHostStorage(virQEMUDriver *driver,
   virDomainObj *vm,
@@ -6813,16 +6842,11 @@ qemuProcessPrepareHostStorage(virQEMUDriver *driver,
 return -1;
 }

-/* connect to any necessary vdpa block devices */
-for (i = vm->def->ndisks; i > 0; i--) {
-size_t idx = i - 1;
-virDomainDiskDef *disk = vm->def->disks[idx];
-virStorageSource *src;
+for (i = 0; i < vm->def->ndisks; i++) {
+virDomainDiskDef *disk = vm->def->disks[i];

-for (src = disk->src; virStorageSourceIsBacking(src); src = 
src->backingStore) {
-if (qemuProcessPrepareHostStorageSourceVDPA(src, vm->privateData) 
< 0)
-return -1;
-}
+if (qemuProcessPrepareHostStorageDisk(vm, disk) < 0)
+return -1;
 }

 return 0;
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index ef05b46892..7b974259d3 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -133,6 +133,9 @@ int qemuProcessPrepareHost(virQEMUDriver *driver,
virDomainObj *vm,
unsigned int flags);

+int qemuProcessPrepareHostStorageDisk(virDomainObj *vm,
+  virDomainDiskDef *disk);
+
 int qemuProcessDeleteThreadContext(virDomainObj *vm);

 int qemuProcessLaunch(virConnectPtr conn,
-- 
2.41.0



[PATCH 2/2] qemu: hotplug: Setup host side of VDPA device for disk hotplug

2023-10-26 Thread Peter Krempa
The code which opens the VDPA device and prepares it for FD passing was
not called in the hotplug code path, preventing hotplug of VDPA disks
with:

 error: internal error: argument key 'path' must not have null value

Use the new helper qemuProcessPrepareHostStorageDisk to setup the VDPA
definition.

Closes: https://gitlab.com/libvirt/libvirt/-/issues/539
Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_hotplug.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1f7f5bdd26..fec7c4be4e 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1007,6 +1007,9 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver 
*driver,
 if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL) < 0)
 goto cleanup;

+if (qemuProcessPrepareHostStorageDisk(vm, disk) < 0)
+goto cleanup;
+
 if (qemuHotplugAttachManagedPR(vm, disk->src, VIR_ASYNC_JOB_NONE) < 0)
 goto cleanup;

-- 
2.41.0



[PATCH 0/2] qemu: Fix hotplug of VDPA disks

2023-10-26 Thread Peter Krempa
Peter Krempa (2):
  qemu: process: Extract host setup of disk device into a helper
  qemu: hotplug: Setup host side of VDPA device for disk hotplug

 src/qemu/qemu_hotplug.c |  3 +++
 src/qemu/qemu_process.c | 42 -
 src/qemu/qemu_process.h |  3 +++
 3 files changed, 39 insertions(+), 9 deletions(-)

-- 
2.41.0



[PATCH] docs: formatdomain: Clarify that the SLIC ACPI table config is available for all modes

2023-10-26 Thread Peter Krempa
Move the docs for the  element under a common section as
it's not specific for direct kernel boot. In fact the original use was
for Windows activation.

Fixes: 72f652da63255c7f1a9914625cce617dde9128d0
Signed-off-by: Peter Krempa 
---
 docs/formatdomain.rst | 29 +
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 03735e4593..459815d2b5 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -387,9 +387,6 @@ and full virtualized guests.
  /root/f8-i386-initrd
  console=ttyS0 ks=http://example.com/f8-i386/os/
  /root/ppc.dtb
- 
-   /path/to/slic.dat
- 

...

@@ -413,11 +410,6 @@ and full virtualized guests.
The contents of this element specify the fully-qualified path to the
(optional) device tree binary (dtb) image in the host OS. :since:`Since
1.0.4`
-``acpi``
-   The ``table`` element contains a fully-qualified path to the ACPI table. The
-   ``type`` attribute contains the ACPI table type (currently only ``slic`` is
-   supported) :since:`Since 1.3.5 (QEMU)` :since:`Since 5.9.0 (Xen)`
-

 Container boot
 ~~
@@ -470,6 +462,27 @@ If you want to enable user namespace, set the ``idmap`` 
element. The ``uid`` and
  


+Common  element configuration
+~
+
+These options apply to any form of booting of the guest OS.
+
+::
+
+   ...
+   
+ ...
+ 
+   /path/to/slic.dat
+ 
+   
+   ...
+
+``acpi``
+   The ``table`` element contains a fully-qualified path to the ACPI table. The
+   ``type`` attribute contains the ACPI table type (currently only ``slic`` is
+   supported) :since:`Since 1.3.5 (QEMU)` :since:`Since 5.9.0 (Xen)`
+

 SMBIOS System Information
 -
-- 
2.41.0



[PATCH 15/22] qemuBlockStorageSourceGetBackendProps: Unify ordering of fields

2023-10-25 Thread Peter Krempa
Use the same ordering of the relevant fields as we do for the format
layer -blockdev so that later they can be refactored without test
fallout.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c |  2 +-
 .../xml2json/dir-fat-cache.json   |  6 ++---
 .../file-backing_basic-cache-directsync.json  | 24 +--
 .../file-backing_basic-cache-none.json| 24 +--
 .../file-backing_basic-cache-unsafe.json  | 24 +--
 .../file-backing_basic-cache-writeback.json   | 24 +--
 ...file-backing_basic-cache-writethrough.json | 24 +--
 .../xml2json/file-raw-aio_native.json |  6 ++---
 ...work-qcow2-backing-chain-cache-unsafe.json | 12 +-
 .../blkdeviotune-group-num.x86_64-latest.args |  4 ++--
 ...blkdeviotune-max-length.x86_64-latest.args |  4 ++--
 .../blkdeviotune-max.x86_64-latest.args   |  4 ++--
 .../blkdeviotune.x86_64-latest.args   |  4 ++--
 .../controller-order.x86_64-latest.args   |  2 +-
 .../disk-aio.x86_64-latest.args   |  2 +-
 .../disk-cache.x86_64-latest.args | 10 
 .../disk-error-policy-s390x.s390x-latest.args |  6 ++---
 .../disk-error-policy.x86_64-latest.args  |  6 ++---
 .../disk-metadata-cache.x86_64-latest.args|  6 ++---
 .../disk-network-nfs.x86_64-latest.args   |  2 +-
 ...rk-tlsx509-nbd-hostname.x86_64-latest.args |  2 +-
 ...disk-network-tlsx509-nbd.x86_64-5.2.0.args |  2 +-
 ...isk-network-tlsx509-nbd.x86_64-latest.args |  2 +-
 ...isk-network-tlsx509-vxhs.x86_64-5.0.0.args |  6 ++---
 .../disk-nvme.x86_64-latest.args  |  2 +-
 .../disk-shared.x86_64-latest.args|  6 ++---
 .../disk-slices.x86_64-latest.args|  2 +-
 .../disk-snapshot.x86_64-latest.args  |  4 ++--
 .../disk-transient.x86_64-latest.args |  2 +-
 .../disk-vhostvdpa.x86_64-latest.args |  2 +-
 .../name-escape.x86_64-latest.args|  2 +-
 .../user-aliases.x86_64-latest.args   |  4 ++--
 ...eo-bochs-display-device.x86_64-latest.args |  2 +-
 ...-device-pciaddr-default.x86_64-latest.args |  2 +-
 ...video-qxl-device-vgamem.x86_64-latest.args |  2 +-
 .../video-qxl-device.x86_64-latest.args   |  2 +-
 ...o-qxl-sec-device-vgamem.x86_64-latest.args |  2 +-
 .../video-qxl-sec-device.x86_64-latest.args   |  2 +-
 ...eo-ramfb-display-device.x86_64-latest.args |  2 +-
 ...video-vga-device-vgamem.x86_64-latest.args |  2 +-
 .../video-vga-device.x86_64-latest.args   |  2 +-
 .../video-virtio-blob-off.x86_64-latest.args  |  2 +-
 .../video-virtio-blob-on.x86_64-latest.args   |  2 +-
 ...video-virtio-gpu-device.x86_64-latest.args |  2 +-
 ...video-virtio-gpu-sdl-gl.x86_64-latest.args |  2 +-
 ...deo-virtio-gpu-spice-gl.x86_64-latest.args |  2 +-
 .../video-virtio-gpu-virgl.x86_64-latest.args |  2 +-
 .../video-virtio-vga.x86_64-latest.args   |  2 +-
 48 files changed, 132 insertions(+), 132 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 1fa9627444..689eb535cb 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1113,10 +1113,10 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,

 if (virJSONValueObjectAdd(,
   "s:node-name", nodename,
-  "A:cache", ,
   "T:read-only", ro,
   "T:auto-read-only", aro,
   "S:discard", discardstr,
+  "A:cache", ,
   NULL) < 0)
 return NULL;
 }
diff --git a/tests/qemublocktestdata/xml2json/dir-fat-cache.json 
b/tests/qemublocktestdata/xml2json/dir-fat-cache.json
index 2a24175ef4..320dc77de1 100644
--- a/tests/qemublocktestdata/xml2json/dir-fat-cache.json
+++ b/tests/qemublocktestdata/xml2json/dir-fat-cache.json
@@ -14,10 +14,10 @@
   "floppy": false,
   "rw": false,
   "node-name": "node-s",
+  "auto-read-only": true,
+  "discard": "unmap",
   "cache": {
 "direct": true,
 "no-flush": false
-  },
-  "auto-read-only": true,
-  "discard": "unmap"
+  }
 }
diff --git 
a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json 
b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json
index 1d5ae09813..7a8d0686f6 100644
--- a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json
+++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json
@@ -13,12 +13,12 @@
   "driver": "file",
   "filename": "/var/lib/libvirt/images/a",
   "node-name": "node-a-s",
+  "auto-read-only": true,
+  "discard&q

[PATCH 10/22] qemublocktest: Drop 'sheepdog' and 'vxhs' test cases

2023-10-25 Thread Peter Krempa
QEMU deprecated and removed support for those protocols, but due to a
logic bug in the tests it was not caught. Remove the test cases first.

Signed-off-by: Peter Krempa 
---
 tests/qemublocktest.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index ce76150200..a89dddf002 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -1084,12 +1084,6 @@ mymain(void)
 TEST_JSON_FORMAT_NET("\n"
  "  \n"
  "\n");
-TEST_JSON_FORMAT_NET("\n"
- "  \n"
- "\n");
-TEST_JSON_FORMAT_NET("\n"
- "  \n"
- "\n");

 #define TEST_DISK_TO_JSON_FULL(nme, fl) \
 do { \
-- 
2.41.0



[PATCH 22/22] qemu: block: Remove unused flags QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_ flags

2023-10-25 Thread Peter Krempa
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP is no longer
referenced inside the code.

QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY is passed from
various code paths to the qemuBlockStorageSourceGetBackendProps helper,
but it's no longer used.

Both thus can be removed.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 7 +--
 src/qemu/qemu_block.h | 4 +---
 tests/qemublocktest.c | 7 ++-
 3 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index a625e72a5d..382015f293 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1006,11 +1006,6 @@ 
qemuBlockStorageSourceAddBlockdevCommonProps(virJSONValue **props,
  *  use legacy formatting of attributes (for -drive / old qemus)
  *  QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY:
  *  omit any data which does not identify the image itself
- *  QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY:
- *  use the auto-read-only feature of qemu
- *  QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP:
- *  don't enable 'discard:unmap' option for passing through discards
- *  (note that this is disabled also for _LEGACY and _TARGET_ONLY options)
  *  QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE:
  *  the 'protocol' node is used as the effective/top node of a 
virStorageSource
  *
@@ -1510,7 +1505,7 @@ 
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSource *src,
 virStorageSource *backingStore)
 {
 g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
-unsigned int backendpropsflags = 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY;
+unsigned int backendpropsflags = 0;

 data = g_new0(qemuBlockStorageSourceAttachData, 1);

diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 9757108501..5c784a4386 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -66,9 +66,7 @@ 
qemuBlockStorageSourceSupportsConcurrentAccess(virStorageSource *src);
 typedef enum {
 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY = 1 << 0,
 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY = 1 << 1,
-QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY = 1 << 2,
-QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP = 1 << 3,
-QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE = 1 << 4,
+QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE = 1 << 2,
 } qemuBlockStorageSourceBackendPropsFlags;

 virJSONValue *
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index b8db1a2570..c581bd1748 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -285,9 +285,6 @@ testQemuDiskXMLToProps(const void *opaque)

 for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
 g_autofree char *backingstore = NULL;
-unsigned int backendpropsflagsnormal = 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY;
-unsigned int backendpropsflagstarget = 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY |
-   
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY;

 if (testQemuDiskXMLToJSONFakeSecrets(n) < 0)
 return -1;
@@ -298,8 +295,8 @@ testQemuDiskXMLToProps(const void *opaque)
 qemuDomainPrepareDiskSourceData(disk, n);

 if (!(formatProps = qemuBlockStorageSourceGetFormatProps(n, 
n->backingStore)) ||
-!(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, 
backendpropsflagstarget)) ||
-!(storageProps = qemuBlockStorageSourceGetBackendProps(n, 
backendpropsflagsnormal)) ||
+!(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY)) ||
+!(storageProps = qemuBlockStorageSourceGetBackendProps(n, 0)) ||
 !(backingstore = qemuBlockGetBackingStoreString(n, true))) {
 if (!data->fail) {
 VIR_TEST_VERBOSE("failed to generate qemu blockdev props");
-- 
2.41.0



[PATCH 20/22] qemuBlockStorageSourceGetBackendProps: Use qemuBlockStorageSourceAddBlockdevCommonProps

2023-10-25 Thread Peter Krempa
Use the qemuBlockStorageSourceAddBlockdevCommonProps helper when
formatting protocol layer both when it's used as backing for a format
node and when it's used as the effective node.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 29 +++--
 1 file changed, 3 insertions(+), 26 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 7902ef31b3..5c8d107257 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1184,33 +1184,10 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 return NULL;

 if (!onlytarget && !legacy) {
-const char *nodename = qemuBlockStorageSourceGetStorageNodename(src);
-
-if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE) {
-if (qemuBlockStorageSourceAddBlockdevCommonProps(, src, 
nodename, true) < 0)
-return NULL;
-} else {
-g_autoptr(virJSONValue) cache = NULL;
-const char *discardstr = "unmap";
-
-if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)
-discardstr = NULL;
-
-if (qemuBlockNodeNameValidate(nodename) < 0)
+if (qemuBlockStorageSourceAddBlockdevCommonProps(, src,
+ 
qemuBlockStorageSourceGetStorageNodename(src),
+ !!(flags & 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE)) < 0)
 return NULL;
-
-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 
0)
-return NULL;
-
-if (virJSONValueObjectAdd(,
-  "s:node-name", nodename,
-  "T:read-only", ro,
-  "T:auto-read-only", aro,
-  "S:discard", discardstr,
-  "A:cache", ,
-  NULL) < 0)
-return NULL;
-}
 }

 return g_steal_pointer();
-- 
2.41.0



[PATCH 19/22] qemuBuildHostdevSCSIAttachPrepare: Use "effective node" mode for getting blockdev props

2023-10-25 Thread Peter Krempa
The resulting properties are identical, as the hostdev backend code
doesn't set any of the extra properties.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_command.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 98e7fa3d80..2674dd6959 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5066,8 +5066,7 @@ qemuBuildHostdevSCSIAttachPrepare(virDomainHostdevDef 
*hostdev,
 ret->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
 *backendAlias = qemuBlockStorageSourceGetStorageNodename(src);

-if (!(ret->storageProps = qemuBlockStorageSourceGetBackendProps(src,
-
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)))
+if (!(ret->storageProps = qemuBlockStorageSourceGetBackendProps(src, 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE)))
 return NULL;

 if (qemuBuildStorageSourceAttachPrepareCommon(src, ret) < 0)
-- 
2.41.0



[PATCH 08/22] qemuBlockStorageSourceGetBlockdevGetCacheProps: Return the cache object rather than appending it

2023-10-25 Thread Peter Krempa
Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c  | 29 -
 src/qemu/qemu_domain.c |  2 +-
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 0f47b5b37f..41038fb994 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -913,24 +913,20 @@ qemuBlockStorageSourceGetVhostVdpaProps(virStorageSource 
*src)

 static int
 qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSource *src,
-   virJSONValue *props)
+   virJSONValue **cache)
 {
-g_autoptr(virJSONValue) cacheobj = NULL;
 bool direct = false;
 bool noflush = false;

 if (!qemuDomainDiskCachemodeFlags(src->cachemode, NULL, , ))
 return 0;

-if (virJSONValueObjectAdd(,
+if (virJSONValueObjectAdd(cache,
   "b:direct", direct,
   "b:no-flush", noflush,
   NULL) < 0)
 return -1;

-if (virJSONValueObjectAppend(props, "cache", ) < 0)
-return -1;
-
 return 0;
 }

@@ -1109,10 +1105,13 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 return NULL;

 if (!legacy) {
-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, fileprops) 
< 0)
+g_autoptr(virJSONValue) cache = NULL;
+
+if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 
0)
 return NULL;

 if (virJSONValueObjectAdd(,
+  "A:cache", ,
   "T:read-only", ro,
   "T:auto-read-only", aro,
   NULL) < 0)
@@ -1278,10 +1277,14 @@ 
qemuBlockStorageSourceGetBlockdevFormatCommonProps(virStorageSource *src)
 int detectZeroesMode = virDomainDiskGetDetectZeroesMode(src->discard,
 
src->detect_zeroes);
 g_autoptr(virJSONValue) props = NULL;
+g_autoptr(virJSONValue) cache = NULL;

 if 
(qemuBlockNodeNameValidate(qemuBlockStorageSourceGetFormatNodename(src)) < 0)
 return NULL;

+if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 0)
+return NULL;
+
 if (src->discard)
 discard = virDomainDiskDiscardTypeToString(src->discard);

@@ -1297,12 +1300,10 @@ 
qemuBlockStorageSourceGetBlockdevFormatCommonProps(virStorageSource *src)
   "b:read-only", src->readonly,
   "S:discard", discard,
   "S:detect-zeroes", detectZeroes,
+  "A:cache", ,
   NULL) < 0)
 return NULL;

-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, props) < 0)
-return NULL;
-
 return g_steal_pointer();
 }

@@ -1439,10 +1440,14 @@ static virJSONValue *
 qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSource *src)
 {
 g_autoptr(virJSONValue) props = NULL;
+g_autoptr(virJSONValue) cache = NULL;

 if (qemuBlockNodeNameValidate(src->sliceStorage->nodename) < 0)
 return NULL;

+if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 0)
+return NULL;
+
 if (virJSONValueObjectAdd(,
   "s:driver", "raw",
   "s:node-name", src->sliceStorage->nodename,
@@ -1451,12 +1456,10 @@ 
qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSource *src)
   "s:file", 
qemuBlockStorageSourceGetStorageNodename(src),
   "b:auto-read-only", true,
   "s:discard", "unmap",
+  "A:cache", ,
   NULL) < 0)
 return NULL;

-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, props) < 0)
-return NULL;
-
 return g_steal_pointer();
 }

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 0b36a49bdf..ae19ce884b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11442,7 +11442,7 @@ qemuDomainDiskCachemodeFlags(virDomainDiskCache 
cachemode,
  * directsync   │ false true   false
  * unsafe   │ true  false  true
  */
-switch ((virDomainDiskCache) cachemode) {
+switch (cachemode) {
 case VIR_DOMAIN_DISK_CACHE_DISABLE: /* 'none' */
 *writeback = true;
 *direct = true;
-- 
2.41.0



[PATCH 13/22] qemuBlockStorageSourceGetBackendProps: Unify cases for '!onlytarget' and '!legacy'

2023-10-25 Thread Peter Krempa
At this point only a single code path (for formatting -drive for legacy
SD cards) uses the 'legacy' output and that code path doesn't populate
the node name. Thus we can unify the code block and simplify the JSON
formatters.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 40 ++--
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 41038fb994..ca68b9ab66 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1097,32 +1097,28 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 if (driver && virJSONValueObjectPrependString(fileprops, "driver", driver) 
< 0)
 return NULL;

-if (!onlytarget) {
-if 
(qemuBlockNodeNameValidate(qemuBlockStorageSourceGetStorageNodename(src)) < 0 ||
-virJSONValueObjectAdd(,
-  "S:node-name", 
qemuBlockStorageSourceGetStorageNodename(src),
-  NULL) < 0)
-return NULL;
+if (!onlytarget && !legacy) {
+g_autoptr(virJSONValue) cache = NULL;
+const char *discardstr = "unmap";
+const char *nodename = qemuBlockStorageSourceGetStorageNodename(src);

-if (!legacy) {
-g_autoptr(virJSONValue) cache = NULL;
+if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)
+discardstr = NULL;

-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 
0)
-return NULL;
+if (qemuBlockNodeNameValidate(nodename) < 0)
+return NULL;

-if (virJSONValueObjectAdd(,
-  "A:cache", ,
-  "T:read-only", ro,
-  "T:auto-read-only", aro,
-  NULL) < 0)
-return NULL;
+if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 0)
+return NULL;

-if (!(flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP) 
&&
-virJSONValueObjectAdd(,
-  "s:discard", "unmap",
-  NULL) < 0)
-return NULL;
-}
+if (virJSONValueObjectAdd(,
+  "s:node-name", nodename,
+  "A:cache", ,
+  "T:read-only", ro,
+  "T:auto-read-only", aro,
+  "S:discard", discardstr,
+  NULL) < 0)
+return NULL;
 }

 return g_steal_pointer();
-- 
2.41.0



[PATCH 14/22] virDomainDiskGetDetectZeroesMode: Return proper type

2023-10-25 Thread Peter Krempa
Change the return value type to 'virDomainDiskGetDetectZeroes'.

Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.c  | 2 +-
 src/conf/domain_conf.h  | 2 +-
 src/qemu/qemu_block.c   | 4 ++--
 src/qemu/qemu_command.c | 4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 80f467ae7a..fa97def9f7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30592,7 +30592,7 @@ virDomainDiskTranslateSourcePool(virDomainDiskDef *def)
  * don't change it in the XML for easier adjustments.  This behaviour is
  * documented.
  */
-int
+virDomainDiskDetectZeroes
 virDomainDiskGetDetectZeroesMode(virDomainDiskDiscard discard,
  virDomainDiskDetectZeroes detect_zeroes)
 {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 98f99721f0..7c0e017038 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -4406,7 +4406,7 @@ virDomainNetResolveActualType(virDomainNetDef *iface)

 int virDomainDiskTranslateSourcePool(virDomainDiskDef *def);

-int
+virDomainDiskDetectZeroes
 virDomainDiskGetDetectZeroesMode(virDomainDiskDiscard discard,
  virDomainDiskDetectZeroes detect_zeroes);

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index ca68b9ab66..1fa9627444 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1270,8 +1270,8 @@ 
qemuBlockStorageSourceGetBlockdevFormatCommonProps(virStorageSource *src)
 {
 const char *detectZeroes = NULL;
 const char *discard = NULL;
-int detectZeroesMode = virDomainDiskGetDetectZeroesMode(src->discard,
-
src->detect_zeroes);
+virDomainDiskDetectZeroes detectZeroesMode = 
virDomainDiskGetDetectZeroesMode(src->discard,
+   
   src->detect_zeroes);
 g_autoptr(virJSONValue) props = NULL;
 g_autoptr(virJSONValue) cache = NULL;

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fd0f12f304..98e7fa3d80 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1680,8 +1680,8 @@ static char *
 qemuBuildDriveStr(virDomainDiskDef *disk)
 {
 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
-int detect_zeroes = virDomainDiskGetDetectZeroesMode(disk->discard,
- disk->detect_zeroes);
+virDomainDiskDetectZeroes detect_zeroes = 
virDomainDiskGetDetectZeroesMode(disk->discard,
+   
disk->detect_zeroes);

 if (qemuBuildDriveSourceStr(disk, ) < 0)
 return NULL;
-- 
2.41.0



[PATCH 16/22] qemu: block: Add helper to add common properties for -blockdev configuration

2023-10-25 Thread Peter Krempa
The new helper replaces qemuBlockStorageSourceGetBlockdevFormatCommonProps
and the two inline instances generating the common properties for a
blockdev layer.

The new helper is to be used for both the format layer and the storage
backing layer, thus a new parameter 'effective' switches between the
modes.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 128 +-
 1 file changed, 88 insertions(+), 40 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 689eb535cb..aeb05a7f00 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -931,6 +931,90 @@ 
qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSource *src,
 }


+/**
+ * qemuBlockStorageSourceAddBlockdevCommonProps:
+ * @props: JSON object to append the props to
+ * @src: storage source
+ * @nodename: nodename to use for @src
+ * @effective: Whether props for the effective(topmost) layer are to be 
formatted
+ *
+ * Add the common props (node name, read-only state, cache configuration, 
discard)
+ * to a JSON object for a -blockdev definition. If @effective is true,
+ * the props are configured for the topmost layer used to access the data,
+ * otherwise the props are configured for the storage protocol backing a format
+ * layer.
+ */
+static int
+qemuBlockStorageSourceAddBlockdevCommonProps(virJSONValue **props,
+ virStorageSource *src,
+ const char *nodename,
+ bool effective)
+{
+virStorageType actualType = virStorageSourceGetActualType(src);
+g_autoptr(virJSONValue) cache = NULL;
+const char *detectZeroes = NULL;
+const char *discard = NULL;
+virTristateBool autoReadOnly = VIR_TRISTATE_BOOL_ABSENT;
+virTristateBool readOnly = VIR_TRISTATE_BOOL_ABSENT;
+
+if (qemuBlockNodeNameValidate(nodename) < 0)
+return -1;
+
+if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 0)
+return -1;
+
+if (effective) {
+virDomainDiskDetectZeroes dz = 
virDomainDiskGetDetectZeroesMode(src->discard,
+
src->detect_zeroes);
+
+if (src->discard != VIR_DOMAIN_DISK_DISCARD_DEFAULT)
+discard = virDomainDiskDiscardTypeToString(src->discard);
+
+if (dz != VIR_DOMAIN_DISK_DETECT_ZEROES_DEFAULT)
+detectZeroes = virDomainDiskDetectZeroesTypeToString(dz);
+
+autoReadOnly = VIR_TRISTATE_BOOL_ABSENT;
+readOnly = virTristateBoolFromBool(src->readonly);
+} else {
+/* when passing a FD to qemu via the /dev/fdset mechanism qemu
+ * fetches the appropriate FD from the fdset by checking that it has
+ * the correct accessmode. Now with 'auto-read-only' in effect qemu
+ * wants to use a read-only FD first. If the user didn't pass multiple
+ * FDs the feature will not work regardless, so we'll not enable it. */
+if ((actualType == VIR_STORAGE_TYPE_FILE || actualType == 
VIR_STORAGE_TYPE_BLOCK) &&
+src->fdtuple && src->fdtuple->nfds == 1) {
+autoReadOnly = VIR_TRISTATE_BOOL_ABSENT;
+
+/* now we setup the normal readonly flag. If user requested write 
access honour it */
+if (src->fdtuple->writable)
+readOnly = VIR_TRISTATE_BOOL_NO;
+else
+readOnly = virTristateBoolFromBool(src->readonly);
+} else {
+autoReadOnly = VIR_TRISTATE_BOOL_YES;
+}
+
+discard = "unmap";
+}
+
+/* currently unhandled global properties:
+ * '*force-share': 'bool'
+ */
+
+if (virJSONValueObjectAdd(props,
+  "s:node-name", nodename,
+  "T:read-only", readOnly,
+  "T:auto-read-only", autoReadOnly,
+  "S:discard", discard,
+  "S:detect-zeroes", detectZeroes,
+  "A:cache", ,
+  NULL) < 0)
+return -1;
+
+return 0;
+}
+
+
 /**
  * qemuBlockStorageSourceGetBackendProps:
  * @src: disk source
@@ -1265,52 +1349,16 @@ 
qemuBlockStorageSourceGetFormatQcow2Props(virStorageSource *src,
 }


-static virJSONValue *
-qemuBlockStorageSourceGetBlockdevFormatCommonProps(virStorageSource *src)
-{
-const char *detectZeroes = NULL;
-const char *discard = NULL;
-virDomainDiskDetectZeroes detectZeroesMode = 
virDomainDiskGetDetectZeroesMode(src->discard,
-   
   src->detect_zeroes);
-g_autoptr(virJSONValue) props = NULL;
-g_autoptr(virJSONValue) cache = NULL;
-
-if 
(qemuBlockNodeNameValidate(qemuBlo

[PATCH 07/22] qemuDomainDiskCachemodeFlags: Simplify usage

2023-10-25 Thread Peter Krempa
Return whether a relevant cachemode was presented rather than returning
an error, so that callers can be simplified. Use the proper enum type as
argument rather than typecasting in the switch statement.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c   |  5 +
 src/qemu/qemu_command.c | 15 ++-
 src/qemu/qemu_domain.c  | 31 +--
 src/qemu/qemu_domain.h  |  4 ++--
 4 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 3be12b47e3..0f47b5b37f 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -919,12 +919,9 @@ 
qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSource *src,
 bool direct = false;
 bool noflush = false;

-if (src->cachemode == VIR_DOMAIN_DISK_CACHE_DEFAULT)
+if (!qemuDomainDiskCachemodeFlags(src->cachemode, NULL, , ))
 return 0;

-if (qemuDomainDiskCachemodeFlags(src->cachemode, NULL, , ) 
< 0)
-return -1;
-
 if (virJSONValueObjectAdd(,
   "b:direct", direct,
   "b:no-flush", noflush,
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index dbef8d0068..fd0f12f304 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1889,16 +1889,13 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
 wwn = virJSONValueNewNumberUlong(w);
 }

-if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
-/* VIR_DOMAIN_DISK_DEVICE_LUN translates into 'scsi-block'
- * where any caching setting makes no sense. */
-if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN) {
-bool wb;
-
-if (qemuDomainDiskCachemodeFlags(disk->cachemode, , NULL,
- NULL) < 0)
-return NULL;
+/* 'write-cache' component of disk->cachemode is set on device level.
+ * VIR_DOMAIN_DISK_DEVICE_LUN translates into 'scsi-block' where any
+ * caching setting makes no sense. */
+if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN) {
+bool wb;

+if (qemuDomainDiskCachemodeFlags(disk->cachemode, , NULL, NULL)) {
 writeCache = virTristateSwitchFromBool(wb);
 }
 }
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 995aa3f79c..0b36a49bdf 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11406,13 +11406,18 @@ qemuDomainPrepareHostdev(virDomainHostdevDef *hostdev,

 /**
  * qemuDomainDiskCachemodeFlags:
+ * @cachemode: aggregated cache mode
+ * @writeback: populated with 'writeback' component of @cachemode (may be NULL)
+ * @direct: populated with 'direct' component of @cachemode (may be NULL)
+ * @noflush: populated with 'noflush' component of @cachemode (may be NULL)
  *
- * Converts disk cachemode to the cache mode options for qemu. Returns -1 for
- * invalid @cachemode values and fills the flags and returns 0 on success.
- * Flags may be NULL.
+ * Converts disk @cachemode to the cache mode options for qemu according to the
+ * table below.
+ *
+ * Returns true if @cachemode is a relevant cache mode setting.
  */
-int
-qemuDomainDiskCachemodeFlags(int cachemode,
+bool
+qemuDomainDiskCachemodeFlags(virDomainDiskCache cachemode,
  bool *writeback,
  bool *direct,
  bool *noflush)
@@ -11442,40 +11447,38 @@ qemuDomainDiskCachemodeFlags(int cachemode,
 *writeback = true;
 *direct = true;
 *noflush = false;
-break;
+return true;

 case VIR_DOMAIN_DISK_CACHE_WRITETHRU:
 *writeback = false;
 *direct = false;
 *noflush = false;
-break;
+return true;

 case VIR_DOMAIN_DISK_CACHE_WRITEBACK:
 *writeback = true;
 *direct = false;
 *noflush = false;
-break;
+return true;

 case VIR_DOMAIN_DISK_CACHE_DIRECTSYNC:
 *writeback = false;
 *direct = true;
 *noflush = false;
-break;
+return true;

 case VIR_DOMAIN_DISK_CACHE_UNSAFE:
 *writeback = true;
 *direct = false;
 *noflush = true;
-break;
+return true;

 case VIR_DOMAIN_DISK_CACHE_DEFAULT:
 case VIR_DOMAIN_DISK_CACHE_LAST:
-default:
-virReportEnumRangeError(virDomainDiskCache, cachemode);
-return -1;
+return false;
 }

-return 0;
+return false;
 }


diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index a3fc6acaaa..1e56e50672 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -1008,8 +1008,8 @@ qemuDomainPrepareDiskSource(virDomainDiskDef *disk,
 qemuDomainObjPrivate *priv,
 virQEMUDriverConfig *cfg);

-int
-qemuDomainDiskCachemodeFlags(int cachemode,
+bool
+qemu

[PATCH 18/22] qemuBlockStorageSourceGetBackendProps: Introduce QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE

2023-10-25 Thread Peter Krempa
Introduce a mode where the protocol layer -blockdev will be formatted
so that it can be used as the effective node (used to access data from
the device). For this new mode we'll use
qemuBlockStorageSourceAddBlockdevCommonProps.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 40 
 src/qemu/qemu_block.h |  1 +
 2 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index dc6f34530b..7902ef31b3 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1030,6 +1030,8 @@ qemuBlockStorageSourceAddBlockdevCommonProps(virJSONValue 
**props,
  *  QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP:
  *  don't enable 'discard:unmap' option for passing through discards
  *  (note that this is disabled also for _LEGACY and _TARGET_ONLY options)
+ *  QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE:
+ *  the 'protocol' node is used as the effective/top node of a 
virStorageSource
  *
  * Creates a JSON object describing the underlying storage or protocol of a
  * storage source. Returns NULL on error and reports an appropriate error 
message.
@@ -1182,27 +1184,33 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 return NULL;

 if (!onlytarget && !legacy) {
-g_autoptr(virJSONValue) cache = NULL;
-const char *discardstr = "unmap";
 const char *nodename = qemuBlockStorageSourceGetStorageNodename(src);

-if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)
-discardstr = NULL;
+if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE) {
+if (qemuBlockStorageSourceAddBlockdevCommonProps(, src, 
nodename, true) < 0)
+return NULL;
+} else {
+g_autoptr(virJSONValue) cache = NULL;
+const char *discardstr = "unmap";

-if (qemuBlockNodeNameValidate(nodename) < 0)
-return NULL;
+if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)
+discardstr = NULL;

-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 0)
-return NULL;
+if (qemuBlockNodeNameValidate(nodename) < 0)
+return NULL;

-if (virJSONValueObjectAdd(,
-  "s:node-name", nodename,
-  "T:read-only", ro,
-  "T:auto-read-only", aro,
-  "S:discard", discardstr,
-  "A:cache", ,
-  NULL) < 0)
-return NULL;
+if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 
0)
+return NULL;
+
+if (virJSONValueObjectAdd(,
+  "s:node-name", nodename,
+  "T:read-only", ro,
+  "T:auto-read-only", aro,
+  "S:discard", discardstr,
+  "A:cache", ,
+  NULL) < 0)
+return NULL;
+}
 }

 return g_steal_pointer();
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 7bb83d8d44..9757108501 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -68,6 +68,7 @@ typedef enum {
 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY = 1 << 1,
 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY = 1 << 2,
 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP = 1 << 3,
+QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE = 1 << 4,
 } qemuBlockStorageSourceBackendPropsFlags;

 virJSONValue *
-- 
2.41.0



[PATCH 11/22] qemublocktest: Fix logical bug in TEST_JSON_FORMAT macro

2023-10-25 Thread Peter Krempa
Condition handling failure of the first virTestRun was lacking the 'ret
= -1' line thus the subsequent line was taken as it's body rendering the
first invocation useless.

Signed-off-by: Peter Krempa 
---
 tests/qemublocktest.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index a89dddf002..161fd84871 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -1015,6 +1015,7 @@ mymain(void)
 xmljsonxmldata.legacy = true; \
 if (virTestRun(virTestCounterNext(), testBackingXMLjsonXML, \
) < 0) \
+ret = -1; \
 xmljsonxmldata.legacy = false; \
 if (virTestRun(virTestCounterNext(), testBackingXMLjsonXML, \
) < 0) \
-- 
2.41.0



[PATCH 17/22] qemu: block: Use qemuBlockStorageSourceAddBlockdevCommonProps for storage slice

2023-10-25 Thread Peter Krempa
Use the new helper in qemuBlockStorageSourceGetBlockdevStorageSliceProps
to format the common bits.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c   | 17 ++---
 .../disk-slices.x86_64-latest.args  |  6 +++---
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index aeb05a7f00..dc6f34530b 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1484,26 +1484,21 @@ static virJSONValue *
 qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSource *src)
 {
 g_autoptr(virJSONValue) props = NULL;
-g_autoptr(virJSONValue) cache = NULL;
-
-if (qemuBlockNodeNameValidate(src->sliceStorage->nodename) < 0)
-return NULL;
-
-if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, ) < 0)
-return NULL;

 if (virJSONValueObjectAdd(,
   "s:driver", "raw",
-  "s:node-name", src->sliceStorage->nodename,
   "U:offset", src->sliceStorage->offset,
   "U:size", src->sliceStorage->size,
   "s:file", 
qemuBlockStorageSourceGetStorageNodename(src),
-  "b:auto-read-only", true,
-  "s:discard", "unmap",
-  "A:cache", ,
   NULL) < 0)
 return NULL;

+if (qemuBlockStorageSourceAddBlockdevCommonProps(,
+ src,
+ 
src->sliceStorage->nodename,
+ false) < 0)
+return NULL;
+
 return g_steal_pointer();
 }

diff --git a/tests/qemuxml2argvdata/disk-slices.x86_64-latest.args 
b/tests/qemuxml2argvdata/disk-slices.x86_64-latest.args
index deaa094379..363f0c0361 100644
--- a/tests/qemuxml2argvdata/disk-slices.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/disk-slices.x86_64-latest.args
@@ -31,14 +31,14 @@ 
XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
 -blockdev 
'{"node-name":"libvirt-6-format","read-only":false,"driver":"raw","offset":0,"size":321,"file":"libvirt-6-storage"}'
 \
 -device 
'{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-6-format","id":"virtio-disk0","bootindex":1}'
 \
 -blockdev 
'{"driver":"file","filename":"/var/lib/libvirt/images/raw.img","node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}'
 \
--blockdev 
'{"driver":"raw","node-name":"libvirt-5-slice-sto","offset":9876,"size":123456789,"file":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}'
 \
+-blockdev 
'{"driver":"raw","offset":9876,"size":123456789,"file":"libvirt-5-storage","node-name":"libvirt-5-slice-sto","auto-read-only":true,"discard":"unmap"}'
 \
 -blockdev 
'{"node-name":"libvirt-5-format","read-only":true,"driver":"qcow2","file":"libvirt-5-slice-sto","backing":null}'
 \
 -blockdev 
'{"driver":"file","filename":"/var/lib/libvirt/images/overlay.qcow2","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}'
 \
 -blockdev 
'{"node-name":"libvirt-4-format","read-only":false,"driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-format"}'
 \
 -device 
'{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-4-format","id":"virtio-disk1"}'
 \
 -object 
'{"qom-type":"secret","id":"libvirt-3-format-encryption-secret0","data":"9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}'
 \
 -blockdev 
'{"driver":"file","filename":"/var/lib/libvirt/images/luks.img","node-name":"libvirt-3-storage","auto-re

[PATCH 00/22] qemu: Refactor blockdev protocol JSON generators ('raw' driver removal part 2)

2023-10-25 Thread Peter Krempa
Second part cleans up tests and various bits and refactors the protocol
blockdev JSON configuration generator to be reusable.

This still doesn't change the configuration of the blockdevs, just
reorders some arguments.

Peter Krempa (22):
  qemuxml2(argv|xml)test: Add network backed disk type='sd'
  qemu: migration: No longer avoid 'auto-read-only' option for migration
  qemuBuildDriveSourceStr: Absorb only use of qemuDiskSourceGetProps
  qemuBlockStorageSourceGetBackendProps: Remove unnecessary indent for
non-nbdkit code path
  conf: Move definition of some disk type enums to a common header
  virStorageSource: Use proper type for shadow copies of
iomode/cachemode/discard/detect_zeroes
  qemuDomainDiskCachemodeFlags: Simplify usage
  qemuBlockStorageSourceGetBlockdevGetCacheProps: Return the cache
object rather than appending it
  qemublocktest: Use "target only" mode in 'testJSONtoJSON' and
'testBackingXMLjsonXML'
  qemublocktest: Drop 'sheepdog' and 'vxhs' test cases
  qemublocktest: Fix logical bug in TEST_JSON_FORMAT macro
  qemublocktest: testBackingXMLjsonXML: Drop 'legacy' mode
  qemuBlockStorageSourceGetBackendProps: Unify cases for '!onlytarget'
and '!legacy'
  virDomainDiskGetDetectZeroesMode: Return proper type
  qemuBlockStorageSourceGetBackendProps: Unify ordering of fields
  qemu: block: Add helper to add common properties for -blockdev
configuration
  qemu: block: Use qemuBlockStorageSourceAddBlockdevCommonProps for
storage slice
  qemuBlockStorageSourceGetBackendProps: Introduce
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE
  qemuBuildHostdevSCSIAttachPrepare: Use "effective node" mode for
getting blockdev props
  qemuBlockStorageSourceGetBackendProps: Use
qemuBlockStorageSourceAddBlockdevCommonProps
  qemuBlockStorageSourceGetBackendProps: Remove unused logic for
(auto-)read-only flags
  qemu: block: Remove unused flags
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_ flags

 src/conf/domain_conf.c|   2 +-
 src/conf/domain_conf.h|  39 +-
 src/conf/storage_source_conf.h|   8 +-
 src/conf/virconftypes.h   |  39 +-
 src/qemu/qemu_block.c | 349 +-
 src/qemu/qemu_block.h |   6 +-
 src/qemu/qemu_command.c   |  63 ++--
 src/qemu/qemu_domain.c|  33 +-
 src/qemu/qemu_domain.h|   4 +-
 src/qemu/qemu_migration.c |   5 +-
 tests/qemublocktest.c |  41 +-
 .../jsontojson/curl-libguestfs-out.json   |   5 +-
 .../ssh-passthrough-libguestfs-out.json   |   4 +-
 .../xml2json/dir-fat-cache.json   |   6 +-
 .../file-backing_basic-cache-directsync.json  |  24 +-
 .../file-backing_basic-cache-none.json|  24 +-
 .../file-backing_basic-cache-unsafe.json  |  24 +-
 .../file-backing_basic-cache-writeback.json   |  24 +-
 ...file-backing_basic-cache-writethrough.json |  24 +-
 .../xml2json/file-raw-aio_native.json |   6 +-
 ...work-qcow2-backing-chain-cache-unsafe.json |  12 +-
 .../blkdeviotune-group-num.x86_64-latest.args |   4 +-
 ...blkdeviotune-max-length.x86_64-latest.args |   4 +-
 .../blkdeviotune-max.x86_64-latest.args   |   4 +-
 .../blkdeviotune.x86_64-latest.args   |   4 +-
 .../controller-order.x86_64-latest.args   |   2 +-
 .../disk-aio.x86_64-latest.args   |   2 +-
 .../disk-arm-virtio-sd.aarch64-latest.args|   2 +
 tests/qemuxml2argvdata/disk-arm-virtio-sd.xml |  16 +
 .../disk-cache.x86_64-latest.args |  10 +-
 .../disk-error-policy-s390x.s390x-latest.args |   6 +-
 .../disk-error-policy.x86_64-latest.args  |   6 +-
 .../disk-metadata-cache.x86_64-latest.args|   6 +-
 .../disk-network-nfs.x86_64-latest.args   |   2 +-
 ...rk-tlsx509-nbd-hostname.x86_64-latest.args |   2 +-
 ...disk-network-tlsx509-nbd.x86_64-5.2.0.args |   2 +-
 ...isk-network-tlsx509-nbd.x86_64-latest.args |   2 +-
 ...isk-network-tlsx509-vxhs.x86_64-5.0.0.args |   6 +-
 .../disk-nvme.x86_64-latest.args  |   2 +-
 .../disk-shared.x86_64-latest.args|   6 +-
 .../disk-slices.x86_64-latest.args|   8 +-
 .../disk-snapshot.x86_64-latest.args  |   4 +-
 .../disk-transient.x86_64-latest.args |   2 +-
 .../disk-vhostvdpa.x86_64-latest.args |   2 +-
 .../name-escape.x86_64-latest.args|   2 +-
 .../user-aliases.x86_64-latest.args   |   4 +-
 ...eo-bochs-display-device.x86_64-latest.args |   2 +-
 ...-device-pciaddr-default.x86_64-latest.args |   2 +-
 ...video-qxl-device-vgamem.x86_64-latest.args |   2 +-
 .../video-qxl-device.x86_64-latest.args   |   2 +-
 ...o-qxl-sec-device-vgamem.x86_64-latest.args |   2 +-
 .../video-qxl-sec-device.x86_64-latest.args   |   2 +-
 ...eo-ramfb-display-device.x86_64-latest.args |   2 +-
 ...video-vga-

[PATCH 12/22] qemublocktest: testBackingXMLjsonXML: Drop 'legacy' mode

2023-10-25 Thread Peter Krempa
Legacy mode used to be needed for use with -drive, which was almost
completely deleted. We now have qemuxml2argvtest test cases checking a
few cases and the rest uses the modern mode only. Thus we don't need to
test the legacy mode any more.

Signed-off-by: Peter Krempa 
---
 tests/qemublocktest.c | 25 -
 1 file changed, 8 insertions(+), 17 deletions(-)

diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index 161fd84871..b8db1a2570 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -61,8 +61,6 @@ testBackingXMLjsonXML(const void *args)
 g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER;
 unsigned int backendpropsflags = 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY;

-if (data->legacy)
-backendpropsflags |= QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY;

 xmlsrc = virStorageSourceNew();
 xmlsrc->type = data->type;
@@ -81,17 +79,15 @@ testBackingXMLjsonXML(const void *args)
 return -1;
 }

-if (!data->legacy) {
-if (testQEMUSchemaValidate(backendprops, data->schemaroot,
-   data->schema, false, ) < 0) {
-g_autofree char *debugmsg = virBufferContentAndReset();
-g_autofree char *debugprops = virJSONValueToString(backendprops, 
true);
+if (testQEMUSchemaValidate(backendprops, data->schemaroot,
+   data->schema, false, ) < 0) {
+g_autofree char *debugmsg = virBufferContentAndReset();
+g_autofree char *debugprops = virJSONValueToString(backendprops, true);

-VIR_TEST_VERBOSE("json does not conform to QAPI schema");
-VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n 
%s",
-   debugprops, NULLSTR(debugmsg));
-return -1;
-}
+VIR_TEST_VERBOSE("json does not conform to QAPI schema");
+VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s",
+   debugprops, NULLSTR(debugmsg));
+return -1;
 }

 if (virJSONValueObjectAdd(, "a:file", , NULL) < 0)
@@ -1012,11 +1008,6 @@ mymain(void)
 do { \
 xmljsonxmldata.type = tpe; \
 xmljsonxmldata.xml = xmlstr; \
-xmljsonxmldata.legacy = true; \
-if (virTestRun(virTestCounterNext(), testBackingXMLjsonXML, \
-   ) < 0) \
-ret = -1; \
-xmljsonxmldata.legacy = false; \
 if (virTestRun(virTestCounterNext(), testBackingXMLjsonXML, \
) < 0) \
 ret = -1; \
-- 
2.41.0



[PATCH 06/22] virStorageSource: Use proper type for shadow copies of iomode/cachemode/discard/detect_zeroes

2023-10-25 Thread Peter Krempa
The aforementioned fields in virStorageSource struct are copies of the
disk properties, but were not converted to the proper type yet.

Signed-off-by: Peter Krempa 
---
 src/conf/storage_source_conf.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index 2db780611e..5e7d127453 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -397,10 +397,10 @@ struct _virStorageSource {
 /* Libvirt currently stores the following properties in virDomainDiskDef.
  * These instances are currently just copies from the parent definition and
  * are not mapped back to the XML */
-int iomode; /* enum virDomainDiskIo */
-int cachemode; /* enum virDomainDiskCache */
-int discard; /* enum virDomainDiskDiscard */
-int detect_zeroes; /* enum virDomainDiskDetectZeroes */
+virDomainDiskIo iomode;
+virDomainDiskCache cachemode;
+virDomainDiskDiscard discard;
+virDomainDiskDetectZeroes detect_zeroes;
 virTristateSwitch discard_no_unref;

 bool floppyimg; /* set to true if the storage source is going to be used
-- 
2.41.0



[PATCH 21/22] qemuBlockStorageSourceGetBackendProps: Remove unused logic for (auto-)read-only flags

2023-10-25 Thread Peter Krempa
The code was refactored to format the 'read-only' and 'auto-read-only'
flags via the common helper, so the logic determining their values can
be removed.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 36 +++-
 1 file changed, 3 insertions(+), 33 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 5c8d107257..a625e72a5d 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -806,9 +806,7 @@ qemuBlockStorageSourceGetSshProps(virStorageSource *src)

 static virJSONValue *
 qemuBlockStorageSourceGetFileProps(virStorageSource *src,
-   bool onlytarget,
-   virTristateBool *autoReadOnly,
-   virTristateBool *readOnly)
+   bool onlytarget)
 {
 const char *path = src->path;
 const char *iomode = NULL;
@@ -824,25 +822,8 @@ qemuBlockStorageSourceGetFileProps(virStorageSource *src,
 if (src->iomode != VIR_DOMAIN_DISK_IO_DEFAULT)
 iomode = virDomainDiskIoTypeToString(src->iomode);

-if (srcpriv && srcpriv->fdpass) {
+if (srcpriv && srcpriv->fdpass)
 path = qemuFDPassGetPath(srcpriv->fdpass);
-
-/* when passing a FD to qemu via the /dev/fdset mechanism qemu
- * fetches the appropriate FD from the fdset by checking that it 
has
- * the correct accessmode. Now with 'auto-read-only' in effect qemu
- * wants to use a read-only FD first. If the user didn't pass 
multiple
- * FDs the feature will not work regardless, so we'll disable it. 
*/
-if (src->fdtuple->nfds == 1) {
-*autoReadOnly = VIR_TRISTATE_BOOL_ABSENT;
-
-/* now we setup the normal readonly flag. If user requested 
write
- * access honour it */
-if (src->fdtuple->writable)
-*readOnly = VIR_TRISTATE_BOOL_NO;
-else
-*readOnly = virTristateBoolFromBool(src->readonly);
-}
-}
 }

 ignore_value(virJSONValueObjectAdd(,
@@ -1043,20 +1024,9 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 virStorageType actualType = virStorageSourceGetActualType(src);
 g_autoptr(virJSONValue) fileprops = NULL;
 const char *driver = NULL;
-virTristateBool aro = VIR_TRISTATE_BOOL_ABSENT;
-virTristateBool ro = VIR_TRISTATE_BOOL_ABSENT;
 bool onlytarget = flags & 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY;
 bool legacy = flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY;

-if (flags & QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY) {
-aro = VIR_TRISTATE_BOOL_YES;
-} else {
-if (src->readonly)
-ro = VIR_TRISTATE_BOOL_YES;
-else
-ro = VIR_TRISTATE_BOOL_NO;
-}
-
 switch (actualType) {
 case VIR_STORAGE_TYPE_BLOCK:
 case VIR_STORAGE_TYPE_FILE:
@@ -1069,7 +1039,7 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 driver = "file";
 }

-if (!(fileprops = qemuBlockStorageSourceGetFileProps(src, onlytarget, 
, )))
+if (!(fileprops = qemuBlockStorageSourceGetFileProps(src, onlytarget)))
 return NULL;
 break;

-- 
2.41.0



[PATCH 05/22] conf: Move definition of some disk type enums to a common header

2023-10-25 Thread Peter Krempa
Certain disk config fields are mirrored between the disk and storage
source definitions. We nee

Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.h  | 37 -
 src/conf/virconftypes.h | 39 ++-
 2 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9e6dd930fa..98f99721f0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -413,17 +413,6 @@ typedef enum {
 VIR_DOMAIN_DISK_BUS_LAST
 } virDomainDiskBus;

-typedef enum {
-VIR_DOMAIN_DISK_CACHE_DEFAULT,
-VIR_DOMAIN_DISK_CACHE_DISABLE,
-VIR_DOMAIN_DISK_CACHE_WRITETHRU,
-VIR_DOMAIN_DISK_CACHE_WRITEBACK,
-VIR_DOMAIN_DISK_CACHE_DIRECTSYNC,
-VIR_DOMAIN_DISK_CACHE_UNSAFE,
-
-VIR_DOMAIN_DISK_CACHE_LAST
-} virDomainDiskCache;
-
 typedef enum {
 VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT,
 VIR_DOMAIN_DISK_ERROR_POLICY_STOP,
@@ -451,32 +440,6 @@ typedef enum {
 VIR_DOMAIN_DISK_TRANS_LAST
 } virDomainDiskGeometryTrans;

-typedef enum {
-VIR_DOMAIN_DISK_IO_DEFAULT = 0,
-VIR_DOMAIN_DISK_IO_NATIVE,
-VIR_DOMAIN_DISK_IO_THREADS,
-VIR_DOMAIN_DISK_IO_URING,
-
-VIR_DOMAIN_DISK_IO_LAST
-} virDomainDiskIo;
-
-typedef enum {
-VIR_DOMAIN_DISK_DISCARD_DEFAULT = 0,
-VIR_DOMAIN_DISK_DISCARD_UNMAP,
-VIR_DOMAIN_DISK_DISCARD_IGNORE,
-
-VIR_DOMAIN_DISK_DISCARD_LAST
-} virDomainDiskDiscard;
-
-typedef enum {
-VIR_DOMAIN_DISK_DETECT_ZEROES_DEFAULT = 0,
-VIR_DOMAIN_DISK_DETECT_ZEROES_OFF,
-VIR_DOMAIN_DISK_DETECT_ZEROES_ON,
-VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP,
-
-VIR_DOMAIN_DISK_DETECT_ZEROES_LAST
-} virDomainDiskDetectZeroes;
-
 typedef enum {
 VIR_DOMAIN_DISK_MODEL_DEFAULT = 0,
 VIR_DOMAIN_DISK_MODEL_VIRTIO,
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index e07f967814..26cb966194 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -1,5 +1,5 @@
 /*
- * virconftypes.h: struct typedefs to avoid circular inclusion
+ * virconftypes.h: struct and enum type definitions to avoid circular inclusion
  *
  * Copyright (C) 2006-2019 Red Hat, Inc.
  * Copyright (C) 2006-2008 Daniel P. Berrange
@@ -261,3 +261,40 @@ typedef struct _virDomainXMLOption virDomainXMLOption;
 typedef struct _virDomainXMLPrivateDataCallbacks 
virDomainXMLPrivateDataCallbacks;

 typedef struct _virDomainXenbusControllerOpts virDomainXenbusControllerOpts;
+
+typedef enum {
+VIR_DOMAIN_DISK_IO_DEFAULT = 0,
+VIR_DOMAIN_DISK_IO_NATIVE,
+VIR_DOMAIN_DISK_IO_THREADS,
+VIR_DOMAIN_DISK_IO_URING,
+
+VIR_DOMAIN_DISK_IO_LAST
+} virDomainDiskIo;
+
+typedef enum {
+VIR_DOMAIN_DISK_CACHE_DEFAULT = 0,
+VIR_DOMAIN_DISK_CACHE_DISABLE,
+VIR_DOMAIN_DISK_CACHE_WRITETHRU,
+VIR_DOMAIN_DISK_CACHE_WRITEBACK,
+VIR_DOMAIN_DISK_CACHE_DIRECTSYNC,
+VIR_DOMAIN_DISK_CACHE_UNSAFE,
+
+VIR_DOMAIN_DISK_CACHE_LAST
+} virDomainDiskCache;
+
+typedef enum {
+VIR_DOMAIN_DISK_DISCARD_DEFAULT = 0,
+VIR_DOMAIN_DISK_DISCARD_UNMAP,
+VIR_DOMAIN_DISK_DISCARD_IGNORE,
+
+VIR_DOMAIN_DISK_DISCARD_LAST
+} virDomainDiskDiscard;
+
+typedef enum {
+VIR_DOMAIN_DISK_DETECT_ZEROES_DEFAULT = 0,
+VIR_DOMAIN_DISK_DETECT_ZEROES_OFF,
+VIR_DOMAIN_DISK_DETECT_ZEROES_ON,
+VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP,
+
+VIR_DOMAIN_DISK_DETECT_ZEROES_LAST
+} virDomainDiskDetectZeroes;
-- 
2.41.0



[PATCH 09/22] qemublocktest: Use "target only" mode in 'testJSONtoJSON' and 'testBackingXMLjsonXML'

2023-10-25 Thread Peter Krempa
Both tests pass a disk source definition which didn't go through the
preparation steps and thus contains only the target information that
were originally present, thus we should be using the
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY flag.

For the same reason QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY
used in 'testJSONtoJSON' doesn't make sense.

Signed-off-by: Peter Krempa 
---
 tests/qemublocktest.c| 4 ++--
 tests/qemublocktestdata/jsontojson/curl-libguestfs-out.json  | 5 ++---
 .../jsontojson/ssh-passthrough-libguestfs-out.json   | 4 +---
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index addd646071..ce76150200 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -59,7 +59,7 @@ testBackingXMLjsonXML(const void *args)
 g_autoptr(virStorageSource) xmlsrc = NULL;
 g_autoptr(virStorageSource) jsonsrc = NULL;
 g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER;
-unsigned int backendpropsflags = 0;
+unsigned int backendpropsflags = 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY;

 if (data->legacy)
 backendpropsflags |= QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY;
@@ -157,7 +157,7 @@ testJSONtoJSON(const void *args)
 }

 if (!(jsonsrcout = qemuBlockStorageSourceGetBackendProps(src,
- 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY))) {
+ 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_TARGET_ONLY))) {
 fprintf(stderr, "failed to format disk source json\n");
 return -1;
 }
diff --git a/tests/qemublocktestdata/jsontojson/curl-libguestfs-out.json 
b/tests/qemublocktestdata/jsontojson/curl-libguestfs-out.json
index e130c7bd3c..8cfacb5bc8 100644
--- a/tests/qemublocktestdata/jsontojson/curl-libguestfs-out.json
+++ b/tests/qemublocktestdata/jsontojson/curl-libguestfs-out.json
@@ -2,8 +2,7 @@
   "driver": "https",
   "url": "https://test.host:443/whatever.img;,
   "sslverify": false,
+  "cookie": "some_cookie=\"some_value_or_whatever\"",
   "timeout": 2000,
-  "readahead": 65536,
-  "auto-read-only": true,
-  "discard": "unmap"
+  "readahead": 65536
 }
diff --git 
a/tests/qemublocktestdata/jsontojson/ssh-passthrough-libguestfs-out.json 
b/tests/qemublocktestdata/jsontojson/ssh-passthrough-libguestfs-out.json
index 1f6032deb4..7855917e2e 100644
--- a/tests/qemublocktestdata/jsontojson/ssh-passthrough-libguestfs-out.json
+++ b/tests/qemublocktestdata/jsontojson/ssh-passthrough-libguestfs-out.json
@@ -8,7 +8,5 @@
   "user": "testuser",
   "host-key-check": {
 "mode": "none"
-  },
-  "auto-read-only": true,
-  "discard": "unmap"
+  }
 }
-- 
2.41.0



[PATCH 02/22] qemu: migration: No longer avoid 'auto-read-only' option for migration

2023-10-25 Thread Peter Krempa
The 'auto-read-only' blockdev option is available in all supported qemu
versions so we can remove the migration hack which disabled it.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 8 ++--
 src/qemu/qemu_block.h | 3 +--
 src/qemu/qemu_command.c   | 2 +-
 src/qemu/qemu_migration.c | 5 +
 4 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 0d252552de..e706bb7369 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1513,14 +1513,10 @@ 
qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachData *data)
  */
 qemuBlockStorageSourceAttachData *
 qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSource *src,
-virStorageSource *backingStore,
-bool autoreadonly)
+virStorageSource *backingStore)
 {
 g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
-unsigned int backendpropsflags = 0;
-
-if (autoreadonly)
-backendpropsflags |= 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY;
+unsigned int backendpropsflags = 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_AUTO_READONLY;

 data = g_new0(qemuBlockStorageSourceAttachData, 1);

diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 7008a4e7da..7bb83d8d44 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -134,8 +134,7 @@ 
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockStorageSourceAttachData,

 qemuBlockStorageSourceAttachData *
 qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSource *src,
-virStorageSource *backingStore,
-bool autoreadonly);
+virStorageSource *backingStore);

 qemuBlockStorageSourceAttachData *
 qemuBlockStorageSourceDetachPrepare(virStorageSource *src);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d40d3a4e13..ba21976956 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -10937,7 +10937,7 @@ 
qemuBuildStorageSourceChainAttachPrepareBlockdevOne(qemuBlockStorageSourceChainD
 {
 g_autoptr(qemuBlockStorageSourceAttachData) elem = NULL;

-if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(src, 
backingStore, true)))
+if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(src, 
backingStore)))
 return -1;

 if (qemuBuildStorageSourceAttachPrepareCommon(src, elem) < 0)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 76da981d08..ac58aa1a8c 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1045,11 +1045,8 @@ qemuMigrationSrcNBDStorageCopyBlockdev(virDomainObj *vm,
 
tlsAlias, tlsHostname)))
 return -1;

-/* Migration via blockdev-mirror was supported sooner than the 
auto-read-only
- * feature was added to qemu */
 if (!(data = qemuBlockStorageSourceAttachPrepareBlockdev(copysrc,
- 
copysrc->backingStore,
- false)))
+ 
copysrc->backingStore)))
 return -1;

 if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_MIGRATION_OUT) < 0)
-- 
2.41.0



[PATCH 01/22] qemuxml2(argv|xml)test: Add network backed disk type='sd'

2023-10-25 Thread Peter Krempa
Add a few examples of SD cards backed with network storage to capture
the current state as the formatter code is about to be refactored.

Signed-off-by: Peter Krempa 
---
 .../disk-arm-virtio-sd.aarch64-latest.args   |  2 ++
 tests/qemuxml2argvdata/disk-arm-virtio-sd.xml| 16 
 .../disk-arm-virtio-sd.aarch64-latest.xml| 16 
 3 files changed, 34 insertions(+)

diff --git a/tests/qemuxml2argvdata/disk-arm-virtio-sd.aarch64-latest.args 
b/tests/qemuxml2argvdata/disk-arm-virtio-sd.aarch64-latest.args
index 5d841604fb..00fdd1759e 100644
--- a/tests/qemuxml2argvdata/disk-arm-virtio-sd.aarch64-latest.args
+++ b/tests/qemuxml2argvdata/disk-arm-virtio-sd.aarch64-latest.args
@@ -33,6 +33,8 @@ 
XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-armtest/.config \
 -dtb /arm.dtb \
 -usb \
 -drive file=/arm-sd.qcow2,format=qcow2,if=sd,index=0 \
+-drive 
file.driver=nbd,file.server.type=inet,file.server.host=localhost,file.server.port=10809,file.export=export,format=qcow2,if=sd,index=1
 \
+-drive 
file.driver=gluster,file.volume=Volume3,file.path=Image.qcow2,file.server.0.type=inet,file.server.0.host=example.org,file.server.0.port=6000,file.server.1.type=inet,file.server.1.host=example.org,file.server.1.port=24007,file.server.2.type=unix,file.server.2.path=/path/to/sock,file.debug=4,format=qcow2,if=sd,index=2
 \
 -blockdev 
'{"driver":"file","filename":"/arm-virtio.qcow2","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}'
 \
 -blockdev 
'{"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2","file":"libvirt-1-storage"}'
 \
 -device 
'{"driver":"virtio-blk-device","drive":"libvirt-1-format","id":"virtio-disk0"}' 
\
diff --git a/tests/qemuxml2argvdata/disk-arm-virtio-sd.xml 
b/tests/qemuxml2argvdata/disk-arm-virtio-sd.xml
index 45a2192d48..9315c12c76 100644
--- a/tests/qemuxml2argvdata/disk-arm-virtio-sd.xml
+++ b/tests/qemuxml2argvdata/disk-arm-virtio-sd.xml
@@ -26,6 +26,22 @@
   
   
 
+
+  
+  
+
+  
+  
+
+
+  
+  
+
+
+
+  
+  
+
 
   
   
diff --git a/tests/qemuxml2xmloutdata/disk-arm-virtio-sd.aarch64-latest.xml 
b/tests/qemuxml2xmloutdata/disk-arm-virtio-sd.aarch64-latest.xml
index 962dc8f367..b9d412d3fb 100644
--- a/tests/qemuxml2xmloutdata/disk-arm-virtio-sd.aarch64-latest.xml
+++ b/tests/qemuxml2xmloutdata/disk-arm-virtio-sd.aarch64-latest.xml
@@ -30,6 +30,22 @@
   
   
 
+
+  
+  
+
+  
+  
+
+
+  
+  
+
+
+
+  
+  
+
 
   
   
-- 
2.41.0



[PATCH 04/22] qemuBlockStorageSourceGetBackendProps: Remove unnecessary indent for non-nbdkit code path

2023-10-25 Thread Peter Krempa
Formatting of the 'nbdkit' driven backend breaks out of the switch
statement so we don't need to have an unnecessary block and indentation
level for the case when nbdkit is not in use.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 132 +-
 1 file changed, 66 insertions(+), 66 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index e706bb7369..3be12b47e3 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1028,75 +1028,75 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 return NULL;

 case VIR_STORAGE_TYPE_NETWORK:
-/* prefer using nbdkit for sources that are supported */
+/* prefer using nbdkit if configured for sources that are supported */
 if ((fileprops = qemuBlockStorageSourceGetNbdkitProps(src))) {
 driver = "nbd";
 break;
-} else {
-switch ((virStorageNetProtocol) src->protocol) {
-case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
-driver = "gluster";
-if (!(fileprops = 
qemuBlockStorageSourceGetGlusterProps(src, onlytarget)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_VXHS:
-driver = "vxhs";
-if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src, 
onlytarget)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_HTTP:
-case VIR_STORAGE_NET_PROTOCOL_HTTPS:
-case VIR_STORAGE_NET_PROTOCOL_FTP:
-case VIR_STORAGE_NET_PROTOCOL_FTPS:
-case VIR_STORAGE_NET_PROTOCOL_TFTP:
-driver = virStorageNetProtocolTypeToString(src->protocol);
-if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src, 
onlytarget)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_ISCSI:
-driver = "iscsi";
-if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src, 
onlytarget)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_NBD:
-driver = "nbd";
-if (!(fileprops = qemuBlockStorageSourceGetNBDProps(src, 
onlytarget)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_RBD:
-driver = "rbd";
-if (!(fileprops = qemuBlockStorageSourceGetRBDProps(src, 
onlytarget)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
-driver = "sheepdog";
-if (!(fileprops = 
qemuBlockStorageSourceGetSheepdogProps(src)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_SSH:
-driver = "ssh";
-if (!(fileprops = qemuBlockStorageSourceGetSshProps(src)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_NFS:
-driver = "nfs";
-if (!(fileprops = qemuBlockStorageSourceGetNFSProps(src)))
-return NULL;
-break;
-
-case VIR_STORAGE_NET_PROTOCOL_NONE:
-case VIR_STORAGE_NET_PROTOCOL_LAST:
-virReportEnumRangeError(virStorageNetProtocol, 
src->protocol);
-return NULL;
-}
+}
+
+switch ((virStorageNetProtocol) src->protocol) {
+case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+driver = "gluster";
+if (!(fileprops = qemuBlockStorageSourceGetGlusterProps(src, 
onlytarget)))
+return NULL;
+break;
+
+case VIR_STORAGE_NET_PROTOCOL_VXHS:
+driver = "vxhs";
+if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src, 
onlytarget)))
+return NULL;
+break;
+
+case VIR_STORAGE_NET_PROTOCOL_HTTP:
+case VIR_STORAGE_NET_PROTOCOL_HTTPS:
+case VIR_STORAGE_NET_PROTOCOL_FTP:
+case VIR_STORAGE_NET_PROTOCOL_FTPS:
+case VIR_STORAGE_NET_PROTOCOL_TFTP:
+driver = virStorageNetProtocolTypeToString(src->protocol);
+if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src, 
onlytarget)))
+return NULL;
+break;
+
+case VIR_STORAGE_NET_PROTOCOL_ISCSI:
+driver = "iscsi";
+if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src, 
onlytarget)))
+r

[PATCH 03/22] qemuBuildDriveSourceStr: Absorb only use of qemuDiskSourceGetProps

2023-10-25 Thread Peter Krempa
'qemuBuildDriveSourceStr' used to build the legacy -drive commandline
for SD cards is the only user of qemuDiskSourceGetProps. Move the helper
directly inline.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_command.c | 39 +++
 1 file changed, 11 insertions(+), 28 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ba21976956..dbef8d0068 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1572,30 +1572,6 @@ qemuDiskBusIsSD(int bus)
 }


-/**
- * qemuDiskSourceGetProps:
- * @src: disk source struct
- *
- * Returns the disk source struct wrapped so that it can be used as disk source
- * directly by converting it from json.
- */
-static virJSONValue *
-qemuDiskSourceGetProps(virStorageSource *src)
-{
-g_autoptr(virJSONValue) props = NULL;
-virJSONValue *ret = NULL;
-
-if (!(props = qemuBlockStorageSourceGetBackendProps(src,
-
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY)))
-return NULL;
-
-if (virJSONValueObjectAdd(, "a:file", , NULL) < 0)
-return NULL;
-
-return ret;
-}
-
-
 static int
 qemuBuildDriveSourceStr(virDomainDiskDef *disk,
 virBuffer *buf)
@@ -1603,7 +1579,6 @@ qemuBuildDriveSourceStr(virDomainDiskDef *disk,
 virStorageType actualType = virStorageSourceGetActualType(disk->src);
 qemuDomainStorageSourcePrivate *srcpriv = 
QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
 qemuDomainSecretInfo **encinfo = NULL;
-g_autoptr(virJSONValue) srcprops = NULL;
 bool rawluks = false;

 if (srcpriv)
@@ -1624,14 +1599,22 @@ qemuBuildDriveSourceStr(virDomainDiskDef *disk,
 virQEMUBuildBufferEscapeComma(buf, disk->src->path);
 break;

-case VIR_STORAGE_TYPE_NETWORK:
-if (!(srcprops = qemuDiskSourceGetProps(disk->src)))
+case VIR_STORAGE_TYPE_NETWORK: {
+g_autoptr(virJSONValue) props = NULL;
+g_autoptr(virJSONValue) wrap = NULL;
+
+if (!(props = qemuBlockStorageSourceGetBackendProps(disk->src,
+
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY)))
 return -1;

-if (virQEMUBuildCommandLineJSON(srcprops, buf, NULL,
+if (virJSONValueObjectAdd(, "a:file", , NULL) < 0)
+return -1;
+
+if (virQEMUBuildCommandLineJSON(wrap, buf, NULL,
 
virQEMUBuildCommandLineJSONArrayNumbered) < 0)
 return -1;
 break;
+}

 case VIR_STORAGE_TYPE_VOLUME:
 case VIR_STORAGE_TYPE_NVME:
-- 
2.41.0



[PATCH 13/31] qemuDomainGetStatsBlockExportDisk: Use 'storage' node name accessors

2023-10-16 Thread Peter Krempa
In all cases we want to probe stats from the 'storage' layer as we're
interested in the 'threshold' value, which we set there.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_driver.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f3c9730cd8..e2fe2016af 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17349,7 +17349,7 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDef 
*disk,
 if (QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
 frontendalias = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
 backendalias = n->nodeformat;
-backendstoragealias = n->nodestorage;
+backendstoragealias = qemuBlockStorageSourceGetStorageNodename(n);
 } else {
 /* alias may be NULL if the VM is not running */
 if (disk->info.alias &&
@@ -17408,7 +17408,7 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDef 
*disk,
stats) < 0)
 return -1;

-if 
(qemuDomainGetStatsBlockExportBackendStorage(disk->mirror->nodestorage,
+if 
(qemuDomainGetStatsBlockExportBackendStorage(qemuBlockStorageSourceGetStorageNodename(disk->mirror),
 stats, *recordnr,
 params) < 0)
 return -1;
@@ -17437,7 +17437,7 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDef 
*disk,
stats) < 0)
 return -1;

-if 
(qemuDomainGetStatsBlockExportBackendStorage(backupdisk->store->nodestorage,
+if 
(qemuDomainGetStatsBlockExportBackendStorage(qemuBlockStorageSourceGetStorageNodename(backupdisk->store),
 stats, 
*recordnr,
 params) < 
0)
 return -1;
-- 
2.41.0



[PATCH 17/31] qemu: block: Add accessors for storage source effective nodename

2023-10-16 Thread Peter Krempa
Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 14 ++
 src/qemu/qemu_block.h |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index cba1fb1c1e..10c2c0104b 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -86,6 +86,20 @@ qemuBlockStorageSourceSetFormatNodename(virStorageSource 
*src,
 }


+/**
+ * qemuBlockStorageSourceGetEffectiveNodename:
+ * @src: virStorageSource to get the effective nodename of
+ *
+ * Gets the nodename that exposes the guest visible data. This function always
+ * returns a name.
+ */
+const char *
+qemuBlockStorageSourceGetEffectiveNodename(virStorageSource *src)
+{
+return src->nodeformat;
+}
+
+
 /**
  * qemuBlockStorageSourceGetEffectiveStorageNodename:
  * @src: virStorageSource to get the effective nodename of
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 6ed0aa85b2..7008a4e7da 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -43,6 +43,9 @@ qemuBlockStorageSourceGetStorageNodename(virStorageSource 
*src);
 const char *
 qemuBlockStorageSourceGetFormatNodename(virStorageSource *src);

+const char *
+qemuBlockStorageSourceGetEffectiveNodename(virStorageSource *src);
+

 typedef struct qemuBlockNodeNameBackingChainData 
qemuBlockNodeNameBackingChainData;
 struct qemuBlockNodeNameBackingChainData {
-- 
2.41.0



[PATCH 11/31] qemu: Refactor storage backend attach/detach setup code to use 'storage' nodename accessors

2023-10-16 Thread Peter Krempa
Refactor the code settin up data structures used to attach/detach disks
and SCSI hostdevs.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c   | 7 ---
 src/qemu/qemu_command.c | 6 +++---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 1fc36569a9..7355cb0b5e 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1484,7 +1484,7 @@ 
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSource *src,
  
backendpropsflags)))
 return NULL;

-data->storageNodeName = src->nodestorage;
+data->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
 data->formatNodeName = src->nodeformat;

 if (qemuBlockStorageSourceNeedsStorageSliceLayer(src)) {
@@ -1705,7 +1705,7 @@ qemuBlockStorageSourceDetachPrepare(virStorageSource *src)

 data->formatNodeName = src->nodeformat;
 data->formatAttached = true;
-data->storageNodeName = src->nodestorage;
+data->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
 data->storageAttached = true;

 /* 'raw' format doesn't need the extra 'raw' layer when slicing, thus
@@ -1899,7 +1899,8 @@ qemuBlockStorageSourceDetachOneBlockdev(virDomainObj *vm,
 ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), src->nodeformat);

 if (ret == 0)
-ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), 
src->nodestorage);
+ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm),
+ 
qemuBlockStorageSourceGetStorageNodename(src));

 qemuDomainObjExitMonitor(vm);

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8a7b80719f..40de712c61 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5049,7 +5049,7 @@ qemuBuildHostdevSCSIDetachPrepare(virDomainHostdevDef 
*hostdev,
 }

 srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
-ret->storageNodeName = src->nodestorage;
+ret->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
 ret->storageAttached = true;

 if (srcpriv && srcpriv->secinfo)
@@ -5083,8 +5083,8 @@ qemuBuildHostdevSCSIAttachPrepare(virDomainHostdevDef 
*hostdev,
 return NULL;
 }

-ret->storageNodeName = src->nodestorage;
-*backendAlias = src->nodestorage;
+ret->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
+*backendAlias = qemuBlockStorageSourceGetStorageNodename(src);

 if (!(ret->storageProps = qemuBlockStorageSourceGetBackendProps(src,
 
QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)))
-- 
2.41.0



[PATCH 08/31] qemu: domain: Convert the status XML code for 'storage' nodenames to new accessors

2023-10-16 Thread Peter Krempa
Use the new accessors in the private XML formatters and parsers and the
recovery code.

Specifically in all instances we use the proper (not effective) storage
nodename. In the virStorageSource private data it is what we need to
store. In blockjobs status XML it simply serves us to find the
appropriate 'virStorageSource' struct so using the storage layer node
name is simpler.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_domain.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index f891defa91..78dc99d243 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2000,7 +2000,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
 int enccount;
 xmlNodePtr nbdkitnode = NULL;

-src->nodestorage = 
virXPathString("string(./nodenames/nodename[@type='storage']/@name)", ctxt);
+qemuBlockStorageSourceSetStorageNodename(src, 
virXPathString("string(./nodenames/nodename[@type='storage']/@name)", ctxt));
 src->nodeformat = 
virXPathString("string(./nodenames/nodename[@type='format']/@name)", ctxt);
 src->tlsAlias = virXPathString("string(./objects/TLSx509/@alias)", ctxt);

@@ -2111,7 +2111,7 @@ qemuStorageSourcePrivateDataFormat(virStorageSource *src,
 g_auto(virBuffer) objectsChildBuf = VIR_BUFFER_INIT_CHILD(buf);
 g_auto(virBuffer) fdsetsChildBuf = VIR_BUFFER_INIT_CHILD(buf);

-virBufferEscapeString(, "\n", src->nodestorage);
+virBufferEscapeString(, "\n", qemuBlockStorageSourceGetStorageNodename(src));
 virBufferEscapeString(, "\n", src->nodeformat);

 if (src->sliceStorage)
@@ -2288,13 +2288,16 @@ qemuDomainPrivateBlockJobFormatCommit(qemuBlockJobData 
*job,
 g_auto(virBuffer) disabledBitmapsBuf = VIR_BUFFER_INIT_CHILD(buf);

 if (job->data.commit.base)
-virBufferAsprintf(buf, "\n", 
job->data.commit.base->nodestorage);
+virBufferAsprintf(buf, "\n",
+  
qemuBlockStorageSourceGetStorageNodename(job->data.commit.base));

 if (job->data.commit.top)
-virBufferAsprintf(buf, "\n", 
job->data.commit.top->nodestorage);
+virBufferAsprintf(buf, "\n",
+  
qemuBlockStorageSourceGetStorageNodename(job->data.commit.top));

 if (job->data.commit.topparent)
-virBufferAsprintf(buf, "\n", 
job->data.commit.topparent->nodestorage);
+virBufferAsprintf(buf, "\n",
+  
qemuBlockStorageSourceGetStorageNodename(job->data.commit.topparent));

 if (job->data.commit.deleteCommittedImages)
 virBufferAddLit(buf, "\n");
@@ -2357,7 +2360,8 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void 
*payload,
 switch ((qemuBlockJobType) job->type) {
 case QEMU_BLOCKJOB_TYPE_PULL:
 if (job->data.pull.base)
-virBufferAsprintf(, "\n", 
job->data.pull.base->nodestorage);
+virBufferAsprintf(, "\n",
+  
qemuBlockStorageSourceGetStorageNodename(job->data.pull.base));
 break;

 case QEMU_BLOCKJOB_TYPE_COMMIT:
@@ -6060,8 +6064,8 @@ 
qemuDomainDeviceHostdevDefPostParseRestoreBackendAlias(virDomainHostdevDef *host
 return -1;
 }

-if (!src->nodestorage)
-src->nodestorage = g_strdup_printf("libvirt-%s-backend", 
hostdev->info->alias);
+if (!qemuBlockStorageSourceGetStorageNodename(src))
+qemuBlockStorageSourceSetStorageNodename(src, 
g_strdup_printf("libvirt-%s-backend", hostdev->info->alias));

 return 0;
 }
-- 
2.41.0



[PATCH 26/31] qemu: Use 'format' nodename accessors for block dirty bitmap operations

2023-10-16 Thread Peter Krempa
In most cases the bitmap operations are relevant only on qcow2 images
thus the 'format' layer will be present. Although in certain specific
cases temporary bitmaps can be created on top of other images as well,
thus we use the 'effective' bitmap name in all cases for bitmap
operations.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c  | 27 ++-
 src/qemu/qemu_blockjob.c   |  4 ++--
 src/qemu/qemu_checkpoint.c |  9 +
 src/qemu/qemu_driver.c |  7 ---
 src/qemu/qemu_snapshot.c   |  6 --
 5 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 4c1a711dd3..edc8edcb70 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -2807,7 +2807,8 @@ qemuBlockNamedNodeDataGetBitmapByName(GHashTable 
*blockNamedNodeData,
 qemuBlockNamedNodeData *nodedata;
 size_t i;

-if (!(nodedata = virHashLookup(blockNamedNodeData, src->nodeformat)))
+if (!(nodedata = virHashLookup(blockNamedNodeData,
+   
qemuBlockStorageSourceGetEffectiveNodename(src
 return NULL;

 for (i = 0; i < nodedata->nbitmaps; i++) {
@@ -2863,7 +2864,7 @@ qemuBlockGetBitmapMergeActionsGetBitmaps(virStorageSource 
*topsrc,
 /* for now it doesn't make sense to consider bitmaps which are not present
  * in @topsrc as we can't recreate a bitmap for a layer if it's missing */

-if (!(entry = virHashLookup(blockNamedNodeData, topsrc->nodeformat)))
+if (!(entry = virHashLookup(blockNamedNodeData, 
qemuBlockStorageSourceGetEffectiveNodename(topsrc
 return NULL;

 for (i = 0; i < entry->nbitmaps; i++) {
@@ -2972,7 +2973,7 @@ qemuBlockGetBitmapMergeActions(virStorageSource *topsrc,
 granularity = bitmap->granularity;

 if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(merge,
- n->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(n),
  bitmap->name) 
< 0)
 return -1;
 }
@@ -2982,7 +2983,7 @@ qemuBlockGetBitmapMergeActions(virStorageSource *topsrc,
  target, 
curbitmap))) {

 if (qemuMonitorTransactionBitmapAdd(act,
-target->nodeformat,
+
qemuBlockStorageSourceGetEffectiveNodename(target),
 mergebitmapname,
 mergebitmappersistent,
 mergebitmapdisabled,
@@ -2992,18 +2993,18 @@ qemuBlockGetBitmapMergeActions(virStorageSource *topsrc,

 if (writebitmapsrc &&
 qemuMonitorTransactionBitmapMergeSourceAddBitmap(merge,
- 
writebitmapsrc->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(writebitmapsrc),
  
"libvirt-tmp-activewrite") < 0)
 return -1;

-if (qemuMonitorTransactionBitmapMerge(act, target->nodeformat,
+if (qemuMonitorTransactionBitmapMerge(act, 
qemuBlockStorageSourceGetEffectiveNodename(target),
   mergebitmapname, ) < 0)
 return -1;
 }

  done:
 if (writebitmapsrc &&
-qemuMonitorTransactionBitmapRemove(act, writebitmapsrc->nodeformat,
+qemuMonitorTransactionBitmapRemove(act, 
qemuBlockStorageSourceGetEffectiveNodename(writebitmapsrc),
"libvirt-tmp-activewrite") < 0)
 return -1;

@@ -3578,8 +3579,8 @@ qemuBlockCommit(virDomainObj *vm,
 rc = qemuMonitorBlockCommit(priv->mon,
 qemuDomainDiskGetTopNodename(disk),
 job->name,
-topSource->nodeformat,
-baseSource->nodeformat,
+
qemuBlockStorageSourceGetEffectiveNodename(topSource),
+
qemuBlockStorageSourceGetEffectiveNodename(baseSource),
 backingPath, bandwidth,
 autofinalize);

@@ -3663,7 +3664,7 @@ qemuBlockPivot(virDomainObj *vm,
 bitmapactions = virJSONValueNewArray();

 if (qemuMonitorTransactionBitmapAdd(bitmapactions,
-disk->mirror->nodeformat,
+
qemuBlockStorageSourceGetE

[PATCH 21/31] qemu: block: Use 'format' nodename accessors in '-blockdev' setup code

2023-10-16 Thread Peter Krempa
Convert the main -blockdev JSON object setup code to use the new
accessors. In these we use mainly the real 'format' layer node name.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 0fa5b6e55d..852028f014 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1282,7 +1282,7 @@ 
qemuBlockStorageSourceGetBlockdevFormatCommonProps(virStorageSource *src)
 
src->detect_zeroes);
 g_autoptr(virJSONValue) props = NULL;

-if (qemuBlockNodeNameValidate(src->nodeformat) < 0)
+if 
(qemuBlockNodeNameValidate(qemuBlockStorageSourceGetFormatNodename(src)) < 0)
 return NULL;

 if (src->discard)
@@ -1296,7 +1296,7 @@ 
qemuBlockStorageSourceGetBlockdevFormatCommonProps(virStorageSource *src)
  */

 if (virJSONValueObjectAdd(,
-  "s:node-name", src->nodeformat,
+  "s:node-name", 
qemuBlockStorageSourceGetFormatNodename(src),
   "b:read-only", src->readonly,
   "S:discard", discard,
   "S:detect-zeroes", detectZeroes,
@@ -1530,7 +1530,7 @@ 
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSource *src,
 return NULL;

 data->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
-data->formatNodeName = src->nodeformat;
+data->formatNodeName = qemuBlockStorageSourceGetFormatNodename(src);

 if (qemuBlockStorageSourceNeedsStorageSliceLayer(src)) {
 if (!(data->storageSliceProps = 
qemuBlockStorageSourceGetBlockdevStorageSliceProps(src)))
@@ -1748,7 +1748,7 @@ qemuBlockStorageSourceDetachPrepare(virStorageSource *src)

 data = g_new0(qemuBlockStorageSourceAttachData, 1);

-data->formatNodeName = src->nodeformat;
+data->formatNodeName = qemuBlockStorageSourceGetFormatNodename(src);
 data->formatAttached = true;
 data->storageNodeName = qemuBlockStorageSourceGetStorageNodename(src);
 data->storageAttached = true;
@@ -1941,7 +1941,8 @@ qemuBlockStorageSourceDetachOneBlockdev(virDomainObj *vm,
 if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
 return -1;

-ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), src->nodeformat);
+ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm),
+ qemuBlockStorageSourceGetFormatNodename(src));

 if (ret == 0)
 ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm),
@@ -1959,8 +1960,8 @@ qemuBlockSnapshotAddBlockdev(virJSONValue *actions,
  virStorageSource *newsrc)
 {
 return qemuMonitorTransactionSnapshotBlockdev(actions,
-  disk->src->nodeformat,
-  newsrc->nodeformat);
+  
qemuBlockStorageSourceGetEffectiveNodename(disk->src),
+  
qemuBlockStorageSourceGetFormatNodename(newsrc));
 }


-- 
2.41.0



[PATCH 23/31] tests: Use 'format' layer nodename accessors in test code

2023-10-16 Thread Peter Krempa
The test code cares mostly about the actual layer nodenames thus,
appropriate accessors are used.

Signed-off-by: Peter Krempa 
---
 tests/qemublocktest.c   | 10 +-
 tests/qemumonitorjsontest.c |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index 9a72a67ce2..addd646071 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -241,7 +241,7 @@ testQemuDiskXMLToJSONFakeSecrets(virStorageSource *src)
 srcpriv->encinfo[0] = g_new0(qemuDomainSecretInfo, 1);

 srcpriv->encinfo[0]->alias = g_strdup_printf("%s-encalias",
- NULLSTR(src->nodeformat));
+ 
qemuBlockStorageSourceGetFormatNodename(src));
 srcpriv->enccount = 1;
 }

@@ -653,7 +653,7 @@ testQemuBitmapListPrint(const char *title,

 for (; next; next = next->next) {
 virStorageSource *src = next->data;
-virBufferAsprintf(buf, "%s\n", src->nodeformat);
+virBufferAsprintf(buf, "%s\n", 
qemuBlockStorageSourceGetFormatNodename(src));
 }
 }

@@ -668,7 +668,7 @@ testQemuBackupIncrementalBitmapCalculateGetFakeImage(size_t 
idx)
ret->format = VIR_STORAGE_FILE_QCOW2;
ret->path = g_strdup_printf("/image%zu", idx);
qemuBlockStorageSourceSetStorageNodename(ret, 
g_strdup_printf("libvirt-%zu-storage", idx));
-   ret->nodeformat = g_strdup_printf("libvirt-%zu-format", idx);
+   qemuBlockStorageSourceSetFormatNodename(ret, 
g_strdup_printf("libvirt-%zu-format", idx));

return ret;
 }
@@ -741,7 +741,7 @@ testQemuBackupIncrementalBitmapCalculate(const void *opaque)
 }

 target = virStorageSourceNew();
-target->nodeformat = g_strdup_printf("target_node");
+qemuBlockStorageSourceSetFormatNodename(target, 
g_strdup_printf("target_node"));

 if (qemuBackupDiskPrepareOneBitmapsChain(data->chain,
  target,
@@ -872,7 +872,7 @@ testQemuBlockBitmapBlockcopy(const void *opaque)
 g_autoptr(virStorageSource) fakemirror = virStorageSourceNew();
 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;

-fakemirror->nodeformat = g_strdup("mirror-format-node");
+qemuBlockStorageSourceSetFormatNodename(fakemirror, 
g_strdup("mirror-format-node"));

 expectpath = g_strdup_printf("%s/%s%s-out.json", abs_srcdir,
  blockcopyPrefix, data->name);
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 6b82e3841b..6293b416bd 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -2600,7 +2600,7 @@ testQemuMonitorJSONBlockdevReopen(const void *opaque)

 src->format = VIR_STORAGE_FILE_QCOW2;
 src->readonly = true;
-src->nodeformat = g_strdup("test node");
+qemuBlockStorageSourceSetFormatNodename(src, g_strdup("test node"));
 qemuBlockStorageSourceSetStorageNodename(src, g_strdup("backing 
nodename"));
 src->backingStore = virStorageSourceNew();

-- 
2.41.0



[PATCH 14/31] qemuDomainSetBlockThreshold: Use 'storage' node name accessor

2023-10-16 Thread Peter Krempa
We need to keep setting the block threshold on the real storage layer
per semantics of the API. Use the appropriate accessor.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_driver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e2fe2016af..6d95711cbc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18682,7 +18682,7 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
 goto endjob;
 }

-nodename = g_strdup(src->nodestorage);
+nodename = g_strdup(qemuBlockStorageSourceGetStorageNodename(src));

 qemuDomainObjEnterMonitor(vm);
 rc = qemuMonitorSetBlockThreshold(priv->mon, nodename, threshold);
-- 
2.41.0



[PATCH 20/31] qemu: blockjob: Use 'format' nodename accessors for job naming

2023-10-16 Thread Peter Krempa
Use the effective nodename for naming the job as we use that one now.
It doesn't matter too much which one we pick, because it's used just for
the name of the job, which we preserve in the status XML.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_blockjob.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 12f3d59df5..cb9948ae2a 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -252,7 +252,8 @@ qemuBlockJobDiskNewPull(virDomainObj *vm,
 unsigned int jobflags)
 {
 g_autoptr(qemuBlockJobData) job = NULL;
-g_autofree char *jobname = g_strdup_printf("pull-%s-%s", disk->dst, 
disk->src->nodeformat);
+g_autofree char *jobname = g_strdup_printf("pull-%s-%s", disk->dst,
+   
qemuBlockStorageSourceGetEffectiveNodename(disk->src));

 if (!(job = qemuBlockJobDataNew(QEMU_BLOCKJOB_TYPE_PULL, jobname)))
 return NULL;
@@ -278,7 +279,8 @@ qemuBlockJobDiskNewCommit(virDomainObj *vm,
   unsigned int jobflags)
 {
 g_autoptr(qemuBlockJobData) job = NULL;
-g_autofree char *jobname = g_strdup_printf("commit-%s-%s", disk->dst, 
top->nodeformat);
+g_autofree char *jobname = g_strdup_printf("commit-%s-%s", disk->dst,
+   
qemuBlockStorageSourceGetEffectiveNodename(top));
 qemuBlockJobType jobtype = QEMU_BLOCKJOB_TYPE_COMMIT;

 if (topparent == NULL)
@@ -309,7 +311,7 @@ qemuBlockJobNewCreate(virDomainObj *vm,
 {
 g_autoptr(qemuBlockJobData) job = NULL;
 g_autofree char *jobname = NULL;
-const char *nodename = src->nodeformat;
+const char *nodename = qemuBlockStorageSourceGetEffectiveNodename(src);

 if (storage)
 nodename = qemuBlockStorageSourceGetStorageNodename(src);
@@ -340,7 +342,8 @@ qemuBlockJobDiskNewCopy(virDomainObj *vm,
 unsigned int jobflags)
 {
 g_autoptr(qemuBlockJobData) job = NULL;
-g_autofree char *jobname = g_strdup_printf("copy-%s-%s", disk->dst, 
disk->src->nodeformat);
+g_autofree char *jobname = g_strdup_printf("copy-%s-%s", disk->dst,
+   
qemuBlockStorageSourceGetEffectiveNodename(disk->src));

 if (!(job = qemuBlockJobDataNew(QEMU_BLOCKJOB_TYPE_COPY, jobname)))
 return NULL;
@@ -368,7 +371,8 @@ qemuBlockJobDiskNewBackup(virDomainObj *vm,
 g_autoptr(qemuBlockJobData) job = NULL;
 g_autofree char *jobname = NULL;

-jobname = g_strdup_printf("backup-%s-%s", disk->dst, 
disk->src->nodeformat);
+jobname = g_strdup_printf("backup-%s-%s", disk->dst,
+  
qemuBlockStorageSourceGetEffectiveNodename(disk->src));

 if (!(job = qemuBlockJobDataNew(QEMU_BLOCKJOB_TYPE_BACKUP, jobname)))
 return NULL;
-- 
2.41.0



[PATCH 19/31] qemu: backup: Use format nodename accessors

2023-10-16 Thread Peter Krempa
Both modified cases in this patch require the effective nodename as they
deal with the data being backed up.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_backup.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c
index e4db967e2c..857709b17e 100644
--- a/src/qemu/qemu_backup.c
+++ b/src/qemu/qemu_backup.c
@@ -335,9 +335,9 @@ qemuBackupDiskPrepareDataOnePush(virJSONValue *actions,
 syncmode = QEMU_MONITOR_TRANSACTION_BACKUP_SYNC_MODE_INCREMENTAL;

 if (qemuMonitorTransactionBackup(actions,
- dd->domdisk->src->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(dd->domdisk->src),
  dd->blockjob->name,
- dd->store->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(dd->store),
  dd->incrementalBitmap,
  syncmode) < 0)
 return -1;
@@ -355,9 +355,9 @@ qemuBackupDiskPrepareDataOnePull(virJSONValue *actions,
 dd->backupdisk->exportbitmap = g_strdup(dd->incrementalBitmap);

 if (qemuMonitorTransactionBackup(actions,
- dd->domdisk->src->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(dd->domdisk->src),
  dd->blockjob->name,
- dd->store->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(dd->store),
  NULL,
  
QEMU_MONITOR_TRANSACTION_BACKUP_SYNC_MODE_NONE) < 0)
 return -1;
-- 
2.41.0



[PATCH 25/31] qemu: driver: Convert disk stats code to use 'format' nodename accessors

2023-10-16 Thread Peter Krempa
I case of statistics we're interested in the statistics of the effective
bitmap whatever it happens to be.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_driver.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6d95711cbc..2d1d0bb3e2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9368,7 +9368,7 @@ qemuDomainBlocksStatsGather(virDomainObj *vm,

 /* capacity are reported only per node-name so we need to transfer 
them */
 if (disk && disk->src &&
-(capstats = virHashLookup(blockstats, disk->src->nodeformat))) {
+(capstats = virHashLookup(blockstats, 
qemuBlockStorageSourceGetEffectiveNodename(disk->src {
 (*retstats)->capacity = capstats->capacity;
 (*retstats)->physical = capstats->physical;
 (*retstats)->wr_highest_offset = capstats->wr_highest_offset;
@@ -17348,7 +17348,7 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDef 
*disk,

 if (QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
 frontendalias = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
-backendalias = n->nodeformat;
+backendalias = qemuBlockStorageSourceGetEffectiveNodename(n);
 backendstoragealias = qemuBlockStorageSourceGetStorageNodename(n);
 } else {
 /* alias may be NULL if the VM is not running */
@@ -17402,7 +17402,7 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDef 
*disk,
 return -1;

 if (qemuDomainGetStatsOneBlock(driver, cfg, dom, params,
-   disk->mirror->nodeformat,
+   
qemuBlockStorageSourceGetEffectiveNodename(disk->mirror),
disk->mirror,
*recordnr,
stats) < 0)
@@ -17431,7 +17431,7 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDef 
*disk,
 return -1;

 if (qemuDomainGetStatsOneBlock(driver, cfg, dom, params,
-   
backupdisk->store->nodeformat,
+   
qemuBlockStorageSourceGetEffectiveNodename(backupdisk->store),
backupdisk->store,
*recordnr,
stats) < 0)
-- 
2.41.0



[PATCH 24/31] qemu: Convert disk backend setup code to use 'format' nodename accessors

2023-10-16 Thread Peter Krempa
The disk backend setup code is concerned only about the effective
nodename. Doing this conversion will also simplify further changes
needed to drop the 'raw' layer in cases when it's not really needed.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c  | 6 +++---
 src/qemu/qemu_domain.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 852028f014..4c1a711dd3 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1980,7 +1980,7 @@ qemuBlockStorageGetCopyOnReadProps(virDomainDiskDef *disk)
 ignore_value(virJSONValueObjectAdd(,
"s:driver", "copy-on-read",
"s:node-name", priv->nodeCopyOnRead,
-   "s:file", disk->src->nodeformat,
+   "s:file", 
qemuBlockStorageSourceGetEffectiveNodename(disk->src),
"s:discard", "unmap",
NULL));

@@ -2735,10 +2735,10 @@ qemuBlockStorageSourceCreateDetectSize(GHashTable 
*blockNamedNodeData,
 {
 qemuBlockNamedNodeData *entry;

-if (!(entry = virHashLookup(blockNamedNodeData, templ->nodeformat))) {
+if (!(entry = virHashLookup(blockNamedNodeData, 
qemuBlockStorageSourceGetEffectiveNodename(templ {
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("failed to update capacity data for block node 
'%1$s'"),
-   templ->nodeformat);
+   qemuBlockStorageSourceGetEffectiveNodename(templ));
 return -1;
 }

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d8d3a17e55..995aa3f79c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -7891,7 +7891,7 @@ qemuDomainDiskGetTopNodename(virDomainDiskDef *disk)
 if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON)
 return priv->nodeCopyOnRead;

-return disk->src->nodeformat;
+return qemuBlockStorageSourceGetEffectiveNodename(disk->src);
 }


-- 
2.41.0



[PATCH 31/31] conf: Rename 'nodeformat' field of virStorageSource to 'nodenameformat'

2023-10-16 Thread Peter Krempa
While the name itself doesn't matter, this rename is done to prove that
all places using 'nodeformat' were converted to the appropriate
accessors.

Signed-off-by: Peter Krempa 
---
 src/conf/storage_source_conf.c | 4 ++--
 src/conf/storage_source_conf.h | 2 +-
 src/qemu/qemu_block.c  | 8 
 src/qemu/qemu_blockjob.c   | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index ea171f9945..f974a521b1 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -828,7 +828,7 @@ virStorageSourceCopy(const virStorageSource *src,
 def->backingStoreRawFormat = src->backingStoreRawFormat;
 def->snapshot = g_strdup(src->snapshot);
 def->configFile = g_strdup(src->configFile);
-def->nodeformat = g_strdup(src->nodeformat);
+def->nodenameformat = g_strdup(src->nodenameformat);
 def->nodenamestorage = g_strdup(src->nodenamestorage);
 def->compat = g_strdup(src->compat);
 def->tlsAlias = g_strdup(src->tlsAlias);
@@ -1169,7 +1169,7 @@ virStorageSourceClear(virStorageSource *def)
 virObjectUnref(def->privateData);

 VIR_FREE(def->nodenamestorage);
-VIR_FREE(def->nodeformat);
+VIR_FREE(def->nodenameformat);

 virStorageSourceBackingStoreClear(def);

diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index e9525c8f65..5a9b03b610 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -370,7 +370,7 @@ struct _virStorageSource {
 virStorageFileFormat backingStoreRawFormat;

 /* metadata that allows identifying given storage source */
-char *nodeformat;  /* name of the format handler object */
+char *nodenameformat;  /* name of the format handler object */
 char *nodenamestorage; /* name of the storage object */

 /* An optional setting to enable usage of TLS for the storage source */
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index fa31028db3..0d252552de 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -81,8 +81,8 @@ void
 qemuBlockStorageSourceSetFormatNodename(virStorageSource *src,
 char *nodename)
 {
-g_free(src->nodeformat);
-src->nodeformat = nodename;
+g_free(src->nodenameformat);
+src->nodenameformat = nodename;
 }


@@ -96,7 +96,7 @@ qemuBlockStorageSourceSetFormatNodename(virStorageSource *src,
 const char *
 qemuBlockStorageSourceGetEffectiveNodename(virStorageSource *src)
 {
-return src->nodeformat;
+return src->nodenameformat;
 }


@@ -141,7 +141,7 @@ qemuBlockStorageSourceGetStorageNodename(virStorageSource 
*src)
 const char *
 qemuBlockStorageSourceGetFormatNodename(virStorageSource *src)
 {
-return src->nodeformat;
+return src->nodenameformat;
 }


diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 0913a224e3..4b5b63d287 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -617,7 +617,7 @@ qemuBlockJobCleanStorageSourceRuntime(virStorageSource *src)
 VIR_FREE(src->relPath);
 VIR_FREE(src->backingStoreRaw);
 VIR_FREE(src->nodenamestorage);
-VIR_FREE(src->nodeformat);
+VIR_FREE(src->nodenameformat);
 VIR_FREE(src->tlsAlias);
 VIR_FREE(src->tlsCertdir);
 }
-- 
2.41.0



[PATCH 07/31] qemu: block: Use proper accessors for image formatting/creation code

2023-10-16 Thread Peter Krempa
Use 'qemuBlockStorageSourceGetEffectiveStorageNodename' in all the JSON
props formatters for setting up a 'blockdev-create' job of a format
layer.

In case of the blockjob name designator we're okay to use just the
storage layer nodename as that serves only to find the appropriate
entry.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c| 10 +-
 src/qemu/qemu_blockjob.c |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 0c9460f678..a98caa330e 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -2078,7 +2078,7 @@ 
qemuBlockStorageSourceCreateGetFormatPropsGeneric(virStorageSource *src,

 if (virJSONValueObjectAdd(,
   "s:driver", driver,
-  "s:file", src->nodestorage,
+  "s:file", 
qemuBlockStorageSourceGetEffectiveStorageNodename(src),
   "U:size", src->capacity,
   NULL) < 0)
 return -1;
@@ -2143,7 +2143,7 @@ 
qemuBlockStorageSourceCreateGetFormatPropsLUKS(virStorageSource *src,

 if (virJSONValueObjectAdd(,
   "s:driver", "luks",
-  "s:file", src->nodestorage,
+  "s:file", 
qemuBlockStorageSourceGetEffectiveStorageNodename(src),
   "U:size", src->capacity,
   NULL) < 0)
 return -1;
@@ -2200,7 +2200,7 @@ 
qemuBlockStorageSourceCreateGetFormatPropsQcow2(virStorageSource *src,

 if (virJSONValueObjectAdd(,
   "s:driver", "qcow2",
-  "s:file", src->nodestorage,
+  "s:file", 
qemuBlockStorageSourceGetEffectiveStorageNodename(src),
   "U:size", src->capacity,
   "S:version", qcow2version,
   "P:cluster-size", src->clusterSize,
@@ -2226,7 +2226,7 @@ 
qemuBlockStorageSourceCreateGetFormatPropsQcow(virStorageSource *src,

 if (virJSONValueObjectAdd(,
   "s:driver", "qcow",
-  "s:file", src->nodestorage,
+  "s:file", 
qemuBlockStorageSourceGetEffectiveStorageNodename(src),
   "U:size", src->capacity,
   NULL) < 0)
 return -1;
@@ -2249,7 +2249,7 @@ 
qemuBlockStorageSourceCreateGetFormatPropsQed(virStorageSource *src,

 if (virJSONValueObjectAdd(,
   "s:driver", "qed",
-  "s:file", src->nodestorage,
+  "s:file", 
qemuBlockStorageSourceGetEffectiveStorageNodename(src),
   "U:size", src->capacity,
   NULL) < 0)
 return -1;
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index f1d22df59f..25ac74d6c4 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -312,7 +312,7 @@ qemuBlockJobNewCreate(virDomainObj *vm,
 const char *nodename = src->nodeformat;

 if (storage)
-nodename = src->nodestorage;
+nodename = qemuBlockStorageSourceGetStorageNodename(src);

 jobname = g_strdup_printf("create-%s", nodename);

-- 
2.41.0



[PATCH 29/31] qemu: migration: Use 'format' nodename accessors in dirty bitmap migration

2023-10-16 Thread Peter Krempa
The persistent bitmaps are stored in the format layer, using 'effective'
bitmap name is the most reasonable approach in this case.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_migration.c| 11 ++-
 src/qemu/qemu_migration_cookie.c |  2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 949ef6d6d5..76da981d08 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2393,7 +2393,8 @@ 
qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(qemuMigrationCookie *mig,
 qemuMigrationBlockDirtyBitmapsDisk *disk;
 GSList *bitmaps = NULL;
 virDomainDiskDef *diskdef = vm->def->disks[i];
-qemuBlockNamedNodeData *nodedata = virHashLookup(blockNamedNodeData, 
diskdef->src->nodeformat);
+qemuBlockNamedNodeData *nodedata = virHashLookup(blockNamedNodeData,
+ 
qemuBlockStorageSourceGetEffectiveNodename(diskdef->src));
 size_t j;

 if (!nodedata)
@@ -4456,7 +4457,7 @@ 
qemuMigrationSrcRunPrepareBlockDirtyBitmapsMerge(virDomainObj *vm,
 granularity = b->granularity;

 if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(merge,
- 
n->nodeformat,
+ 
qemuBlockStorageSourceGetEffectiveNodename(n),
  b->name) 
< 0)
 return -1;
 }
@@ -4465,19 +4466,19 @@ 
qemuMigrationSrcRunPrepareBlockDirtyBitmapsMerge(virDomainObj *vm,
 bitmap->persistent = VIR_TRISTATE_BOOL_YES;

 if (qemuMonitorTransactionBitmapAdd(actions,
-disk->disk->src->nodeformat,
+
qemuBlockStorageSourceGetEffectiveNodename(disk->disk->src),
 bitmap->sourcebitmap,
 false, false, granularity) < 0)
 return -1;

 if (qemuMonitorTransactionBitmapMerge(actions,
-  disk->disk->src->nodeformat,
+  
qemuBlockStorageSourceGetEffectiveNodename(disk->disk->src),
   bitmap->sourcebitmap,
   ) < 0)
 return -1;

 tmpbmp = g_new0(qemuDomainJobPrivateMigrateTempBitmap, 1);
-tmpbmp->nodename = g_strdup(disk->disk->src->nodeformat);
+tmpbmp->nodename = 
g_strdup(qemuBlockStorageSourceGetEffectiveNodename(disk->disk->src));
 tmpbmp->bitmapname = g_strdup(bitmap->sourcebitmap);
 tmpbitmaps = g_slist_prepend(tmpbitmaps, tmpbmp);
 }
diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c
index ba146960d5..5505fdaf22 100644
--- a/src/qemu/qemu_migration_cookie.c
+++ b/src/qemu/qemu_migration_cookie.c
@@ -1573,7 +1573,7 @@ 
qemuMigrationCookieBlockDirtyBitmapsMatchDisks(virDomainDef *def,
 return -1;
 }

-disk->nodename = disk->disk->src->nodeformat;
+disk->nodename = 
qemuBlockStorageSourceGetEffectiveNodename(disk->disk->src);
 }

 return 0;
-- 
2.41.0



[PATCH 18/31] qemuBlockStorageSourceGetFormatProps: Use new frontend name accessor

2023-10-16 Thread Peter Krempa
---
 src/qemu/qemu_block.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 10c2c0104b..0fa5b6e55d 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1418,7 +1418,7 @@ qemuBlockStorageSourceGetFormatProps(virStorageSource 
*src,
 src->format >= VIR_STORAGE_FILE_BACKING) {
 if (virStorageSourceIsBacking(backingStore)) {
 backingFormatterStr = "s:backing";
-backingNodename = backingStore->nodeformat;
+backingNodename = 
qemuBlockStorageSourceGetEffectiveNodename(backingStore);
 } else {
 /* chain is terminated, indicate that no detection should happen 
in qemu */
 backingFormatterStr = "n:backing";
-- 
2.41.0



[PATCH 28/31] qemu: Convert migration setup code to use 'format' layer node name accessors

2023-10-16 Thread Peter Krempa
The blockjob, NBD export and setup of the cookie data all care about the
effective nodename.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c| 6 +++---
 src/qemu/qemu_migration.c| 4 ++--
 src/qemu/qemu_migration_cookie.c | 3 ++-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index edc8edcb70..fa31028db3 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -3406,11 +3406,11 @@ qemuBlockExportAddNBD(virDomainObj *vm,
 const char *bitmaps[2] = { bitmap, NULL };

 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_EXPORT_ADD))
-return qemuMonitorNBDServerAdd(priv->mon, src->nodeformat,
+return qemuMonitorNBDServerAdd(priv->mon, 
qemuBlockStorageSourceGetEffectiveNodename(src),
exportname, writable, bitmap);

-if (!(nbdprops = qemuBlockExportGetNBDProps(src->nodeformat, exportname,
-writable, bitmaps)))
+if (!(nbdprops = 
qemuBlockExportGetNBDProps(qemuBlockStorageSourceGetEffectiveNodename(src),
+exportname, writable, 
bitmaps)))
 return -1;

 return qemuMonitorBlockExportAdd(priv->mon, );
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 7d08df1fc5..949ef6d6d5 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1012,7 +1012,7 @@ 
qemuMigrationSrcNBDStorageCopyBlockdevPrepareSource(virDomainDiskDef *disk,
 copysrc->tlsHostname = g_strdup(tlsHostname);

 qemuBlockStorageSourceSetStorageNodename(copysrc, 
g_strdup_printf("migration-%s-storage", disk->dst));
-copysrc->nodeformat = g_strdup_printf("migration-%s-format", disk->dst);
+qemuBlockStorageSourceSetFormatNodename(copysrc, 
g_strdup_printf("migration-%s-format", disk->dst));

 return g_steal_pointer();
 }
@@ -1060,7 +1060,7 @@ qemuMigrationSrcNBDStorageCopyBlockdev(virDomainObj *vm,
 if (mon_ret == 0)
 mon_ret = qemuMonitorBlockdevMirror(qemuDomainGetMonitor(vm), 
diskAlias, true,
 qemuDomainDiskGetTopNodename(disk),
-copysrc->nodeformat,
+
qemuBlockStorageSourceGetEffectiveNodename(copysrc),
 mirror_speed, 0, 0, mirror_shallow,
 syncWrites);

diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c
index 7f0b7a3412..ba146960d5 100644
--- a/src/qemu/qemu_migration_cookie.c
+++ b/src/qemu/qemu_migration_cookie.c
@@ -31,6 +31,7 @@
 #include "qemu_domain.h"
 #include "qemu_migration_cookie.h"
 #include "qemu_migration_params.h"
+#include "qemu_block.h"


 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -507,7 +508,7 @@ qemuMigrationCookieAddNBD(qemuMigrationCookie *mig,
 virDomainDiskDef *disk = vm->def->disks[i];
 qemuBlockStats *entry;

-if (!(entry = virHashLookup(stats, disk->src->nodeformat)))
+if (!(entry = virHashLookup(stats, 
qemuBlockStorageSourceGetEffectiveNodename(disk->src
 continue;

 mig->nbd->disks[mig->nbd->ndisks].target = g_strdup(disk->dst);
-- 
2.41.0



[PATCH 27/31] qemu: command: Use 'format' nodename accessors for 'pflash' backend setup

2023-10-16 Thread Peter Krempa
The frontend device needs to access the blocks directly so it cares
about the effective nodename.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_command.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 40de712c61..d40d3a4e13 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7032,9 +7032,11 @@ qemuBuildMachineCommandLine(virCommand *cmd,

 if (virDomainDefHasOldStyleUEFI(def)) {
 if (priv->pflash0)
-virBufferAsprintf(, ",pflash0=%s", priv->pflash0->nodeformat);
+virBufferAsprintf(, ",pflash0=%s",
+  
qemuBlockStorageSourceGetEffectiveNodename(priv->pflash0));
 if (def->os.loader->nvram)
-virBufferAsprintf(, ",pflash1=%s", 
def->os.loader->nvram->nodeformat);
+virBufferAsprintf(, ",pflash1=%s",
+  
qemuBlockStorageSourceGetEffectiveNodename(def->os.loader->nvram));
 }

 if (virDomainNumaHasHMAT(def->numa))
-- 
2.41.0



[PATCH 30/31] qemu: driver: Use 'format' nodename accessors for disk resize

2023-10-16 Thread Peter Krempa
Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_driver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b286d94ca1..43d96739d5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9252,7 +9252,7 @@ qemuDomainBlockResize(virDomainPtr dom,
 }

 if (!qemuDiskBusIsSD(disk->bus)) {
-nodename = disk->src->nodeformat;
+nodename = qemuBlockStorageSourceGetEffectiveNodename(disk->src);
 } else {
 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
 goto endjob;
-- 
2.41.0



[PATCH 22/31] qemu: domain: Use 'format' layer node name accessors for nodename setup code

2023-10-16 Thread Peter Krempa
The code setting the nodenames needs to use the 'true' nodename of the
format layer.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_domain.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 1b2f09a316..d8d3a17e55 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2001,7 +2001,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
 xmlNodePtr nbdkitnode = NULL;

 qemuBlockStorageSourceSetStorageNodename(src, 
virXPathString("string(./nodenames/nodename[@type='storage']/@name)", ctxt));
-src->nodeformat = 
virXPathString("string(./nodenames/nodename[@type='format']/@name)", ctxt);
+qemuBlockStorageSourceSetFormatNodename(src, 
virXPathString("string(./nodenames/nodename[@type='format']/@name)", ctxt));
 src->tlsAlias = virXPathString("string(./objects/TLSx509/@alias)", ctxt);

 if (src->sliceStorage)
@@ -2112,7 +2112,7 @@ qemuStorageSourcePrivateDataFormat(virStorageSource *src,
 g_auto(virBuffer) fdsetsChildBuf = VIR_BUFFER_INIT_CHILD(buf);

 virBufferEscapeString(, "\n", qemuBlockStorageSourceGetStorageNodename(src));
-virBufferEscapeString(, "\n", src->nodeformat);
+virBufferEscapeString(, "\n", qemuBlockStorageSourceGetFormatNodename(src));

 if (src->sliceStorage)
 virBufferEscapeString(, "\n",
@@ -2817,8 +2817,9 @@ qemuDomainVirStorageSourceFindByNodeName(virStorageSource 
*top,

 for (tmp = top; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
 const char *nodestorage = 
qemuBlockStorageSourceGetStorageNodename(tmp);
+const char *nodeformat = qemuBlockStorageSourceGetFormatNodename(tmp);

-if ((tmp->nodeformat && STREQ(tmp->nodeformat, nodeName)) ||
+if ((nodeformat && STREQ(nodeformat, nodeName)) ||
 (nodestorage && STREQ(nodestorage, nodeName)))
 return tmp;
 }
@@ -11144,10 +11145,11 @@ 
qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
virQEMUDriverConfig *cfg)
 {
 char *nodestorage = g_strdup_printf("%s-storage", nodenameprefix);
+char *nodeformat = g_strdup_printf("%s-format", nodenameprefix);

 /* qemuBlockStorageSourceSetStorageNodename steals 'nodestorage' */
 qemuBlockStorageSourceSetStorageNodename(src, nodestorage);
-src->nodeformat = g_strdup_printf("%s-format", nodenameprefix);
+qemuBlockStorageSourceSetFormatNodename(src, nodeformat);

 if (qemuBlockStorageSourceNeedsStorageSliceLayer(src))
 src->sliceStorage->nodename = g_strdup_printf("libvirt-%u-slice-sto", 
src->id);
@@ -11161,8 +11163,7 @@ 
qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
 qemuDomainPrepareStorageSourceConfig(src, cfg);
 qemuDomainPrepareDiskSourceData(disk, src);

-if (qemuDomainSecretStorageSourcePrepareEncryption(priv, src,
-   src->nodeformat) < 0)
+if (qemuDomainSecretStorageSourcePrepareEncryption(priv, src, nodeformat) 
< 0)
 return -1;

 if (!qemuDomainPrepareStorageSourceNbdkit(src, cfg, nodestorage, priv)) {
@@ -11698,7 +11699,7 @@ qemuDomainInitializePflashStorageSource(virDomainObj 
*vm,
 pflash0->path = g_strdup(def->os.loader->path);
 pflash0->readonly = false;
 virTristateBoolToBool(def->os.loader->readonly, >readonly);
-pflash0->nodeformat = g_strdup("libvirt-pflash0-format");
+qemuBlockStorageSourceSetFormatNodename(pflash0, 
g_strdup("libvirt-pflash0-format"));
 qemuBlockStorageSourceSetStorageNodename(pflash0, 
g_strdup("libvirt-pflash0-storage"));

 if (def->os.loader->nvram) {
-- 
2.41.0



[PATCH 10/31] qemu: domain: Rework assignment of 'storage' nodenames to use new accessors

2023-10-16 Thread Peter Krempa
Refactor the code which assigns the 'storage' layer nodenames for disks.
scsi hostdevs and pflash backend.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_domain.c| 25 ++---
 src/qemu/qemu_migration.c |  2 +-
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 78dc99d243..885c5ee96b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11143,7 +11143,10 @@ 
qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
qemuDomainObjPrivate *priv,
virQEMUDriverConfig *cfg)
 {
-src->nodestorage = g_strdup_printf("%s-storage", nodenameprefix);
+char *nodestorage = g_strdup_printf("%s-storage", nodenameprefix);
+
+/* qemuBlockStorageSourceSetStorageNodename steals 'nodestorage' */
+qemuBlockStorageSourceSetStorageNodename(src, nodestorage);
 src->nodeformat = g_strdup_printf("%s-format", nodenameprefix);

 if (qemuBlockStorageSourceNeedsStorageSliceLayer(src))
@@ -11162,18 +11165,17 @@ 
qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
src->nodeformat) < 0)
 return -1;

-if (!qemuDomainPrepareStorageSourceNbdkit(src, cfg, src->nodestorage, 
priv)) {
+if (!qemuDomainPrepareStorageSourceNbdkit(src, cfg, nodestorage, priv)) {
 /* If we're using nbdkit to serve the storage source, we don't pass
  * authentication secrets to qemu, but will pass them to nbdkit 
instead */
-if (qemuDomainSecretStorageSourcePrepareAuth(priv, src,
- src->nodestorage) < 0)
+if (qemuDomainSecretStorageSourcePrepareAuth(priv, src, nodestorage) < 
0)
 return -1;
 }

-if (qemuDomainPrepareStorageSourcePR(src, priv, src->nodestorage) < 0)
+if (qemuDomainPrepareStorageSourcePR(src, priv, nodestorage) < 0)
 return -1;

-if (qemuDomainPrepareStorageSourceTLS(src, cfg, src->nodestorage,
+if (qemuDomainPrepareStorageSourceTLS(src, cfg, nodestorage,
   priv) < 0)
 return -1;

@@ -11297,12 +11299,14 @@ qemuDomainPrepareHostdevSCSI(virDomainHostdevDef 
*hostdev,
 }

 if (src) {
-const char *backendalias = hostdev->info->alias;
+char *backendalias;

 src->readonly = hostdev->readonly;
 src->id = qemuDomainStorageIDNew(priv);
-src->nodestorage = g_strdup_printf("libvirt-%d-backend", src->id);
-backendalias = src->nodestorage;
+backendalias = g_strdup_printf("libvirt-%d-backend", src->id);
+
+/* 'src' takes ownership of 'backendalias' */
+qemuBlockStorageSourceSetStorageNodename(src, backendalias);

 if (src->auth) {
 virSecretUsageType usageType = VIR_SECRET_USAGE_TYPE_ISCSI;
@@ -11695,8 +11699,7 @@ qemuDomainInitializePflashStorageSource(virDomainObj 
*vm,
 pflash0->readonly = false;
 virTristateBoolToBool(def->os.loader->readonly, >readonly);
 pflash0->nodeformat = g_strdup("libvirt-pflash0-format");
-pflash0->nodestorage = g_strdup("libvirt-pflash0-storage");
-
+qemuBlockStorageSourceSetStorageNodename(pflash0, 
g_strdup("libvirt-pflash0-storage"));

 if (def->os.loader->nvram) {
 if (qemuDomainPrepareStorageSourceBlockdevNodename(NULL,
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 011482c2b5..7d08df1fc5 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1011,7 +1011,7 @@ 
qemuMigrationSrcNBDStorageCopyBlockdevPrepareSource(virDomainDiskDef *disk,
 copysrc->tlsAlias = g_strdup(tlsAlias);
 copysrc->tlsHostname = g_strdup(tlsHostname);

-copysrc->nodestorage = g_strdup_printf("migration-%s-storage", disk->dst);
+qemuBlockStorageSourceSetStorageNodename(copysrc, 
g_strdup_printf("migration-%s-storage", disk->dst));
 copysrc->nodeformat = g_strdup_printf("migration-%s-format", disk->dst);

 return g_steal_pointer();
-- 
2.41.0



[PATCH 05/31] tests: Use 'storage' layer nodename accessors in tests

2023-10-16 Thread Peter Krempa
Convert all places in tests to use the 'storage' layer nodename
accessors instead of (virStorageSource)->nodestorage.

Signed-off-by: Peter Krempa 
---
 tests/qemublocktest.c   | 4 ++--
 tests/qemumonitorjsontest.c | 2 +-
 tests/qemuxml2argvtest.c| 3 ++-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index edfe7719c8..9a72a67ce2 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -233,7 +233,7 @@ testQemuDiskXMLToJSONFakeSecrets(virStorageSource *src)

 srcpriv->secinfo->username = g_strdup(src->auth->username);
 srcpriv->secinfo->alias = g_strdup_printf("%s-secalias",
-  NULLSTR(src->nodestorage));
+  
NULLSTR(qemuBlockStorageSourceGetStorageNodename(src)));
 }

 if (src->encryption) {
@@ -667,7 +667,7 @@ testQemuBackupIncrementalBitmapCalculateGetFakeImage(size_t 
idx)
ret->type = VIR_STORAGE_TYPE_FILE;
ret->format = VIR_STORAGE_FILE_QCOW2;
ret->path = g_strdup_printf("/image%zu", idx);
-   ret->nodestorage = g_strdup_printf("libvirt-%zu-storage", idx);
+   qemuBlockStorageSourceSetStorageNodename(ret, 
g_strdup_printf("libvirt-%zu-storage", idx));
ret->nodeformat = g_strdup_printf("libvirt-%zu-format", idx);

return ret;
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 2e7b661db4..6b82e3841b 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -2601,7 +2601,7 @@ testQemuMonitorJSONBlockdevReopen(const void *opaque)
 src->format = VIR_STORAGE_FILE_QCOW2;
 src->readonly = true;
 src->nodeformat = g_strdup("test node");
-src->nodestorage = g_strdup("backing nodename");
+qemuBlockStorageSourceSetStorageNodename(src, g_strdup("backing 
nodename"));
 src->backingStore = virStorageSourceNew();

 if (qemuMonitorTestAddItem(test, "blockdev-reopen", "{\"return\":{}}") < 0)
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index a454dcb205..48058cb924 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -12,6 +12,7 @@
 # include "internal.h"
 # include "viralloc.h"
 # include "viridentity.h"
+# include "qemu/qemu_block.h"
 # include "qemu/qemu_capabilities.h"
 # include "qemu/qemu_domain.h"
 # include "qemu/qemu_migration.h"
@@ -338,7 +339,7 @@ testCompareXMLToArgvCreateArgs(virQEMUDriver *drv,

 srcpriv = qemuDomainStorageSourcePrivateFetch(src);

-srcpriv->fdpass = qemuFDPassNew(src->nodestorage, priv);
+srcpriv->fdpass = 
qemuFDPassNew(qemuBlockStorageSourceGetStorageNodename(src), priv);
 qemuFDPassAddFD(srcpriv->fdpass, , "-vdpa");
 }
 }
-- 
2.41.0



[PATCH 15/31] conf: Rename 'nodestorage' field of virStorageSource to 'nodenamestorage'

2023-10-16 Thread Peter Krempa
While the name itself doesn't matter, this rename is done to prove that
all places using 'nodestorage' were converted to the appropriate
accessors.

Signed-off-by: Peter Krempa 
---
 src/conf/storage_source_conf.c | 4 ++--
 src/conf/storage_source_conf.h | 2 +-
 src/qemu/qemu_block.c  | 8 
 src/qemu/qemu_blockjob.c   | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 61a433ab1f..ea171f9945 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -829,7 +829,7 @@ virStorageSourceCopy(const virStorageSource *src,
 def->snapshot = g_strdup(src->snapshot);
 def->configFile = g_strdup(src->configFile);
 def->nodeformat = g_strdup(src->nodeformat);
-def->nodestorage = g_strdup(src->nodestorage);
+def->nodenamestorage = g_strdup(src->nodenamestorage);
 def->compat = g_strdup(src->compat);
 def->tlsAlias = g_strdup(src->tlsAlias);
 def->tlsCertdir = g_strdup(src->tlsCertdir);
@@ -1168,7 +1168,7 @@ virStorageSourceClear(virStorageSource *def)
 virStorageAuthDefFree(def->auth);
 virObjectUnref(def->privateData);

-VIR_FREE(def->nodestorage);
+VIR_FREE(def->nodenamestorage);
 VIR_FREE(def->nodeformat);

 virStorageSourceBackingStoreClear(def);
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index fc6c67f426..e9525c8f65 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -371,7 +371,7 @@ struct _virStorageSource {

 /* metadata that allows identifying given storage source */
 char *nodeformat;  /* name of the format handler object */
-char *nodestorage; /* name of the storage object */
+char *nodenamestorage; /* name of the storage object */

 /* An optional setting to enable usage of TLS for the storage source */
 virTristateBool haveTLS;
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 7355cb0b5e..a2414dc2e3 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -64,8 +64,8 @@ void
 qemuBlockStorageSourceSetStorageNodename(virStorageSource *src,
  char *nodename)
 {
-g_free(src->nodestorage);
-src->nodestorage = nodename;
+g_free(src->nodenamestorage);
+src->nodenamestorage = nodename;
 }


@@ -83,7 +83,7 @@ 
qemuBlockStorageSourceGetEffectiveStorageNodename(virStorageSource *src)
 src->sliceStorage->nodename)
 return src->sliceStorage->nodename;

-return src->nodestorage;
+return src->nodenamestorage;
 }


@@ -96,7 +96,7 @@ 
qemuBlockStorageSourceGetEffectiveStorageNodename(virStorageSource *src)
 const char *
 qemuBlockStorageSourceGetStorageNodename(virStorageSource *src)
 {
-return src->nodestorage;
+return src->nodenamestorage;
 }


diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 25ac74d6c4..12f3d59df5 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -612,7 +612,7 @@ qemuBlockJobCleanStorageSourceRuntime(virStorageSource *src)
 src->detected = false;
 VIR_FREE(src->relPath);
 VIR_FREE(src->backingStoreRaw);
-VIR_FREE(src->nodestorage);
+VIR_FREE(src->nodenamestorage);
 VIR_FREE(src->nodeformat);
 VIR_FREE(src->tlsAlias);
 VIR_FREE(src->tlsCertdir);
-- 
2.41.0



[PATCH 09/31] qemu: block: Convert disk 'storage' backend JSON props generator to new accessors

2023-10-16 Thread Peter Krempa
We need to use the 'effective' storage nodename (one which includes the
optional storage slice 'raw' intermediate layer) in the code which
formats the 'format' layer props.

All other cases need the real storage driver nodename as they either
generate the 'storage' layer props, or the storage slice, which refers
to the proper storage backend.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index a98caa330e..1fc36569a9 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1060,8 +1060,10 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource 
*src,
 return NULL;

 if (!onlytarget) {
-if (qemuBlockNodeNameValidate(src->nodestorage) < 0 ||
-virJSONValueObjectAdd(, "S:node-name", src->nodestorage, 
NULL) < 0)
+if 
(qemuBlockNodeNameValidate(qemuBlockStorageSourceGetStorageNodename(src)) < 0 ||
+virJSONValueObjectAdd(,
+  "S:node-name", 
qemuBlockStorageSourceGetStorageNodename(src),
+  NULL) < 0)
 return NULL;

 if (!legacy) {
@@ -1358,10 +1360,6 @@ qemuBlockStorageSourceGetFormatProps(virStorageSource 
*src,
 g_autoptr(virJSONValue) props = NULL;
 const char *backingFormatterStr = NULL;
 const char *backingNodename = NULL;
-const char *storagenode = src->nodestorage;
-
-if (qemuBlockStorageSourceNeedsStorageSliceLayer(src))
-storagenode = src->sliceStorage->nodename;

 if (virStorageSourceIsBacking(backingStore) &&
 src->format < VIR_STORAGE_FILE_BACKING) {
@@ -1386,7 +1384,7 @@ qemuBlockStorageSourceGetFormatProps(virStorageSource 
*src,
 return NULL;

 if (virJSONValueObjectAdd(,
-  "s:file", storagenode,
+  "s:file", 
qemuBlockStorageSourceGetEffectiveStorageNodename(src),
   backingFormatterStr, backingNodename,
   NULL) < 0)
 return 0;
@@ -1408,7 +1406,7 @@ 
qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSource *src)
   "s:node-name", src->sliceStorage->nodename,
   "U:offset", src->sliceStorage->offset,
   "U:size", src->sliceStorage->size,
-  "s:file", src->nodestorage,
+  "s:file", 
qemuBlockStorageSourceGetStorageNodename(src),
   "b:auto-read-only", true,
   "s:discard", "unmap",
   NULL) < 0)
-- 
2.41.0



[PATCH 16/31] qemu: block: Add accessors for format layer node names

2023-10-16 Thread Peter Krempa
Introduce a set of accessors, which return node names based on
semantics. This will allow to us to modify how we setup the backing
chain in cases when e.g. the format driver can be omitted, without
breaking all the code.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 31 +++
 src/qemu/qemu_block.h |  7 +++
 2 files changed, 38 insertions(+)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index a2414dc2e3..cba1fb1c1e 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -69,6 +69,23 @@ qemuBlockStorageSourceSetStorageNodename(virStorageSource 
*src,
 }


+/**
+ * qemuBlockStorageSourceSetFormatNodename:
+ * @src: virStorageSource to set the format nodename
+ * @nodename: The node name to set (stolen)
+ *
+ * Sets @nodename as the format node name of @src. Using NULL @nodename clears
+ * the nodename. @src takes ownership of @nodename.
+ */
+void
+qemuBlockStorageSourceSetFormatNodename(virStorageSource *src,
+char *nodename)
+{
+g_free(src->nodeformat);
+src->nodeformat = nodename;
+}
+
+
 /**
  * qemuBlockStorageSourceGetEffectiveStorageNodename:
  * @src: virStorageSource to get the effective nodename of
@@ -100,6 +117,20 @@ qemuBlockStorageSourceGetStorageNodename(virStorageSource 
*src)
 }


+/**
+ * qemuBlockStorageSourceGetFormatNodename:
+ * @src: virStorageSource to get the effective nodename of
+ *
+ * Gets the nodename corresponding to the format layer. Useful when accessing
+ * format specific features. Returns NULL if there is no format layer.
+ */
+const char *
+qemuBlockStorageSourceGetFormatNodename(virStorageSource *src)
+{
+return src->nodeformat;
+}
+
+
 /**
  * qemuBlockStorageSourceSupportsConcurrentAccess:
  * @src: disk storage source
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index ecc5711dcd..6ed0aa85b2 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -30,12 +30,19 @@ void
 qemuBlockStorageSourceSetStorageNodename(virStorageSource *src,
  char *nodename);

+void
+qemuBlockStorageSourceSetFormatNodename(virStorageSource *src,
+char *nodename);
+
 const char *
 qemuBlockStorageSourceGetEffectiveStorageNodename(virStorageSource *src);

 const char *
 qemuBlockStorageSourceGetStorageNodename(virStorageSource *src);

+const char *
+qemuBlockStorageSourceGetFormatNodename(virStorageSource *src);
+

 typedef struct qemuBlockNodeNameBackingChainData 
qemuBlockNodeNameBackingChainData;
 struct qemuBlockNodeNameBackingChainData {
-- 
2.41.0



[PATCH 12/31] qemu: Refactor storage backend 'storage' layer helepr object setup

2023-10-16 Thread Peter Krempa
Use the new nodename accessors for any storage layer helper object.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_domain.c  | 2 +-
 src/qemu/qemu_nbdkit.c  | 4 ++--
 src/qemu/qemu_process.c | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 885c5ee96b..1b2f09a316 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11106,7 +11106,7 @@ qemuDomainPrepareStorageSourceFDs(virStorageSource *src,

 srcpriv = qemuDomainStorageSourcePrivateFetch(src);

-srcpriv->fdpass = qemuFDPassNew(src->nodestorage, priv);
+srcpriv->fdpass = 
qemuFDPassNew(qemuBlockStorageSourceGetStorageNodename(src), priv);

 for (i = 0; i < fdt->nfds; i++) {
 g_autofree char *idx = g_strdup_printf("%zu", i);
diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c
index 3ad63cfaa0..85e61be44c 100644
--- a/src/qemu/qemu_nbdkit.c
+++ b/src/qemu/qemu_nbdkit.c
@@ -923,7 +923,7 @@ qemuNbdkitStopStorageSource(virStorageSource *src,

 if (priv && priv->nbdkitProcess &&
 qemuNbdkitProcessStop(priv->nbdkitProcess, vm) < 0)
-VIR_WARN("Unable to stop nbdkit for storage source '%s'", 
src->nodestorage);
+VIR_WARN("Unable to stop nbdkit for storage source '%s'", 
qemuBlockStorageSourceGetStorageNodename(src));
 }
 }

@@ -1173,7 +1173,7 @@ qemuNbdkitProcessStart(qemuNbdkitProcess *proc,

 logfd = qemuLogContextGetWriteFD(logContext);

-VIR_DEBUG("starting nbdkit process for %s", proc->source->nodestorage);
+VIR_DEBUG("starting nbdkit process for %s", 
qemuBlockStorageSourceGetStorageNodename(proc->source));
 virCommandSetErrorFD(cmd, );
 virCommandSetOutputFD(cmd, );
 virCommandSetPidFile(cmd, proc->pidfile);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ae0bb7bf80..63c0c62a46 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6771,7 +6771,7 @@ qemuProcessPrepareHostStorageSourceVDPA(virStorageSource 
*src,

 srcpriv = qemuDomainStorageSourcePrivateFetch(src);

-srcpriv->fdpass = qemuFDPassNew(src->nodestorage, priv);
+srcpriv->fdpass = 
qemuFDPassNew(qemuBlockStorageSourceGetStorageNodename(src), priv);
 qemuFDPassAddFD(srcpriv->fdpass, , "-vdpa");
 return 0;
 }
-- 
2.41.0



[PATCH 01/31] qemu: domain: Identify blockjobs by storage nodename in VM status XML

2023-10-16 Thread Peter Krempa
Use the node name of the storage access driver to identify the block job
volumes. This will prepare the blockjob code to the possibility that the
format layer may be missing. Our lookup code can find either of them,
thus we can safely switch.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_domain.c   |  8 
 tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml | 12 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index eec7bed28b..918b5a14e1 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2288,13 +2288,13 @@ qemuDomainPrivateBlockJobFormatCommit(qemuBlockJobData 
*job,
 g_auto(virBuffer) disabledBitmapsBuf = VIR_BUFFER_INIT_CHILD(buf);

 if (job->data.commit.base)
-virBufferAsprintf(buf, "\n", 
job->data.commit.base->nodeformat);
+virBufferAsprintf(buf, "\n", 
job->data.commit.base->nodestorage);

 if (job->data.commit.top)
-virBufferAsprintf(buf, "\n", 
job->data.commit.top->nodeformat);
+virBufferAsprintf(buf, "\n", 
job->data.commit.top->nodestorage);

 if (job->data.commit.topparent)
-virBufferAsprintf(buf, "\n", 
job->data.commit.topparent->nodeformat);
+virBufferAsprintf(buf, "\n", 
job->data.commit.topparent->nodestorage);

 if (job->data.commit.deleteCommittedImages)
 virBufferAddLit(buf, "\n");
@@ -2357,7 +2357,7 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void 
*payload,
 switch ((qemuBlockJobType) job->type) {
 case QEMU_BLOCKJOB_TYPE_PULL:
 if (job->data.pull.base)
-virBufferAsprintf(, "\n", 
job->data.pull.base->nodeformat);
+virBufferAsprintf(, "\n", 
job->data.pull.base->nodestorage);
 break;

 case QEMU_BLOCKJOB_TYPE_COMMIT:
diff --git a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml 
b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
index b62b3149c2..380ef053d2 100644
--- a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
+++ b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
@@ -238,14 +238,14 @@
 
 
   
-  
-  
-  
+  
+  
+  
 
 
   
-  
-  
+  
+  
   
 
 
@@ -301,7 +301,7 @@
 
 
   
-  
+  
 
 
   
-- 
2.41.0



[PATCH 04/31] qemu: block: Add accessors for protocol/storage node names

2023-10-16 Thread Peter Krempa
Introduce a set of accessors, which return node names based on
semantics. This will allow to us to modify how we setup the backing
chain in cases when e.g. the format driver can be omitted, without
breaking all the code.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 48 +++
 src/qemu/qemu_block.h | 11 ++
 2 files changed, 59 insertions(+)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 07bc8ede76..0c9460f678 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -52,6 +52,54 @@ qemuBlockNodeNameValidate(const char *nn)
 }


+/**
+ * qemuBlockStorageSourceSetStorageNodename:
+ * @src: virStorageSource to set the storage nodename
+ * @nodename: The node name to set (stolen)
+ *
+ * Sets @nodename as the storage node name of @src. Using NULL @nodename clears
+ * the nodename. @src takes ownership of @nodename.
+ */
+void
+qemuBlockStorageSourceSetStorageNodename(virStorageSource *src,
+ char *nodename)
+{
+g_free(src->nodestorage);
+src->nodestorage = nodename;
+}
+
+
+/**
+ * qemuBlockStorageSourceGetEffectiveStorageNodename:
+ * @src: virStorageSource to get the effective nodename of
+ *
+ * Gets the nodename that exposes the storage corresponding to @src, without
+ * the format driver applied. This function always returns a name.
+ */
+const char *
+qemuBlockStorageSourceGetEffectiveStorageNodename(virStorageSource *src)
+{
+if (src->sliceStorage &&
+src->sliceStorage->nodename)
+return src->sliceStorage->nodename;
+
+return src->nodestorage;
+}
+
+
+/**
+ * qemuBlockStorageSourceGetStorageNodename:
+ * @src: virStorageSource to get the effective nodename of
+ *
+ * Gets the nodename corresponding to the real backing storage format layer.
+ */
+const char *
+qemuBlockStorageSourceGetStorageNodename(virStorageSource *src)
+{
+return src->nodestorage;
+}
+
+
 /**
  * qemuBlockStorageSourceSupportsConcurrentAccess:
  * @src: disk storage source
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index cf5eaf87f3..ecc5711dcd 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -26,6 +26,17 @@
 #include "virjson.h"
 #include "viruri.h"

+void
+qemuBlockStorageSourceSetStorageNodename(virStorageSource *src,
+ char *nodename);
+
+const char *
+qemuBlockStorageSourceGetEffectiveStorageNodename(virStorageSource *src);
+
+const char *
+qemuBlockStorageSourceGetStorageNodename(virStorageSource *src);
+
+
 typedef struct qemuBlockNodeNameBackingChainData 
qemuBlockNodeNameBackingChainData;
 struct qemuBlockNodeNameBackingChainData {
 char *qemufilename; /* name of the image from qemu */
-- 
2.41.0



[PATCH 03/31] qemu: block: Rename qemuBlockStorageSourceGetBlockdevProps

2023-10-16 Thread Peter Krempa
Use qemuBlockStorageSourceGetFormatProps as it formats the properties of
the 'format' driver in qemu. Adjust the comment which was hinting
otherwise.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 16 +++-
 src/qemu/qemu_block.h |  4 ++--
 tests/qemublocktest.c |  2 +-
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 9b6d901e8c..07bc8ede76 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1295,18 +1295,17 @@ 
qemuBlockStorageSourceGetBlockdevFormatProps(virStorageSource *src)


 /**
- * qemuBlockStorageSourceGetBlockdevProps:
+ * qemuBlockStorageSourceGetFormatProps:
  *
  * @src: storage source to format
  * @backingStore: a storage source to use as backing of @src
  *
- * Formats @src into a JSON object which can be used with blockdev-add or
- * -blockdev. The formatted object contains both the storage and format layer
- * in nested form including link to the backing chain layer if necessary.
+ * Formats properties of @src related to the format blockdev driver in qemu
+ * into a JSON object which can be used with blockdev-add or -blockdev.
  */
 virJSONValue *
-qemuBlockStorageSourceGetBlockdevProps(virStorageSource *src,
-   virStorageSource *backingStore)
+qemuBlockStorageSourceGetFormatProps(virStorageSource *src,
+ virStorageSource *backingStore)
 {
 g_autoptr(virJSONValue) props = NULL;
 const char *backingFormatterStr = NULL;
@@ -1434,8 +1433,7 @@ 
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSource *src,

 data = g_new0(qemuBlockStorageSourceAttachData, 1);

-if (!(data->formatProps = qemuBlockStorageSourceGetBlockdevProps(src,
- 
backingStore)) ||
+if (!(data->formatProps = qemuBlockStorageSourceGetFormatProps(src, 
backingStore)) ||
 !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src,
  
backendpropsflags)))
 return NULL;
@@ -3049,7 +3047,7 @@ qemuBlockReopenFormatMon(qemuMonitor *mon,
 g_autoptr(virJSONValue) srcprops = NULL;
 g_autoptr(virJSONValue) reopenoptions = virJSONValueNewArray();

-if (!(srcprops = qemuBlockStorageSourceGetBlockdevProps(src, 
src->backingStore)))
+if (!(srcprops = qemuBlockStorageSourceGetFormatProps(src, 
src->backingStore)))
 return -1;

 if (virJSONValueArrayAppend(reopenoptions, ) < 0)
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 530d88d28e..cf5eaf87f3 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -57,8 +57,8 @@ virURI *
 qemuBlockStorageSourceGetURI(virStorageSource *src);

 virJSONValue *
-qemuBlockStorageSourceGetBlockdevProps(virStorageSource *src,
-   virStorageSource *backingStore);
+qemuBlockStorageSourceGetFormatProps(virStorageSource *src,
+ virStorageSource *backingStore);

 virJSONValue *
 qemuBlockStorageGetCopyOnReadProps(virDomainDiskDef *disk);
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index 8bad69e7ac..edfe7719c8 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -301,7 +301,7 @@ testQemuDiskXMLToProps(const void *opaque)

 qemuDomainPrepareDiskSourceData(disk, n);

-if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n, 
n->backingStore)) ||
+if (!(formatProps = qemuBlockStorageSourceGetFormatProps(n, 
n->backingStore)) ||
 !(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, 
backendpropsflagstarget)) ||
 !(storageProps = qemuBlockStorageSourceGetBackendProps(n, 
backendpropsflagsnormal)) ||
 !(backingstore = qemuBlockGetBackingStoreString(n, true))) {
-- 
2.41.0



[PATCH 06/31] qemuDomainVirStorageSourceFindByNodeName: Use proper accessor

2023-10-16 Thread Peter Krempa
The lookup by nodename requires the proper storage nodename which we use
also in status XML.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_domain.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 918b5a14e1..f891defa91 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2812,8 +2812,10 @@ 
qemuDomainVirStorageSourceFindByNodeName(virStorageSource *top,
 virStorageSource *tmp;

 for (tmp = top; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
+const char *nodestorage = 
qemuBlockStorageSourceGetStorageNodename(tmp);
+
 if ((tmp->nodeformat && STREQ(tmp->nodeformat, nodeName)) ||
-(tmp->nodestorage && STREQ(tmp->nodestorage, nodeName)))
+(nodestorage && STREQ(nodestorage, nodeName)))
 return tmp;
 }

-- 
2.41.0



[PATCH 02/31] qemu: block: Refactor logic in qemuBlockStorageSourceGetBlockdevProps

2023-10-16 Thread Peter Krempa
Restructure the conditions so that we can use virJSONValueObjectAdd with
a clearer logic for backing store control.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_block.c | 46 ++-
 1 file changed, 24 insertions(+), 22 deletions(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 7e870baa2f..9b6d901e8c 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1309,39 +1309,41 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSource 
*src,
virStorageSource *backingStore)
 {
 g_autoptr(virJSONValue) props = NULL;
+const char *backingFormatterStr = NULL;
+const char *backingNodename = NULL;
 const char *storagenode = src->nodestorage;

 if (qemuBlockStorageSourceNeedsStorageSliceLayer(src))
 storagenode = src->sliceStorage->nodename;

-if (!(props = qemuBlockStorageSourceGetBlockdevFormatProps(src)))
-return NULL;
-
-if (virJSONValueObjectAppendString(props, "file", storagenode) < 0)
+if (virStorageSourceIsBacking(backingStore) &&
+src->format < VIR_STORAGE_FILE_BACKING) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("storage format '%1$s' does not support backing 
store"),
+   virStorageFileFormatTypeToString(src->format));
 return NULL;
+}

-if (backingStore) {
-if (src->format >= VIR_STORAGE_FILE_BACKING) {
-if (virStorageSourceIsBacking(backingStore)) {
-if (virJSONValueObjectAppendString(props, "backing",
-   backingStore->nodeformat) < 
0)
-return NULL;
-} else {
-/* chain is terminated, indicate that no detection should 
happen
- * in qemu */
-if (virJSONValueObjectAppendNull(props, "backing") < 0)
-return NULL;
-}
+if (backingStore &&
+src->format >= VIR_STORAGE_FILE_BACKING) {
+if (virStorageSourceIsBacking(backingStore)) {
+backingFormatterStr = "s:backing";
+backingNodename = backingStore->nodeformat;
 } else {
-if (virStorageSourceIsBacking(backingStore)) {
-virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-   _("storage format '%1$s' does not support 
backing store"),
-   virStorageFileFormatTypeToString(src->format));
-return NULL;
-}
+/* chain is terminated, indicate that no detection should happen 
in qemu */
+backingFormatterStr = "n:backing";
 }
 }

+if (!(props = qemuBlockStorageSourceGetBlockdevFormatProps(src)))
+return NULL;
+
+if (virJSONValueObjectAdd(,
+  "s:file", storagenode,
+  backingFormatterStr, backingNodename,
+  NULL) < 0)
+return 0;
+
 return g_steal_pointer();
 }

-- 
2.41.0



[PATCH 00/31] qemu: Add accessors for 'storage' and 'format' nodenames and refactor callers ('raw' driver removal part 1)

2023-10-16 Thread Peter Krempa
This is a prequel series necessary for removing the dummy 'raw' driver
node if it isn't needed for performance reasons.

Peter Krempa (31):
  qemu: domain: Identify blockjobs by storage nodename in VM status XML
  qemu: block: Refactor logic in qemuBlockStorageSourceGetBlockdevProps
  qemu: block: Rename qemuBlockStorageSourceGetBlockdevProps
  qemu: block: Add accessors for protocol/storage node names
  tests: Use 'storage' layer nodename accessors in tests
  qemuDomainVirStorageSourceFindByNodeName: Use proper accessor
  qemu: block: Use proper accessors for image formatting/creation code
  qemu: domain: Convert the status XML code for 'storage' nodenames to
new accessors
  qemu: block: Convert disk 'storage' backend JSON props generator to
new accessors
  qemu: domain: Rework assignment of 'storage' nodenames to use new
accessors
  qemu: Refactor storage backend attach/detach setup code to use
'storage' nodename accessors
  qemu: Refactor storage backend 'storage' layer helepr object setup
  qemuDomainGetStatsBlockExportDisk: Use 'storage' node name accessors
  qemuDomainSetBlockThreshold: Use 'storage' node name accessor
  conf: Rename 'nodestorage' field of virStorageSource to
'nodenamestorage'
  qemu: block: Add accessors for format layer node names
  qemu: block: Add accessors for storage source effective nodename
  qemuBlockStorageSourceGetFormatProps: Use new frontend name accessor
  qemu: backup: Use format nodename accessors
  qemu: blockjob: Use 'format' nodename accessors for job naming
  qemu: block: Use 'format' nodename accessors in '-blockdev' setup code
  qemu: domain: Use 'format' layer node name accessors for nodename
setup code
  tests: Use 'format' layer nodename accessors in test code
  qemu: Convert disk backend setup code to use 'format' nodename
accessors
  qemu: driver: Convert disk stats code to use 'format' nodename
accessors
  qemu: Use 'format' nodename accessors for block dirty bitmap
operations
  qemu: command: Use 'format' nodename accessors for 'pflash' backend
setup
  qemu: Convert migration setup code to use 'format' layer node name
accessors
  qemu: migration: Use 'format' nodename accessors in dirty bitmap
migration
  qemu: driver: Use 'format' nodename accessors for disk resize
  conf: Rename 'nodeformat' field of virStorageSource to
'nodenameformat'

 src/conf/storage_source_conf.c|   8 +-
 src/conf/storage_source_conf.h|   4 +-
 src/qemu/qemu_backup.c|   8 +-
 src/qemu/qemu_block.c | 238 --
 src/qemu/qemu_block.h |  25 +-
 src/qemu/qemu_blockjob.c  |  24 +-
 src/qemu/qemu_checkpoint.c|   9 +-
 src/qemu/qemu_command.c   |  12 +-
 src/qemu/qemu_domain.c|  68 ++---
 src/qemu/qemu_driver.c|  25 +-
 src/qemu/qemu_migration.c |  17 +-
 src/qemu/qemu_migration_cookie.c  |   5 +-
 src/qemu/qemu_nbdkit.c|   4 +-
 src/qemu/qemu_process.c   |   2 +-
 src/qemu/qemu_snapshot.c  |   6 +-
 tests/qemublocktest.c |  16 +-
 tests/qemumonitorjsontest.c   |   4 +-
 .../blockjob-blockdev-in.xml  |  12 +-
 tests/qemuxml2argvtest.c  |   3 +-
 19 files changed, 314 insertions(+), 176 deletions(-)

-- 
2.41.0



Re: [libvirt] [PATCHv2 37/62] qemu: process: Setup disk io throttling?for -blockdev

2023-10-16 Thread Peter Krempa
On Mon, Oct 16, 2023 at 14:19:08 +, Chun Feng Wu wrote:
> Thanks for your info! Currently, the iotune in libvirt’s xml indeed works 
> well, BTW, is there any plan for such “re-engineering”?

No, there are no plans, as the current approach covers the vast majority
of use cases. Spending significant engineering resources on something
which will not get much use is not in the interest of the comunity. 



Re: [libvirt] [PATCHv2 37/62] qemu: process: Setup disk io throttling for -blockdev

2023-10-16 Thread Peter Krempa
On Mon, Oct 16, 2023 at 13:36:42 +, Chun Feng Wu wrote:
> Does this libvirt throttling support “chained throttle filters” for single 
> disk described in QEMU doc: 
> https://github.com/qemu/qemu/blob/master/docs/throttle.txt (“The 'throttle' 
> block filter”)

No, libvirt currently still uses the older approach by using
'block_set_io_throttle' QMP command. This was used at the beginning
because the 'throttle' layer was not yet ready at the point when libvirt
adopted -blockdev.

It is sufficient for the throttling options that are currently
configurable via libvirt's XML.

Note that to use the full potential of the throttle groups and
hierarchical throttling will require significant re-engineering of the
XML configuration of throttling.



Re: [PATCH 4/4] virSecretLoad: Simplify cleanup path

2023-10-16 Thread Peter Krempa
On Mon, Oct 16, 2023 at 10:07:51 +0200, Michal Privoznik wrote:
> When loading a secret value fails, the control jumps over to the
> 'cleanup' label where explicit call to virSecretDefFree()
> happens. This is unnecessary as the corresponding variable can be
> declared with g_autoptr() after which all error paths can just
> return NULL instantly.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/conf/virsecretobj.c | 11 +--
>  1 file changed, 5 insertions(+), 6 deletions(-)

Reviewed-by: Peter Krempa 



Re: [PATCH 3/4] virSecretLoadAllConfigs: Use g_autofree for @path

2023-10-16 Thread Peter Krempa
On Mon, Oct 16, 2023 at 10:07:50 +0200, Michal Privoznik wrote:
> When loading virSecret configs, the @path variable holds path to
> individual config files. In each iteration it is freed explicitly
> using VIR_FREE(). Switch it to g_autofree and remove those
> explicit calls.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/conf/virsecretobj.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)

Reviewed-by: Peter Krempa 



Re: [PATCH 2/4] virfile: Drop virBuildPathInternal()

2023-10-16 Thread Peter Krempa
On Mon, Oct 16, 2023 at 10:07:49 +0200, Michal Privoznik wrote:
> After previous cleanup the virBuildPathInternal() function is no
> longer used. Drop it.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/libvirt_private.syms |  1 -
>  src/util/virfile.c   | 22 --
>  src/util/virfile.h   |  5 -
>  3 files changed, 28 deletions(-)

Reviewed-by: Peter Krempa 



Re: [PATCH 1/4] lib: Replace virBuildPath() with g_build_filename()

2023-10-16 Thread Peter Krempa
On Mon, Oct 16, 2023 at 10:07:48 +0200, Michal Privoznik wrote:
> Our virBuildPath() constructs a path from given arguments.
> Exactly like g_build_filename(), except the latter is more
> generic as it uses backslashes on Windows. Therefore, replace the
> former with the latter.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  docs/kbase/internals/command.rst | 2 +-
>  src/util/virfcp.c| 2 +-
>  src/util/virhook.c   | 4 ++--
>  src/util/virpci.c| 4 ++--
>  4 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/docs/kbase/internals/command.rst 
> b/docs/kbase/internals/command.rst
> index 738fb5930a..d958c9d16a 100644
> --- a/docs/kbase/internals/command.rst
> +++ b/docs/kbase/internals/command.rst
> @@ -444,7 +444,7 @@ src/util/hooks.c
>   g_autofree char *path = NULL;
>   g_autoptr(virCommand) cmd = NULL;
>  
> - virBuildPath(, LIBVIRT_HOOK_DIR, drvstr);
> + path = g_build_filename(LIBVIRT_HOOK_DIR, drvstr);

It's docs, but it's missing the NULL sentinel.

Reviewed-by: Peter Krempa 



[PATCH 6/7] conf: Save translated disk definition for disk type='volume' to status XML

2023-10-12 Thread Peter Krempa
Re-translating the disk source pools when reconnecting to a VM makes no
sense as the volume might have changed or pool became inactive. The VM
still uses the original volume though. Failing to re-translate the pool
also causes the VM to be killed.

Fix this by storing the original translation in the status XML.

Resolves: https://issues.redhat.com/browse/RHEL-7345
Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.c  | 3 ++-
 src/conf/virdomainobjlist.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9b636215e9..80f467ae7a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -28247,7 +28247,8 @@ virDomainObjSave(virDomainObj *obj,
   VIR_DOMAIN_DEF_FORMAT_STATUS |
   VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET |
   VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES |
-  VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST);
+  VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST |
+  VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED);

 g_autofree char *xml = NULL;

diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c
index 6be5de5e2b..0bd833257d 100644
--- a/src/conf/virdomainobjlist.c
+++ b/src/conf/virdomainobjlist.c
@@ -532,7 +532,8 @@ virDomainObjListLoadStatus(virDomainObjList *doms,
   VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
   VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
   VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE |
-  
VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL)))
+  
VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL |
+  VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED)))
 goto error;

 virUUIDFormat(obj->def->uuid, uuidstr);
-- 
2.41.0



[PATCH 1/7] virStorageSourcePoolDef: Turn 'mode' member into proper enum type

2023-10-12 Thread Peter Krempa
Use proper enum type and refactor the formatter accordingly.

Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.c | 12 
 src/conf/storage_source_conf.h |  2 +-
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4435ee2ad4..d7f167a469 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7011,7 +7011,6 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node,
 {
 virStorageSourcePoolDef *source;
 int ret = -1;
-g_autofree char *mode = NULL;

 *srcpool = NULL;

@@ -7019,7 +7018,6 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node,

 source->pool = virXMLPropString(node, "pool");
 source->volume = virXMLPropString(node, "volume");
-mode = virXMLPropString(node, "mode");

 /* CD-ROM and Floppy allows no source */
 if (!source->pool && !source->volume) {
@@ -7033,13 +7031,11 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node,
 goto cleanup;
 }

-if (mode &&
-(source->mode = virStorageSourcePoolModeTypeFromString(mode)) <= 0) {
-virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-   _("unknown source mode '%1$s' for volume type disk"),
-   mode);
+if (virXMLPropEnum(node, "mode",
+   virStorageSourcePoolModeTypeFromString,
+   VIR_XML_PROP_NONZERO,
+   >mode) < 0)
 goto cleanup;
-}

 *srcpool = g_steal_pointer();
 ret = 0;
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index fc6c67f426..bfa8d625e5 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -201,7 +201,7 @@ struct _virStorageSourcePoolDef {
 int voltype; /* virStorageVolType, internal only */
 int pooltype; /* virStoragePoolType from storage_conf.h, internal only */
 virStorageType actualtype; /* internal only */
-int mode; /* virStorageSourcePoolMode, currently makes sense only for 
iscsi pool */
+virStorageSourcePoolMode mode; /* currently makes sense only for iscsi 
pool */
 };


-- 
2.41.0



[PATCH 5/7] qemustatusxml2xmltest: Demonstrate use of VIR_DOMAIN_DEF_(PARSE|FORMAT)_VOLUME_TRANSLATED

2023-10-12 Thread Peter Krempa
Enable the flags in the status xml2xmtest and add an exaple to the test
data.

Signed-off-by: Peter Krempa 
---
 tests/qemustatusxml2xmldata/modern-in.xml | 4 ++--
 tests/qemustatusxml2xmltest.c | 6 --
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/tests/qemustatusxml2xmldata/modern-in.xml 
b/tests/qemustatusxml2xmldata/modern-in.xml
index e139c8d38c..67e0aa4952 100644
--- a/tests/qemustatusxml2xmldata/modern-in.xml
+++ b/tests/qemustatusxml2xmldata/modern-in.xml
@@ -378,9 +378,9 @@
 
 
   
-  
+  
 
-
+
 
 
 
diff --git a/tests/qemustatusxml2xmltest.c b/tests/qemustatusxml2xmltest.c
index 418a724b94..f1589345c3 100644
--- a/tests/qemustatusxml2xmltest.c
+++ b/tests/qemustatusxml2xmltest.c
@@ -30,7 +30,8 @@ testCompareStatusXMLToXMLFiles(const void *opaque)
   VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
   VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
   VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE |
-  
VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL))) {
+  
VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL |
+  
VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED))) {
 VIR_TEST_DEBUG("\nfailed to parse '%s'", data->infile);
 goto cleanup;
 }
@@ -40,7 +41,8 @@ testCompareStatusXMLToXMLFiles(const void *opaque)
   VIR_DOMAIN_DEF_FORMAT_STATUS |
   VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET |
   VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES |
-  VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST))) {
+  VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST |
+  
VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED))) {
 VIR_TEST_DEBUG("\nfailed to format back '%s'", data->infile);
 goto cleanup;
 }
-- 
2.41.0



[PATCH 2/7] virDomainDiskSourcePoolDefParse: Refactor cleanup

2023-10-12 Thread Peter Krempa
Register autoptr cleanup function for virStorageSourcePoolDef and
refactor the parser to simplify the logic.

Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.c | 35 +++---
 src/conf/storage_source_conf.h |  1 +
 2 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d7f167a469..3e0989e2e8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7005,44 +7005,31 @@ virDomainLeaseDefParseXML(xmlNodePtr node,
 return NULL;
 }

-static int
-virDomainDiskSourcePoolDefParse(xmlNodePtr node,
-virStorageSourcePoolDef **srcpool)
+static virStorageSourcePoolDef *
+virDomainDiskSourcePoolDefParse(xmlNodePtr node)
 {
-virStorageSourcePoolDef *source;
-int ret = -1;
-
-*srcpool = NULL;
-
-source = g_new0(virStorageSourcePoolDef, 1);
+g_autoptr(virStorageSourcePoolDef) source = 
g_new0(virStorageSourcePoolDef, 1);

 source->pool = virXMLPropString(node, "pool");
 source->volume = virXMLPropString(node, "volume");

-/* CD-ROM and Floppy allows no source */
-if (!source->pool && !source->volume) {
-ret = 0;
-goto cleanup;
-}
+/* CD-ROM and Floppy allows no source -> empty pool */
+if (!source->pool && !source->volume)
+return g_steal_pointer();

 if (!source->pool || !source->volume) {
 virReportError(VIR_ERR_XML_ERROR, "%s",
_("'pool' and 'volume' must be specified together for 
'pool' type source"));
-goto cleanup;
+return NULL;
 }

 if (virXMLPropEnum(node, "mode",
virStorageSourcePoolModeTypeFromString,
VIR_XML_PROP_NONZERO,
>mode) < 0)
-goto cleanup;
-
-*srcpool = g_steal_pointer();
-ret = 0;
+return NULL;

- cleanup:
-virStorageSourcePoolDefFree(source);
-return ret;
+return g_steal_pointer();
 }


@@ -7482,7 +7469,7 @@ virDomainStorageSourceParse(xmlNodePtr node,
 return -1;
 break;
 case VIR_STORAGE_TYPE_VOLUME:
-if (virDomainDiskSourcePoolDefParse(node, >srcpool) < 0)
+if (!(src->srcpool = virDomainDiskSourcePoolDefParse(node)))
 return -1;
 break;
 case VIR_STORAGE_TYPE_NVME:
@@ -8660,7 +8647,7 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt,
 units = virXMLPropString(source_node, "units");
 } else if (def->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
 def->src->type = VIR_STORAGE_TYPE_VOLUME;
-if (virDomainDiskSourcePoolDefParse(source_node, 
>src->srcpool) < 0)
+if (!(def->src->srcpool = 
virDomainDiskSourcePoolDefParse(source_node)))
 goto error;
 }
 }
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index bfa8d625e5..0cd5cd0192 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -498,6 +498,7 @@ virStorageSourceInitChainElement(virStorageSource *newelem,

 void
 virStorageSourcePoolDefFree(virStorageSourcePoolDef *def);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageSourcePoolDef, 
virStorageSourcePoolDefFree);

 void
 virStorageSourceClear(virStorageSource *def);
-- 
2.41.0



[PATCH 4/7] qemu: domain: Allow preserving translated disk type='volume' data into XML if needed

2023-10-12 Thread Peter Krempa
Re-translating a disk type='volume' definition from a storage pool is
not a good idea in cases when the volume might have changed or we might
not have access to the storage driver.

Specific cases are if a storage pool is not activated on daemon restart,
then re-connecting to a VM fails, or if the virt-aa-helper program tries
to setup labelling for apparmor.

Add a new flag which will preserve the translated data in the
definition.

Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.c | 69 ++
 src/conf/domain_conf.h |  4 +++
 2 files changed, 53 insertions(+), 20 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e128457b00..9b636215e9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7006,7 +7006,8 @@ virDomainLeaseDefParseXML(xmlNodePtr node,
 }

 static virStorageSourcePoolDef *
-virDomainDiskSourcePoolDefParse(xmlNodePtr node)
+virDomainDiskSourcePoolDefParse(xmlNodePtr node,
+virDomainDefParseFlags flags)
 {
 g_autoptr(virStorageSourcePoolDef) source = 
g_new0(virStorageSourcePoolDef, 1);

@@ -7029,6 +7030,14 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node)
>mode) < 0)
 return NULL;

+if (flags & VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED) {
+if (virXMLPropEnum(node, "actualType",
+   virStorageTypeFromString,
+   VIR_XML_PROP_NONZERO,
+   >actualtype) < 0)
+return NULL;
+}
+
 return g_steal_pointer();
 }

@@ -7448,12 +7457,22 @@ virDomainStorageSourceParse(xmlNodePtr node,
 unsigned int flags,
 virDomainXMLOption *xmlopt)
 {
+virStorageType actualType = src->type;
 VIR_XPATH_NODE_AUTORESTORE(ctxt)
 xmlNodePtr tmp;

 ctxt->node = node;

-switch (src->type) {
+if (src->type == VIR_STORAGE_TYPE_VOLUME) {
+if (!(src->srcpool = virDomainDiskSourcePoolDefParse(node, flags)))
+return -1;
+
+/* If requested we need to also parse the translated volume runtime 
data */
+if (flags & VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED)
+actualType = virStorageSourceGetActualType(src);
+}
+
+switch (actualType) {
 case VIR_STORAGE_TYPE_FILE:
 src->path = virXMLPropString(node, "file");
 src->fdgroup = virXMLPropString(node, "fdgroup");
@@ -7469,8 +7488,7 @@ virDomainStorageSourceParse(xmlNodePtr node,
 return -1;
 break;
 case VIR_STORAGE_TYPE_VOLUME:
-if (!(src->srcpool = virDomainDiskSourcePoolDefParse(node)))
-return -1;
+/* parsed above */
 break;
 case VIR_STORAGE_TYPE_NVME:
 if (virDomainDiskSourceNVMeParse(node, ctxt, src) < 0)
@@ -7488,7 +7506,7 @@ virDomainStorageSourceParse(xmlNodePtr node,
 case VIR_STORAGE_TYPE_LAST:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %1$s"),
-   virStorageTypeToString(src->type));
+   virStorageTypeToString(actualType));
 return -1;
 }

@@ -8647,7 +8665,7 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt,
 units = virXMLPropString(source_node, "units");
 } else if (def->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
 def->src->type = VIR_STORAGE_TYPE_VOLUME;
-if (!(def->src->srcpool = 
virDomainDiskSourcePoolDefParse(source_node)))
+if (!(def->src->srcpool = 
virDomainDiskSourcePoolDefParse(source_node, flags)))
 goto error;
 }
 }
@@ -22335,10 +22353,28 @@ virDomainDiskSourceFormat(virBuffer *buf,
   bool skipEnc,
   virDomainXMLOption *xmlopt)
 {
+virStorageType actualType = src->type;
 g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
 g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);

-switch (src->type) {
+if (src->type == VIR_STORAGE_TYPE_VOLUME) {
+if (src->srcpool) {
+virBufferEscapeString(, " pool='%s'", src->srcpool->pool);
+virBufferEscapeString(, " volume='%s'", 
src->srcpool->volume);
+if (src->srcpool->mode)
+virBufferAsprintf(, " mode='%s'",
+  
virStorageSourcePoolModeTypeToString(src->srcpool->mode));
+}
+
+if (flags & VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED &&
+src->srcpool->actualtype != VIR_STORAGE_TYPE_NONE) {
+virBufferAsprintf(, " actualType='%s'",
+  
virStorageTypeToString(src->srcpool->actualtype));
+actualType = virStorageSource

[PATCH 0/7] qemu: Fix two pool-translation related bugs

2023-10-12 Thread Peter Krempa
Fix following problems:
 - fix disk type='volume' disks resolving to local images on apparmor-protected 
hosts
 - VMs are killed if pool is not available after libvirtd/virtqemud restart

The first one will be annoying for users of Cockpit on apparmor based
boxes. NOTE: I didn't test it though as I don't have such distro handy.

Peter Krempa (7):
  virStorageSourcePoolDef: Turn 'mode' member into proper enum type
  virDomainDiskSourcePoolDefParse: Refactor cleanup
  virDomainDiskTranslateSourcePool: Don't re-translate already
translated defs
  qemu: domain: Allow preserving translated disk type='volume' data into
XML if needed
  qemustatusxml2xmltest: Demonstrate use of
VIR_DOMAIN_DEF_(PARSE|FORMAT)_VOLUME_TRANSLATED
  conf: Save translated disk definition for disk type='volume' to status
XML
  security: apparmor: Use translated disk definitions for disk
type=volume

 src/conf/domain_conf.c| 111 --
 src/conf/domain_conf.h|   4 +
 src/conf/storage_source_conf.h|   3 +-
 src/conf/virdomainobjlist.c   |   3 +-
 src/security/security_apparmor.c  |   8 +-
 src/security/virt-aa-helper.c |   3 +-
 tests/qemustatusxml2xmldata/modern-in.xml |   4 +-
 tests/qemustatusxml2xmltest.c |   6 +-
 8 files changed, 84 insertions(+), 58 deletions(-)

-- 
2.41.0



[PATCH 3/7] virDomainDiskTranslateSourcePool: Don't re-translate already translated defs

2023-10-12 Thread Peter Krempa
If a disk definition was already translated re-doing it makes no sense.

Skip the translation if the 'actualtype' is already populated.

Signed-off-by: Peter Krempa 
---
 src/conf/domain_conf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3e0989e2e8..e128457b00 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30529,7 +30529,7 @@ virDomainDiskTranslateSourcePool(virDomainDiskDef *def)
 virStorageSource *n;

 for (n = def->src; virStorageSourceIsBacking(n); n = n->backingStore) {
-if (n->type != VIR_STORAGE_TYPE_VOLUME || !n->srcpool)
+if (n->type != VIR_STORAGE_TYPE_VOLUME || !n->srcpool || 
n->srcpool->actualtype != VIR_STORAGE_TYPE_NONE)
 continue;

 if (!conn) {
-- 
2.41.0



[PATCH 7/7] security: apparmor: Use translated disk definitions for disk type=volume

2023-10-12 Thread Peter Krempa
The 'virt-aa-helper' process gets a XML of the VM it needs to create a
profile for. For a disk type='volume' this XML contained only the
pool and volume name.

The 'virt-aa-helper' needs a local path though for anything it needs to
label. This means that we'd either need to invoke connection to the
storage driver and re-resolve the volume. Alternative which makes more
sense is to pass the proper data in the XML already passed to it via the
new XML formatter and parser flags.

This was indirectly reported upstream in
https://gitlab.com/libvirt/libvirt/-/issues/546

The configuration in the issue above was created by Cockpit on Debian.
Since Cockpit is getting more popular it's more likely that users will
be impacted by this problem.

Signed-off-by: Peter Krempa 
---
 src/security/security_apparmor.c | 8 ++--
 src/security/virt-aa-helper.c| 3 ++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index bce797de7c..6fd0aedacf 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -159,13 +159,17 @@ load_profile(virSecurityManager *mgr G_GNUC_UNUSED,
  bool append)
 {
 bool create = true;
+g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
 g_autofree char *xml = NULL;
 g_autoptr(virCommand) cmd = NULL;

-xml = virDomainDefFormat(def, NULL, VIR_DOMAIN_DEF_FORMAT_SECURE);
-if (!xml)
+if (virDomainDefFormatInternal(def, NULL, ,
+   VIR_DOMAIN_DEF_FORMAT_SECURE |
+   VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED) < 
0)
 return -1;

+xml = virBufferContentAndReset();
+
 if (profile_status_file(profile) >= 0)
 create = false;

diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 0855eb68ca..be13979cef 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -654,7 +654,8 @@ get_definition(vahControl * ctl, const char *xmlStr)
 ctl->def = virDomainDefParseString(xmlStr,
ctl->xmlopt, NULL,
VIR_DOMAIN_DEF_PARSE_SKIP_SECLABEL |
-   VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
+   VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE |
+   VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED);

 if (ctl->def == NULL) {
 vah_error(ctl, 0, _("could not parse XML"));
-- 
2.41.0



Re: [PATCH 1/1] Checking the value returned by the function

2023-10-11 Thread Peter Krempa
On Wed, Oct 11, 2023 at 15:24:17 +0300, Sergey Mironov wrote:
> The virSecuritySELinuxSetFilecon function (by definition) always returns 
> values 0 or -1.
> The result of this function is written to 'ret'.
> The code compares the value of the variable 'ret' with 1.
> 
> Signed-off-by: Sergey Mironov 
> ---
>  src/security/security_selinux.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
> index 7914aba84d..7bff780ddf 100644
> --- a/src/security/security_selinux.c
> +++ b/src/security/security_selinux.c
> @@ -1988,7 +1988,7 @@ 
> virSecuritySELinuxSetImageLabelInternal(virSecurityManager *mgr,
>  ret = virSecuritySELinuxSetFilecon(mgr, path, use_label, remember);
>  }
>  
> -if (ret == 1 && !disk_seclabel) {
> +if (ret == -1 && !disk_seclabel) {

Based on the git history it appears that this condition is impossible to
satisfy for more than 10 years. If that is so we need to first assess if
we even want to make this code active, given that it wans't a problem
for such a long time.

It's also possible that it became impossible to reach after a change
outside of the context I've checked, but either way it should not be
blindly fixed even if it appears to be what the author intended
originally



Re: [PATCHv2 1/1] Changes from [v1]:

2023-10-11 Thread Peter Krempa
On Wed, Oct 11, 2023 at 11:19:08 +0300, Sergey Mironov wrote:
> - now checked devAlias and making the code more robust in case when qemu stop 
> sending a devAlias
> 
> [v1] https://listman.redhat.com/archives/libvir-list/2023-October/242544.html

When this is commited to the repository the history of reviews is no
longer important. The commit message should not include it at all and
neither link to previous versions, but rather just state what the patch
is doing.

I'll address that by rewriting the commit message before pushing, so you
don't need to send another version, just keep that in mind for next
time.

> 
> Signed-off-by: Sergey Mironov 
> 
> ---
> v2: devAlias pointer was checked
> ---
>  src/qemu/qemu_monitor_json.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 5b9edadcf7..e37faff683 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -934,7 +934,7 @@ qemuMonitorJSONHandleTrayChange(qemuMonitor *mon,
>  int reason;
>  
>  /* drive alias is always reported but empty for -blockdev */
> -if (*devAlias == '\0')
> +if (devAlias && *devAlias == '\0')

Reviewed-by: Peter Krempa 



Re: [PATCH 1/1] The virJSONValueObjectGetString function can return NULL, there are no checks

2023-10-10 Thread Peter Krempa
On Tue, Oct 10, 2023 at 17:55:26 +0300, Sergey Mironov wrote:
> The devAlias check is performed in the "if (!devAlias && !devid) {", so the 
> situation is not handled when devAlias is NULL, and devid is not NULL
> 
> Signed-off-by: Sergey Mironov 
> ---
>  src/qemu/qemu_monitor_json.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 5b9edadcf7..80b41d77d3 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -933,6 +933,11 @@ qemuMonitorJSONHandleTrayChange(qemuMonitor *mon,
>  bool trayOpened;
>  int reason;
>  
> +if (!devAlias) {
> +VIR_WARN("missing device in tray change event");
> +return;
> +}

This is not correct and based on a wrong assumption. Currently the code
always gets a 'devAlias' set but it *may* be an empty string.

If it is an empty string it's cleared first before continuing.

Then if both the alias and 'id' is NULL the function terminates.

Making the code more robust in case when qemu stops sending a devAlias
is a good thing though, but the fix propsed here would break the
function as it would end early even if 'devid' is non-NULL. The
code afterwards is okay with devAlias being NULL.

Thus the correct fix is for the condition to read:

  if (devAlias && *devAlias == '\0')
  devAlias = NULL;

and leave the other logic as-is.



Re: [RFC PATCH 4/4] qemu_command: Added "ebpf_rss_fds" support for virtio-net.

2023-10-09 Thread Peter Krempa
On Mon, Oct 09, 2023 at 09:16:14 +0300, Andrew Melnychenko wrote:
> Added logic for loading the "RSS" eBPF program.
> eBPF file descriptors passed to the QEMU.
> 
> Signed-off-by: Andrew Melnychenko 
> ---
>  src/qemu/qemu_command.c | 53 +
>  src/qemu/qemu_domain.c  |  4 
>  src/qemu/qemu_domain.h  |  3 +++
>  3 files changed, 60 insertions(+)

This will require addition to qemuxml2argvtest once the qemu bit is
ready.


> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 8a7b80719f..ca6cb1bc7a 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -3786,6 +3786,23 @@ qemuBuildLegacyNicStr(virDomainNetDef *net)
> NULLSTR_EMPTY(net->info.alias));
>  }
>  
> +static char *qemuBuildEbpfRssArg(virDomainNetDef *net) {
> +qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
> +g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
> +size_t nfds;
> +GSList *n;
> +
> +if (netpriv->ebpfrssfds) {

This check is not needed.

> +nfds = 0;
> +for (n = netpriv->ebpfrssfds; n; n = n->next) {
> +virBufferAsprintf(, "%s:", qemuFDPassDirectGetPath(n->data));
> +nfds++;

'nfds' is not used.


> +}
> +}
> +virBufferTrim(, ":");
> +
> +return virBufferContentAndReset();
> +}
>  
>  virJSONValue *
>  qemuBuildNicDevProps(virDomainDef *def,
> @@ -3871,6 +3888,11 @@ qemuBuildNicDevProps(virDomainDef *def,
>"T:failover", failover,
>NULL) < 0)
>  return NULL;
> +if (net->driver.virtio.rss == VIR_TRISTATE_SWITCH_ON && 
> virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EBPF_RSS_FDS)){

This check should not be needed here ...

> +g_autofree char *ebpf = qemuBuildEbpfRssArg(net);

Because this will return a NULL string if it was not set up. 

> +if (virJSONValueObjectAdd(, "S:ebpf_rss_fds", ebpf, NULL) 
> < 0)

This is definitely not needed in a separate step and can be done in the
block above as "S:" skipps the attribute if the argument is NULL.

> +return NULL;
> +}
>  } else {
>  if (virJSONValueObjectAdd(,
>"s:driver", 
> virDomainNetGetModelString(net),
> @@ -4152,6 +4174,33 @@ qemuBuildWatchdogDevProps(const virDomainDef *def,
>  }
>  
>  
> +static void qemuOpenEbpfRssFds(virDomainNetDef *net,
> +  virQEMUCaps *qemuCaps) {
> +const void *ebpfRSSObject = NULL;
> +size_t ebpfRSSObjectSize = 0;
> +int fds[16];

16 feels arbitrary

> +int nfds = 0;
> +qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
> +
> +netpriv->libbpfRSSObject = NULL;
> +netpriv->ebpfrssfds = NULL;
> +
> +/* Add ebpf values */
> +if (net->driver.virtio.rss == VIR_TRISTATE_SWITCH_ON && 
> virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EBPF_RSS_FDS)) {

This line is too long and there's a good spot to break it up;

> +ebpfRSSObject = virQEMUCapsGetEbpf(qemuCaps, "rss", 
> );
> +nfds = qemuInterfaceLoadEbpf(ebpfRSSObject, ebpfRSSObjectSize, 
> >libbpfRSSObject, fds, 16);

Note that the '16' argument is unused by the callee.

Also note that when running an unprivileged instance of libvirt, this
function might not have permissions to do anything. It seems that the
rest is okay, but we need to avoid any form of spurious errors and such
if that is really okay and there are fallback paths.

> +
> +if (nfds > 0) {
> +for (int i = 0; i < nfds; ++i) {
> +g_autofree char *name = g_strdup_printf("ebpfrssfd-%s-%u", 
> net->info.alias, i);
> +netpriv->ebpfrssfds = g_slist_prepend(netpriv->ebpfrssfds, 
> qemuFDPassDirectNew(name, fds + i));
> +}
> +netpriv->ebpfrssfds = g_slist_reverse(netpriv->ebpfrssfds);
> +}
> +}
> +}
> +
> +
>  static int
>  qemuBuildWatchdogCommandLine(virCommand *cmd,
>   const virDomainDef *def,
> @@ -8735,6 +8784,10 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
>  qemuFDPassDirectTransferCommand(netpriv->slirpfd, cmd);
>  qemuFDPassTransferCommand(netpriv->vdpafd, cmd);
>  
> +qemuOpenEbpfRssFds(net, qemuCaps);

Note that this will cause problems when you'll be about to test this
functionality in qemuxml2argvtest. The test code must not modify the
host state, so this will either need to be mocked in the testsuite or
you'll need to move it to the host-prepare function
'qemuProcessPrepareHost' which is skipped from the test suite. The test
suite will then need to fake the data.

> +for (n = netpriv->ebpfrssfds; n; n = n->next)
> +qemuFDPassDirectTransferCommand(n->data, cmd);
> +
>  if (!(hostnetprops = qemuBuildHostNetProps(vm, net)))
>  goto cleanup;
>  
> diff --git a/src/qemu/qemu_domain.c 

Re: [RFC PATCH 3/4] qemu_interface: Added routine for loading the eBPF objects.

2023-10-09 Thread Peter Krempa
On Mon, Oct 09, 2023 at 09:16:13 +0300, Andrew Melnychenko wrote:
> Also, added dependencies for libbpf with bpf option.
> 
> Signed-off-by: Andrew Melnychenko 
> ---
>  meson.build   |  6 ++
>  meson_options.txt |  1 +
>  src/qemu/meson.build  |  1 +
>  src/qemu/qemu_interface.c | 42 +++
>  src/qemu/qemu_interface.h |  4 
>  5 files changed, 54 insertions(+)

Yet again fails to compile:

a.p/qemu_interface.c.o -c ../../../libvirt/src/qemu/qemu_interface.c
../../../libvirt/src/qemu/qemu_interface.c: In function ‘qemuInterfaceLoadEbpf’:
../../../libvirt/src/qemu/qemu_interface.c:779:5: error: ISO C90 forbids mixed 
declarations and code [-Werror=declaration-after-statement]
  779 | struct bpf_program *prog;
  | ^~
../../../libvirt/src/qemu/qemu_interface.c:769:103: error: unused parameter 
‘nfds’ [-Werror=unused-parameter]
  769 | int qemuInterfaceLoadEbpf(const void *ebpfObject, size_t ebpfSize, void 
**retLibbpfObj, int *fds, int nfds) {
  | 
  ^~~~

Fixing that also shows that the syntax-check rules were also broken.

> 
> diff --git a/meson.build b/meson.build
> index de23fbda1e..b68e916246 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -1381,6 +1381,11 @@ if yajl_dep.found()
>conf.set('WITH_YAJL', 1)
>  endif
>  
> +bpf_version = '1.1.0'
> +bpf_dep = dependency('libbpf', version: '>=' + bpf_version, required: 
> get_option('bpf'))
> +if bpf_dep.found()
> +conf.set('WITH_BPF', 1)
> +endif
>  
>  # generic build dependencies checks
>  
> @@ -2269,6 +2274,7 @@ libs_summary = {
>'udev': udev_dep.found(),
>'xdr': xdr_dep.found(),
>'yajl': yajl_dep.found(),
> +  'bpf': bpf_dep.found(),
>  }
>  summary(libs_summary, section: 'Libraries', bool_yn: true)
>  
> diff --git a/meson_options.txt b/meson_options.txt
> index 7c428a9eb0..092b2efe06 100644
> --- a/meson_options.txt
> +++ b/meson_options.txt
> @@ -44,6 +44,7 @@ option('udev', type: 'feature', value: 'auto', description: 
> 'udev support')
>  option('wireshark_dissector', type: 'feature', value: 'auto', description: 
> 'wireshark support')
>  option('wireshark_plugindir', type: 'string', value: '', description: 
> 'wireshark plugins directory for use when installing wireshark plugin')
>  option('yajl', type: 'feature', value: 'auto', description: 'yajl support')
> +option('bpf', type: 'feature', value: 'auto', description: 'qemu libbpf 
> support')
>  
>  
>  # build driver options
> diff --git a/src/qemu/meson.build b/src/qemu/meson.build
> index 64c62e584f..afd9133ae0 100644
> --- a/src/qemu/meson.build
> +++ b/src/qemu/meson.build
> @@ -105,6 +105,7 @@ if conf.has('WITH_QEMU')
>selinux_dep,
>src_dep,
>xdr_dep,
> +  bpf_dep,
>  ],
>  include_directories: [
>conf_inc_dir,
> diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
> index 8856bb95a8..a3a43a43c5 100644
> --- a/src/qemu/qemu_interface.c
> +++ b/src/qemu/qemu_interface.c
> @@ -36,6 +36,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #define VIR_FROM_THIS VIR_FROM_QEMU
>  
> @@ -763,3 +764,44 @@ qemuInterfaceOpenVhostNet(virDomainObj *vm,
>  virDomainAuditNetDevice(vm->def, net, vhostnet_path, vhostfdSize);
>  return 0;
>  }
> +
> +

Please document this function. It's not very obvious what it does on the
first glance.

> +int qemuInterfaceLoadEbpf(const void *ebpfObject, size_t ebpfSize, void 
> **retLibbpfObj, int *fds, int nfds) {
> +int err = 0;
> +int i = 0;
> +
> +struct bpf_object *obj = bpf_object__open_mem(ebpfObject, ebpfSize, 
> NULL);

This is compiled regardless of 'WITH_BPF' flag ...

> +err = libbpf_get_error(obj);
> +if(err) {
> +return -1;
> +}



Re: [RFC PATCH 2/4] qemu_capabilities: Added new capability ebpf_rss_fds for QEMU.

2023-10-09 Thread Peter Krempa
On Mon, Oct 09, 2023 at 09:16:12 +0300, Andrew Melnychenko wrote:
> Also, added logic for retrieving eBPF objects from QEMU.
> eBPF objects stored in the hash table during runtime.
> eBPF objects cached encoded in base64 in the .xml cache file.
> 
> Signed-off-by: Andrew Melnychenko 
> ---
>  src/qemu/qemu_capabilities.c | 181 +++
>  src/qemu/qemu_capabilities.h |   4 +
>  2 files changed, 185 insertions(+)

Once again, make sure to check that each patch builds and passes tests.
This one fails to compile:

u/libvirt_driver_qemu_impl.a.p/qemu_capabilities.c.o -c 
../../../libvirt/src/qemu/qemu_capabilities.c
../../../libvirt/src/qemu/qemu_capabilities.c:808:6: error: no previous 
prototype for ‘virQEMUEbpfOBjectDataDestroy’ [-Werror=missing-prototypes]
  808 | void virQEMUEbpfOBjectDataDestroy(gpointer data) {
  |  ^~~~
../../../libvirt/src/qemu/qemu_capabilities.c: In function 
‘virQEMUEbpfOBjectDataDestroy’:
../../../libvirt/src/qemu/qemu_capabilities.c:811:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
  811 | struct virQEMUEbpfOBjectData *object = data;
  | ^~
../../../libvirt/src/qemu/qemu_capabilities.c: In function 
‘virQEMUCapsProbeQMPEbpfObject’:
../../../libvirt/src/qemu/qemu_capabilities.c:5560:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5560 | struct virQEMUEbpfOBjectData *object = g_malloc(sizeof(*object));
  | ^~
../../../libvirt/src/qemu/qemu_capabilities.c: In function 
‘virQEMUCapsProbeQMPSchemaEbpf’:
../../../libvirt/src/qemu/qemu_capabilities.c:5573:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5573 | virJSONValue *requestSchema = virHashLookup(schema, "request-ebpf");
  | ^~~~
../../../libvirt/src/qemu/qemu_capabilities.c:5577:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5577 | const char *argType = virJSONValueObjectGetString(requestSchema, 
"arg-type");
  | ^
../../../libvirt/src/qemu/qemu_capabilities.c:5581:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5581 | virJSONValue *argSchema = virHashLookup(schema, argType);
  | ^~~~
../../../libvirt/src/qemu/qemu_capabilities.c:5586:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5586 | virJSONValue *members = virJSONValueObjectGetArray(argSchema, 
"members");
  | ^~~~
../../../libvirt/src/qemu/qemu_capabilities.c:5591:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5591 | virJSONValue *idSchema = NULL;
  | ^~~~
../../../libvirt/src/qemu/qemu_capabilities.c:5601:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5601 | const char *ebpfIds = virJSONValueObjectGetString(idSchema, "type");
  | ^
../../../libvirt/src/qemu/qemu_capabilities.c:5606:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5606 | virJSONValue *ebpfIdsArray = 
virJSONValueObjectGetArray(ebpfIdsSchema, "values");
  | ^~~~
../../../libvirt/src/qemu/qemu_capabilities.c:5611:5: error: ISO C90 forbids 
mixed declarations and code [-Werror=declaration-after-statement]
 5611 | virJSONValue *id = NULL;
  | ^~~~
cc1: all warnings being treated as errors


After the compile error is fixed there are further errors caught by
syntax-check.


> @@ -789,6 +790,9 @@ struct _virQEMUCaps {
>  virQEMUCapsAccel kvm;
>  virQEMUCapsAccel hvf;
>  virQEMUCapsAccel tcg;
> +
> +/* Hash of ebpf objects virQEMUEbpfOBjectData */
> +GHashTable *ebpfObjects;
>  };
>  
>  struct virQEMUCapsSearchData {
> @@ -796,6 +800,18 @@ struct virQEMUCapsSearchData {
>  const char *binaryFilter;
>  };
>  
> +struct virQEMUEbpfOBjectData {
> +void *ebpfData;
> +size_t ebpfSize;
> +};
> +
> +void virQEMUEbpfOBjectDataDestroy(gpointer data) {
> +if (!data)
> +return;
> +struct virQEMUEbpfOBjectData *object = data;
> +g_free(object->ebpfData);
> +g_free(data);
> +}


As noted, store the program as the base64 string throughout libvirt,
none of the above will be needed.


>  
>  static virClass *virQEMUCapsClass;
>  static void virQEMUCapsDispose(void *obj);
> @@ -836,6 +852,19 @@ const char *virQEMUCapsArchToString(virArch arch)
>  }
>  
>  
> +const void *
> +virQEMUCapsGetEbpf(virQEMUCaps *qemuCaps, const char *id, size_t *size)
> +{
> +struct virQEMUEbpfOBjectData *object = 
> virHashLookup(qemuCaps->ebpfObjects, id);
> +
> +if (!object)
> +return NULL;
> +
> +*size = object->ebpfSize;
> +return object->ebpfData;
> +}
> +
> +
>  /* Checks whether a domain with @guest arch can run 

Re: [RFC PATCH 1/4] qemu_monitor: Added QEMU's "request-ebpf" support.

2023-10-09 Thread Peter Krempa
On Mon, Oct 09, 2023 at 09:16:11 +0300, Andrew Melnychenko wrote:
> Added code for monitor and monitor_json.
> The "request-ebpf" return's eBPF binary object encoded in base64.
> The function qemuMonitorGetEbpf() returns a decoded blob.
> 
> QEMU provides eBPF that can be loaded and passed to it from Libvirt.
> QEMU requires exact eBPF program/maps, so it can be retrieved using QAPI.
> To load eBPF program - administrative capabilities are required, so Libvirt 
> may load it and pass it to the QEMU instance.
> For now, there is only "RSS"(Receive Side Scaling) for virtio-net eBPF 
> program and maps.

Please wrap the text in the commit message to the usual line length.
Since it's just explanation, the sentences can be neatly wrapped. Long
lines in commit message are acceptable only if it's impossible to split
them or splitting them would destroy the content (e.g. do not split
pasted output of commands).


> Signed-off-by: Andrew Melnychenko 
> ---
>  src/qemu/qemu_monitor.c  | 23 +++
>  src/qemu/qemu_monitor.h  |  3 +++
>  src/qemu/qemu_monitor_json.c | 21 +
>  src/qemu/qemu_monitor_json.h |  3 +++
>  4 files changed, 50 insertions(+)
> 
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 320729f067..07596c78ee 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -4512,3 +4512,26 @@ qemuMonitorGetStatsByQOMPath(virJSONValue *arr,
>  
>  return NULL;
>  }

See coding style problems mentioned in reply to cover letter.

> +
> +void *
> +qemuMonitorGetEbpf(qemuMonitor *mon, const char *ebpfName, size_t *size)
> +{
> +QEMU_CHECK_MONITOR_NULL(mon);

Fails to compile:


In file included from /usr/lib64/glib-2.0/include/glibconfig.h:9,
 from /usr/include/glib-2.0/glib/gtypes.h:34,
 from /usr/include/glib-2.0/glib/galloca.h:34,
 from /usr/include/glib-2.0/glib.h:32,
 from /usr/include/glib-2.0/gobject/gbinding.h:30,
 from /usr/include/glib-2.0/glib-object.h:24,
 from /usr/include/glib-2.0/gio/gioenums.h:30,
 from /usr/include/glib-2.0/gio/giotypes.h:30,
 from /usr/include/glib-2.0/gio/gio.h:28,
 from ../../../libvirt/src/qemu/qemu_monitor.c:27:
../../../libvirt/src/qemu/qemu_monitor.c: In function ‘qemuMonitorGetEbpf’:
/usr/include/glib-2.0/glib/gmacros.h:1347:43: error: ISO C90 forbids mixed 
declarations and code [-Werror=declaration-after-statement]
 1347 | #define _GLIB_CLEANUP(func)   __attribute__((cleanup(func)))
  |   ^
/usr/include/glib-2.0/glib/gmacros.h:1380:29: note: in expansion of macro 
‘_GLIB_CLEANUP’
 1380 | #define g_autoptr(TypeName) 
_GLIB_CLEANUP(_GLIB_AUTOPTR_FUNC_NAME(TypeName)) 
_GLIB_AUTOPTR_TYPENAME(TypeName)
  | ^
../../../libvirt/src/qemu/qemu_monitor.c:4520:5: note: in expansion of macro 
‘g_autoptr’
 4520 | g_autoptr(virJSONValue) reply = NULL;
  | ^
cc1: all warnings being treated as errors


Make sure your code compiles and passes test suite after every single
patch per our coding guidelines.


> +g_autoptr(virJSONValue) reply = NULL;
> +const char *ebpfBase64 = NULL;
> +void *ebpfObject = NULL;
> +
> +if (ebpfName == NULL || size == NULL)

You are mixing returns which do not set a libvirt error ...

> +return NULL;
> +
> +reply = qemuMonitorJSONGetEbpf(mon, ebpfName);
> +
> +if (reply == NULL)

... with those that do. This is not a good idea as the caller can't
distinguish easily whether it's an error or desired NULL value. We don't
allow that.

> +return NULL;
> +
> +ebpfBase64 = virJSONValueObjectGetString(reply, "object");
> +
> +ebpfObject = g_base64_decode(ebpfBase64, size);

I'd very strongly prefer that this is stored in the base64 form inside
libvirt and decoded just before use. Storing strings is simpler, doesn't
require you to pass around the 'size' needlessly and simplifies the XML
formatter/parser in capabilities.

Also please move all extraction of data from the monitor reply to the
JSON command. The qemu_monitor.c wrapper at this point should simply
pass through. It might eventually be completely removed as it serves no
purpose once the HMP monitor support was deleted. (And before that it'd
be semantically wrong because you pass the JSON out of the QMP
function).

> +
> +return ebpfObject;
> +}
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 6c590933aa..15f32f105c 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -1579,3 +1579,6 @@ qemuMonitorExtractQueryStats(virJSONValue *info);
>  virJSONValue *
>  qemuMonitorGetStatsByQOMPath(virJSONValue *arr,
>   char *qom_path);
> +
> +void *
> +qemuMonitorGetEbpf(qemuMonitor *mon, const char *ebpfName, size_t *size);
> diff --git 

Re: [RFC PATCH 0/4] Added virtio-net RSS with eBPF support.

2023-10-09 Thread Peter Krempa
On Mon, Oct 09, 2023 at 10:15:34 +0200, Peter Krempa wrote:
> On Mon, Oct 09, 2023 at 09:16:10 +0300, Andrew Melnychenko wrote:
> > This series of rfc patches adds support for loading the RSS eBPF program 
> > and passing it to the QEMU.
> > Comments and suggestions would be useful.
> > 
> > QEMU with vhost may work with RSS through eBPF. To load eBPF,
> > the capabilities required that Libvirt may provide.
> > eBPF program and maps may be unique for particular QEMU and
> > Libvirt retrieves eBPF through qapi.
> > For now, there is only "RSS" eBPF object in QEMU, in the future,
> > there may be another one(g.e. network filters).
> > That's why in Libvirt added logic to load and store any
> > eBPF object that QEMU provides using qapi schema.
> > 
> > For virtio-net RSS, the document has not changed.
> > ```
> >  
> >   
> >   
> >  
> > ```
> > 
> > Simplified routine for RSS:
> >  * Libvirt retrieves eBPF "RSS" and load it.
> >  * Libvirt passes file descriptors to virtio-net with property 
> > "ebpf_rss_fds" ("rss" property should be "on" too).
> >  * if fds was provided - QEMU using eBPF RSS implementation.
> >  * if fds was not provided - QEMU tries to load eBPF RSS in own context and 
> > use it.
> >  * if eBPF RSS was not loaded - QEMU uses "in-qemu" RSS(vhost not 
> > supported).
> 
> Hi,
> 

Also what is the status of the qemu patches, specifically the QMP
interface? I see that the patch was in v1 of Jasons 'Net patches' pull
request in September, but was dropped in v2 for some reason.

Specifically our policy is that a feature depending on new qemu
interfaces can be merged to libvirt only after the code was comitted to
qemu.

We do not require that it is released, in fact we follow the development
cycle with the the "qemu capabilities" updates done throughout the the
dev cycle.

Once the qemu code is merged I can do the required update of the
capability test output (tests/qemucapabilitiesdata/...replies) output
file based on your patch so that churn and your manual input is
minimized.



Re: [RFC PATCH 0/4] Added virtio-net RSS with eBPF support.

2023-10-09 Thread Peter Krempa
On Mon, Oct 09, 2023 at 09:16:10 +0300, Andrew Melnychenko wrote:
> This series of rfc patches adds support for loading the RSS eBPF program and 
> passing it to the QEMU.
> Comments and suggestions would be useful.
> 
> QEMU with vhost may work with RSS through eBPF. To load eBPF,
> the capabilities required that Libvirt may provide.
> eBPF program and maps may be unique for particular QEMU and
> Libvirt retrieves eBPF through qapi.
> For now, there is only "RSS" eBPF object in QEMU, in the future,
> there may be another one(g.e. network filters).
> That's why in Libvirt added logic to load and store any
> eBPF object that QEMU provides using qapi schema.
> 
> For virtio-net RSS, the document has not changed.
> ```
>  
>   
>   
>  
> ```
> 
> Simplified routine for RSS:
>  * Libvirt retrieves eBPF "RSS" and load it.
>  * Libvirt passes file descriptors to virtio-net with property "ebpf_rss_fds" 
> ("rss" property should be "on" too).
>  * if fds was provided - QEMU using eBPF RSS implementation.
>  * if fds was not provided - QEMU tries to load eBPF RSS in own context and 
> use it.
>  * if eBPF RSS was not loaded - QEMU uses "in-qemu" RSS(vhost not supported).

Hi,

please note that in my review following this mail I'll be mostly
commenting about general problems, coding style problems and the
capabilies probing an caching.

I'm not familiar with what this feature is supposed to be doing as I'm
involved more with storage and I maintain the qemu capability code.

Thus input of others may be needed in terms of the actual feature.

>  meson.build  |   6 ++
>  meson_options.txt|   1 +
>  src/qemu/meson.build |   1 +
>  src/qemu/qemu_capabilities.c | 181 +++
>  src/qemu/qemu_capabilities.h |   4 +
>  src/qemu/qemu_command.c  |  53 ++
>  src/qemu/qemu_domain.c   |   4 +
>  src/qemu/qemu_domain.h   |   3 +
>  src/qemu/qemu_interface.c|  42 
>  src/qemu/qemu_interface.h|   4 +
>  src/qemu/qemu_monitor.c  |  23 +
>  src/qemu/qemu_monitor.h  |   3 +
>  src/qemu/qemu_monitor_json.c |  21 
>  src/qemu/qemu_monitor_json.h |   3 +

During a quick look at the patches I've noticed few repeated coding
style problems.

Note that our prefered function declaration/definition header is

virReturnType *
virFunctionName(virFirstArg argname,
virSecondArg *argval,
virEtc etc)
{

}

We also keep two line spacing between functions.

Additionally we also require C90-style variable declarations (variable
declaration must not mix with code inside a block).

Other comments inline.



Re: [PATCH] qemu: add 'media=cdrom' attribute for usb CDROM

2023-10-07 Thread Peter Krempa
On Sat, Oct 07, 2023 at 16:12:09 +0800, Minglei Liu wrote:
> From: "minglei.liu" 
> 
> In commit 1328a83, the 'media=cdrom' attribute was removed from -drive.
> However, this attribute is still essential for usb cdrom and is still
> supported in qemu 8.1.1. Therefore, we need to reintroduce this attribute
> for usb cdrom.

This just states that it _is_ needed but not why. Please add
justification next time.

Your patch is also missing ceritifcation that it conforms with the
Developer Certificate of origin:

https://www.libvirt.org/hacking.html#developer-certificate-of-origin

> ---
>  src/qemu/qemu_command.c| 7 +++
>  .../disk-cdrom-bus-other.x86_64-latest.args| 2 +-
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 8a7b80719f..42f3f8f740 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -1705,6 +1705,13 @@ qemuBuildDriveStr(virDomainDiskDef *disk)
>  
>  virBufferAsprintf(, "if=sd,index=%d", virDiskNameToIndex(disk->dst));
>  
> +/* While this is a frontend attribute, it only makes sense to be used 
> when
> + * legacy -drive is used. In modern qemu the 'ide-cd' or 'scsi-cd' are 
> used.
> + * currently only usb cdrom need this attribute */
> +if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
> +disk->bus == VIR_DOMAIN_DISK_BUS_USB)
> +virBufferAddLit(, ",media=cdrom");

This code path is exclusively used for '-drive if=sd'. All other code
paths use -blockdev. Thus this hunk and it's explanation makes no sense.
This will never be executed for USB cdroms.

If you want to add USB cdrom device frontend properties you need to
modify qemuBuildDiskDeviceProps.

Please note though that the 'usb-storage' device does not have a 'media'
parameter or anything similar.

> +
>  if (disk->src->readonly)
>  virBufferAddLit(, ",readonly=on");
>  
> diff --git a/tests/qemuxml2argvdata/disk-cdrom-bus-other.x86_64-latest.args 
> b/tests/qemuxml2argvdata/disk-cdrom-bus-other.x86_64-latest.args
> index de5fa083d8..38093423cf 100644
> --- a/tests/qemuxml2argvdata/disk-cdrom-bus-other.x86_64-latest.args
> +++ b/tests/qemuxml2argvdata/disk-cdrom-bus-other.x86_64-latest.args
> @@ -27,7 +27,7 @@ 
> XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
>  -no-shutdown \
>  -boot strict=on \
>  -device 
> '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
> --blockdev 
> '{"driver":"file","filename":"/root/boot.iso","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}'
>  \
> +-blockdev 
> '{"driver":"file","filename":"/root/boot.iso","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap","media":"cdrom"}'
>  \
>  -blockdev 
> '{"node-name":"libvirt-2-format","read-only":true,"driver":"raw","file":"libvirt-2-storage"}'
>  \

And this makes no sense either. You are modifying a test output file
which will not be formatted like this by the code. In fact with this
patch the test suite will fail.

Also -blockdev is the device backend so the placement doesn't make any
sense either.

For the next version please add a justification (description what the
actual problem is) in the first place. Do not attempt to modify anything
'-drive' related. Those code paths are deprecated and we don't add new
features for them. As noted, nowadays it's used only for disk bus='sd'.a

Also make sure you run the test-suite before posting patches



Re: [RFC: vf-token 5/5] qemu: validate and generate vf-token on command line

2023-10-06 Thread Peter Krempa
On Thu, Oct 05, 2023 at 16:05:04 -0700, Vivek Kashyap wrote:
> Introduce a validation function for vf-token support in qemu
> and generate vf-token device attribute in qmeu command line.
> 
> Signed-off-by: Vivek Kashyap 
> ---
>  src/qemu/qemu_command.c  | 27 ---
>  src/qemu/qemu_validate.c | 19 +++
>  2 files changed, 43 insertions(+), 3 deletions(-)

Missing qemuxml2argvtest and qemuxml2xmtest additions, which are
absolutely required for anything that adds/changes the commandline syntax.


> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 8a7b80719f..91d7836f5c 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -1979,7 +1979,6 @@ qemuBuildZPCIDevProps(virDomainDeviceInfo *dev)
>  return props;
>  }
>  
> -

Spurious whitespace change. As noted we do 2 lines between functions.

>  static int
>  qemuCommandAddExtDevice(virCommand *cmd,
>  virDomainDeviceInfo *dev,
> @@ -4729,6 +4728,8 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
>  pcisrc->addr.slot,
>  pcisrc->addr.function);
>  const char *failover_pair_id = NULL;
> +g_autofree char *token = NULL;
> +int ret = 0;
>  
>  /* caller has to assign proper passthrough backend type */
>  switch (pcisrc->backend) {
> @@ -4755,13 +4756,33 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
>  teaming->persistent)
>  failover_pair_id = teaming->persistent;
>  
> -if (virJSONValueObjectAdd(,
> +if ((dev->info->pciAddrExtFlags & VIR_PCI_ADDRESS_EXTENSION_VFTOKEN) &&
> +  pcisrc->addr.token.isSet) {

Broken alignment/code style.

> +const unsigned char *uuid = pcisrc->addr.token.uuid;
> +
> +token = g_strdup_printf(VIR_PCI_DEVICE_TOKEN_FMT,
> +   uuid[0], uuid[1], uuid[2], uuid[3],
> +   uuid[4], uuid[5], uuid[6], uuid[7],
> +   uuid[8], uuid[9], uuid[10], uuid[11],
> +   uuid[12], uuid[13], uuid[14], uuid[15]);

Broken alignment/code style.

> +
> +ret = virJSONValueObjectAdd(,
>"s:driver", "vfio-pci",
>"s:host", host,
> +  "s:vf-token", token,
>"s:id", dev->info->alias,
>"p:bootindex", dev->info->effectiveBootIndex,
>"S:failover_pair_id", failover_pair_id,
> -  NULL) < 0)
> +  NULL);

So firstly you break the code style here by your addition.

Secondly there's no need to duplicate the whole virJSONValueObjectAdd
block in the first place as we allow conditional formatting of fields.

You need to fill the 'token' field only optionally what you do, but then
you can unconditionally format it using:


  "S:vf-token", token,

argument tuple in virJSONValueObjectAdd. The 'S' modifier formats the
attribute only if the string argument is non-NULL.


> +} else 

Trailing whitespace, but this block is not needed ... and in fact not
desired as described above.

> +ret = virJSONValueObjectAdd(,
> +  "s:driver", "vfio-pci",
> +  "s:host", host,
> +  "s:id", dev->info->alias,
> +  "p:bootindex", dev->info->effectiveBootIndex,
> +  "S:failover_pair_id", failover_pair_id,
> +  NULL);
> +if (ret < 0)
>  return NULL;
>  
>  if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)



Re: [RFC: vf-token 4/5] conf: vf-token parsing and formatting

2023-10-06 Thread Peter Krempa
On Thu, Oct 05, 2023 at 16:05:03 -0700, Vivek Kashyap wrote:
> Introduce XML parsing and formatting of vf-token attribute
> 
> Signed-off-by: Vivek Kashyap 
> ---
>  src/conf/device_conf.c| 31 +--
>  src/conf/domain_conf.c|  5 +
>  src/conf/schemas/basictypes.rng   | 11 +++
>  src/conf/schemas/domaincommon.rng |  1 +
>  src/libvirt_private.syms  |  1 +
>  src/util/virpci.c |  5 +
>  6 files changed, 52 insertions(+), 2 deletions(-)
> 
> diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
> index f3d977f2b7..d5ed4ef452 100644
> --- a/src/conf/device_conf.c
> +++ b/src/conf/device_conf.c
> @@ -188,11 +188,20 @@ virDeviceInfoPCIAddressExtensionIsWanted(const 
> virDomainDeviceInfo *info)
> virZPCIDeviceAddressIsIncomplete(>addr.pci.zpci);
>  }
>  
> +bool
> +virDeviceExtensionIsPresent(const virPCIDeviceAddress *pci)
> +{
> +return ((pci->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
> +virZPCIDeviceAddressIsPresent(>zpci)) ||
> +((pci->extFlags & VIR_PCI_ADDRESS_EXTENSION_VFTOKEN) &&
> +pci->token.isSet);

The code alignment is broken here. Also add a function documentation
describing what this function does as it's really not obvious.

> +}
> +

Code style dictates two empty lines between functions.

>  bool
>  virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info)
>  {
> -return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
> -   virZPCIDeviceAddressIsPresent(>addr.pci.zpci);
> +return (info->addr.pci.extFlags != VIR_PCI_ADDRESS_EXTENSION_NONE) &&
> +virDeviceExtensionIsPresent(>addr.pci);

This change is suspicious and should be justified. I'm not going to
comment on whether it's correct or not.

>  }
>  
>  int
> @@ -200,6 +209,7 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
>  virPCIDeviceAddress *addr)
>  {
>  xmlNodePtr zpci;
> +xmlNodePtr token;
>  
>  memset(addr, 0, sizeof(*addr));
>  
> @@ -231,6 +241,10 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
>  return -1;
>  }
>  
> +if ((token = virXMLNodeGetSubelement(node, "vf-token")))

Multi-line condition bodies dictate use of a { } block around it.

> +if (virPCIDeviceTokenParseXML(token, addr) < 0)
> +return -1;

This one is okay though.

> +
>  return 0;
>  }
>  
> @@ -248,6 +262,19 @@ virPCIDeviceAddressFormat(virBuffer *buf,
>addr.function);
>  }
>  
> +int
> +virPCIDeviceTokenParseXML(xmlNodePtr node,
> +  virPCIDeviceAddress *addr)
> +{
> +if (virXMLPropUUID(node, "uuid", VIR_XML_PROP_NONE,
> +   addr->token.uuid) < 0)

virXMLPropUUID parses into a buffer which is not a string (NUL-byte
terminated) but a byte array ...

> +return -1;
> +
> +addr->token.isSet = 1;
> +
> +return 0;
> +}
> +

Two empty lines between functions.

>  int
>  virCCWDeviceAddressParseXML(xmlNodePtr node,
>  virCCWDeviceAddress *addr)
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 4435ee2ad4..cceb1d3b83 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -5389,6 +5389,11 @@ virDomainDeviceInfoFormat(virBuffer *buf,
>info->addr.pci.zpci.uid.value,
>info->addr.pci.zpci.fid.value);
>  }
> +if (virPCIVFIOTokenIDIsPresent(>addr.pci.token)) {
> +virBufferAsprintf(,
> +  "\n",
> +  info->addr.pci.token.uuid);

... but here you use a *string* formatting function. So this will either
not print any reasonable output or potentially crash if the UUID
contains no NUL-bytes.

You would figure this out if you'd add any tests for this feature which
is in fact required. It is okay to add the tests at the end though.

> +}
>  break;
>  
>  case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
> diff --git a/src/conf/schemas/basictypes.rng b/src/conf/schemas/basictypes.rng
> index 26eb538077..bf2c30dd18 100644
> --- a/src/conf/schemas/basictypes.rng
> +++ b/src/conf/schemas/basictypes.rng
> @@ -138,6 +138,17 @@
>
>  
>
> +  
> +
> +  
> +
> +  
> +
> +  
> +
> +  
> +
> +  
>  
>
>
> diff --git a/src/conf/schemas/domaincommon.rng 
> b/src/conf/schemas/domaincommon.rng
> index a26986b5ce..b228a3ca73 100644
> --- a/src/conf/schemas/domaincommon.rng
> +++ b/src/conf/schemas/domaincommon.rng
> @@ -7034,6 +7034,7 @@
>
>
>
> +  
>  
>  
>

Any XML addition _must_ come with correspondign documentation update.
Please document the new flag and how it's supposed to be used in
docs/formatdomain.rst.


> diff --git 

Re: [RFC: vf-token 3/5] conf: vf-token flag

2023-10-06 Thread Peter Krempa
On Thu, Oct 05, 2023 at 16:05:02 -0700, Vivek Kashyap wrote:
> Define PCI address extension flag for vf-token
> 
> Signed-off-by: Vivek Kashyap 
> ---
>  src/conf/device_conf.h | 3 +++
>  src/conf/domain_addr.h | 1 +
>  src/qemu/qemu_domain_address.c | 3 +++
>  3 files changed, 7 insertions(+)
> 
> diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
> index a83377417a..29e03baa99 100644
> --- a/src/conf/device_conf.h
> +++ b/src/conf/device_conf.h
> @@ -188,6 +188,9 @@ bool virDeviceInfoPCIAddressExtensionIsPresent(const 
> virDomainDeviceInfo *info);
>  int virPCIDeviceAddressParseXML(xmlNodePtr node,
>  virPCIDeviceAddress *addr);
>  
> +int virPCIDeviceTokenParseXML(xmlNodePtr node,
> +virPCIDeviceAddress *addr);

Broken alignment of the second line. And same as in 1/5 the function is
not used here so don't define it in this patch.



Re: [RFC: vf-token 2/5] qemu: vf-token capability

2023-10-06 Thread Peter Krempa
On Thu, Oct 05, 2023 at 16:05:01 -0700, Vivek Kashyap wrote:
> Introduce qemu capability for vf-token
> 
> Signed-off-by: Vivek Kashyap 
> ---
>  src/qemu/qemu_capabilities.c | 3 +++
>  src/qemu/qemu_capabilities.h | 1 +
>  2 files changed, 4 insertions(+)
> 
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index 3a1bfbf74d..f84c4df8db 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -698,6 +698,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
>/* 450 */
>"run-with.async-teardown", /* 
> QEMU_CAPS_RUN_WITH_ASYNC_TEARDOWN */
>"virtio-blk-vhost-vdpa", /* 
> QEMU_CAPS_DEVICE_VIRTIO_BLK_VHOST_VDPA */
> +  "vf-token", /* QEMU_CAPS_VFIO_VFTOKEN */
>  );
>  
>  
> @@ -1384,6 +1385,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] 
> = {
>  { "virtio-crypto-device", QEMU_CAPS_DEVICE_VIRTIO_CRYPTO },
>  { "cryptodev-backend-lkcf", QEMU_CAPS_OBJECT_CRYPTO_LKCF },
>  { "pvpanic-pci", QEMU_CAPS_DEVICE_PANIC_PCI },
> +{ "vf-token", QEMU_CAPS_VFIO_VFTOKEN },
>  };
>  
>  
> @@ -1446,6 +1448,7 @@ static struct virQEMUCapsDevicePropsFlags 
> virQEMUCapsDevicePropsVirtioSCSI[] = {
>  };
>  
>  static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVfioPCI[] = {
> +{ "vf-token", QEMU_CAPS_VFIO_VFTOKEN, NULL }, 

Extra trailing whitespace.

>  };

Also the 'vf-token' field was added in qemu-8.1 thus you are missing the
appropriate test file updates.

Also the whitespace error would be caught by our test suite.

Please always make sure to post patches where our test suite passes
after every single commit:

https://www.libvirt.org/hacking.html#preparing-patches


Notably you'll need to re-generate the 'qemucapabilitiestest' output
files to include the new flag. To do so automatically run:

 VIR_TEST_REGENERATE_OUTPUT=1 ./tests/qemucapabilitiestest

from your build directory after you build everything.



Re: [RFC: vf-token 1/5] virpci: Define vf-token

2023-10-06 Thread Peter Krempa
On Thu, Oct 05, 2023 at 16:05:00 -0700, Vivek Kashyap wrote:
> Define the vf-token extension for PCI device
> 
> Signed-off-by: Vivek Kashyap 
> ---
>  src/util/virpci.h | 11 +++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/src/util/virpci.h b/src/util/virpci.h
> index faca6cf6f9..b4e9e95d88 100644
> --- a/src/util/virpci.h
> +++ b/src/util/virpci.h
> @@ -50,7 +50,15 @@ struct _virZPCIDeviceAddress {
>  /* Don't forget to update virPCIDeviceAddressCopy if needed. */
>  };
>  
> +typedef struct _virPCIDeviceToken virPCIDeviceToken;
> +
> +struct _virPCIDeviceToken {
> +unsigned char uuid[VIR_UUID_BUFLEN];
> +bool isSet;
> +};
> +
>  #define VIR_PCI_DEVICE_ADDRESS_FMT "%04x:%02x:%02x.%d"
> +#define VIR_PCI_DEVICE_TOKEN_FMT 
> "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
>  
>  /* Represents format of PF's phys_port_name in switchdev mode:
>   * 'p%u' or 'p%us%u'. New line checked since value is read from sysfs file.
> @@ -65,6 +73,7 @@ struct _virPCIDeviceAddress {
>  virTristateSwitch multi;
>  int extFlags; /* enum virPCIDeviceAddressExtensionFlags */
>  virZPCIDeviceAddress zpci;
> +virPCIDeviceToken token;
>  /* Don't forget to update virPCIDeviceAddressCopy if needed. */
>  };
>  
> @@ -269,6 +278,8 @@ int virPCIDeviceAddressParse(char *address, 
> virPCIDeviceAddress *bdf);
>  
>  bool virZPCIDeviceAddressIsIncomplete(const virZPCIDeviceAddress *addr);
>  bool virZPCIDeviceAddressIsPresent(const virZPCIDeviceAddress *addr);
> +bool virPCIVFIOTokenIDIsPresent(const virPCIDeviceToken *token);
> +bool virDeviceExtensionIsPresent(const virPCIDeviceAddress *pci);

These function definitions should go into the patch that actually
implements the functions themselves.



Re: [RFC: vf-token 0/5] Introduce vf-token when using userspace PF

2023-10-06 Thread Peter Krempa
On Thu, Oct 05, 2023 at 16:04:59 -0700, Vivek Kashyap wrote:
> vf token is set by a vfio-pci based PF driver and it must be known to the
> vfio-pci based VF driver. This vf-token is set by the PF driver before VF
> drivers can access the device. vfio-pci driver and qemu support vf-token. 
> This RFC patch series adds support to provide the vf-token (uuid format) 
> in the domain XML and to generate the qemu commandline including the 
> vf-token.
> 
> To support vf-token the new element will be used as follows:
> 
> 
>
>
>  
>  
>  
>
>   
> 
> 
> The generated commandline will include the following:
> 
> -device {"driver":"vfio-pci","host":":00:0.1",
>  "vf-token":"00112233-4455-6677-8899-aabbccddeeff",
>  "id":"hostdev0","bus":"pci.0","addr":"0x1"}
> 
> This patch is get feedback on the approach. Will post with add
> documentation and testcases in follow-up.
> 
> Vivek Kashyap (5):
>   virpci: Define vf-token
>   qemu: vf-token capability
>   conf: vf-token flag
>   conf: vf-token parsing and formatting
>   qemu: validate and generate vf-token on command line

Please note that my forthcoming review will not include any comments on
whether this feature itself makes sense or whether the XML desing you
are proposing is reasonable ...

>  src/conf/device_conf.c| 31 +--
>  src/conf/device_conf.h|  3 +++
>  src/conf/domain_addr.h|  1 +
>  src/conf/domain_conf.c|  5 +
>  src/conf/schemas/basictypes.rng   | 11 +++
>  src/conf/schemas/domaincommon.rng |  1 +
>  src/libvirt_private.syms  |  1 +
>  src/qemu/qemu_capabilities.c  |  3 +++
>  src/qemu/qemu_capabilities.h  |  1 +
>  src/qemu/qemu_command.c   | 27 ---
>  src/qemu/qemu_domain_address.c|  3 +++
>  src/qemu/qemu_validate.c  | 19 +++
>  src/util/virpci.c |  5 +
>  src/util/virpci.h | 11 +++
>  14 files changed, 117 insertions(+), 5 deletions(-)

This is mostly because the patches do not contain any changes to
documentation that would explain it and I'm not familiar with what the
feature is supposed to do. Thus my comments will be purely for the code
itself and a further review will be required.



Re: [libvirt PATCH v3 00/10] external snapshot revert fixes

2023-09-26 Thread Peter Krempa
On Mon, Sep 18, 2023 at 15:29:17 +0200, Pavel Hrdina wrote:
> This fixes reverting external snapshots to not error out in cases where
> it should work and makes it correctly load the memory state when
> reverting to snapshot of running VM.
> 
> This discards v2 completely and makes changes to v1:
> 
> - moves qemuSaveImageStartProcess to qemu_process as
>   qemuProcessStartWithMemoryState
> 
> - change it to use cookie from memory state file instead of
>   using cookie from snapshot xml
> 
> - comments improvements
> 
> - introduces new helpers to start and stop decompression process
> 
> - reintroduces  capability
> 
> Pavel Hrdina (10):
>   qemu_saveimage: extract starting process to qemuSaveImageStartProcess
>   qemu_saveimage: introduce helpers to decompress memory state file
>   qemu_saveimage: move qemuSaveImageStartProcess to qemu_process
>   qemuProcessStartWithMemoryState: allow setting reason for audit log
>   qemuProcessStartWithMemoryState: add snapshot argument
>   qemuProcessStartWithMemoryState: make it possible to use without data
>   qemu_snapshot: fix reverting external snapshot when not all disks are
> included
>   qemu_snapshot: correctly load the saved memory state file
>   capabilities: report full external snapshot support
>   NEWS: document support for reverting external snapshots

Reviewed-by: Peter Krempa 



Re: [libvirt PATCH v3 06/10] qemuProcessStartWithMemoryState: make it possible to use without data

2023-09-26 Thread Peter Krempa
On Mon, Sep 18, 2023 at 15:29:23 +0200, Pavel Hrdina wrote:
> When used with internal snapshots there is no memory state file so we
> have no data to load and decompression is not needed.
> 
> Signed-off-by: Pavel Hrdina 
> ---
>  src/qemu/qemu_process.c | 23 +--
>  1 file changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index c8430bf7b7..f96918073f 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -8165,7 +8165,7 @@ qemuProcessStart(virConnectPtr conn,
>   * @fd: FD pointer of memory state file
>   * @path: path to memory state file
>   * @snapshot: internal snapshot to load when starting QEMU process or NULL
> - * @data: data from memory state file
> + * @data: data from memory state file or NULL
>   * @asyncJob: type of asynchronous job
>   * @start_flags: flags to start QEMU process with
>   * @reason: audit log reason
> @@ -8175,7 +8175,8 @@ qemuProcessStart(virConnectPtr conn,
>   * is correctly decompressed so it can be loaded by QEMU process.
>   *
>   * When reverting to internal snapshot callers needs to pass @snapshot as 
> well
> - * correctly start QEMU process.
> + * correctly start QEMU process. In addition there is no memory state file so
> + * it's safe to pass NULL as @data.

This does not fully address my comment from previous patch. It says that
@data 'can' be NULL, not that it MUST be inull if @snapshot is non-null.



Re: [libvirt PATCH v3 05/10] qemuProcessStartWithMemoryState: add snapshot argument

2023-09-26 Thread Peter Krempa
On Mon, Sep 18, 2023 at 15:29:22 +0200, Pavel Hrdina wrote:
> When called from snapshot code we will need to pass snapshot object in
> order to make internal snapshots work correctly.
> 
> Signed-off-by: Pavel Hrdina 
> ---
>  src/qemu/qemu_process.c   | 9 -
>  src/qemu/qemu_process.h   | 1 +
>  src/qemu/qemu_saveimage.c | 2 +-
>  3 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index d414a40fd5..c8430bf7b7 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -8164,6 +8164,7 @@ qemuProcessStart(virConnectPtr conn,
>   * @vm: domain object
>   * @fd: FD pointer of memory state file
>   * @path: path to memory state file
> + * @snapshot: internal snapshot to load when starting QEMU process or NULL
>   * @data: data from memory state file
>   * @asyncJob: type of asynchronous job
>   * @start_flags: flags to start QEMU process with
> @@ -8173,6 +8174,11 @@ qemuProcessStart(virConnectPtr conn,
>   * Start VM with existing memory state. Make sure that the stored memory 
> state
>   * is correctly decompressed so it can be loaded by QEMU process.
>   *
> + * When reverting to internal snapshot callers needs to pass @snapshot as 
> well
> + * correctly start QEMU process.

It doesn't mention that callers must not pass the other state-related
parameters as both methods can't be used at once.

> + *
> + * When restoring VM from saved image @snapshot needs to be NULL.

This is only an implication (one way) that says that with a saveimage
@snapshot must be null, but not that it's also the other way around.



Re: [PATCH 08/31] configure: ensure dependency for cross-compile setup

2023-09-25 Thread Peter Maydell
On Mon, 25 Sept 2023 at 17:45, Alex Bennée  wrote:
>
>
> Paolo Bonzini  writes:
>
> > On 9/25/23 16:48, Alex Bennée wrote:
> >> If we update configure we should make sure we regenerate all the
> >> compiler details. We should also ensure those details are upto date
> >> before building the TCG tests.
> >> Signed-off-by: Alex Bennée 
> >> ---
> >>   configure | 2 ++
> >>   1 file changed, 2 insertions(+)
> >> diff --git a/configure b/configure
> >> index e83872571d..a95e0f5767 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -1788,6 +1788,8 @@ for target in $target_list; do
> >> echo "HOST_GDB_SUPPORTS_ARCH=y" >> "$config_target_mak"
> >> fi
> >>   +  echo "$config_target_mak: configure" >> Makefile.prereqs
> >
> > This in practice is not adding anything; if "configure" changes then
> > Makefile's dependency on config-host.mak will trigger a configure
> > rerun anyway.
> >
> > If you want to add it, you should also add it for other config-*.mak
> > files.  However, I'd remove this line and just change
> >
> > -# 1. ensure config-host.mak is up-to-date
> > +# 1. ensure config-host.mak is up-to-date.  All other config-*.mak
> > +# files for subdirectories will be updated as well.
>
> Peter ran into a mismatch between config-host.mak and
> tests/tcg/foo/config-target.mak in his build system so it didn't get
> picked up at one point.

I did, but looking at the timestamps on the two files, the
problem wasn't that one file got updated and not the other:

$ grep CONFIG_PLUGIN build/x86/config-host.h
#undef CONFIG_PLUGIN
$ grep CONFIG_PLUGIN build/x86/tests/tcg/config-host.mak
CONFIG_PLUGIN=y
e104462:jammy:qemu$ ls -l build/x86/config-host.mak
build/x86/tests/tcg/config-host.mak
-rw-r--r-- 1 petmay01 petmay01 549 Sep 22 16:38 build/x86/config-host.mak
-rw-r--r-- 1 petmay01 petmay01 159 Sep 22 16:38
build/x86/tests/tcg/config-host.mak

(both newer than 'configure' itself by about 10 days.)

-- PMM



Re: [libvirt PATCH v8 10/37] qemu: add functions to start and stop nbdkit

2023-09-21 Thread Peter Krempa
On Thu, Sep 21, 2023 at 12:50:52 -0500, Jonathon Jongsma wrote:
> On 9/20/23 7:24 AM, Pavel Hrdina wrote:
> > On Thu, Aug 31, 2023 at 04:39:50PM -0500, Jonathon Jongsma wrote:
> > > Add some helper functions to build a virCommand object and run the
> > > nbdkit process for a given virStorageSource.
> > > 
> > > Signed-off-by: Jonathon Jongsma 
> > > Reviewed-by: Peter Krempa 
> > > ---
> > >   src/qemu/qemu_nbdkit.c | 250 +
> > >   src/qemu/qemu_nbdkit.h |  10 ++
> > >   2 files changed, 260 insertions(+)

[...]

> > > +VIR_DEBUG("Stopping nbdkit process %i", proc->pid);
> > > +virProcessKill(proc->pid, SIGTERM);
> > 
> > Coverity complains here that the return value of virProcessKill() is not
> > checked which leads me to a question if we should use
> > virProcessKillPainfully() instead.
> > 
> > With the code that is pushed the function qemuNbdkitProcessStop() is
> > called only within the qemu_nbdkit.c for these cases:
> > 
> >  - in qemuNbdkitProcessRestart() before starting the process again
> >where we do not check if the original process was killed correctly
> >or not,
> > 
> >  - in qemuNbdkitStopStorageSource() where we check return value of
> >qemuNbdkitProcessStop() but it will always be 0,
> > 
> >  - in qemuNbdkitProcessStart() as error path where we don't check any
> >return value.
> > 
> > To me it seems that the return value qemuNbdkitProcessStop can be changed
> > to void as we always return 0 and use virProcessKillPainfully() or
> > properly pass return value of virProcessKill() and check it for every
> > use of qemuNbdkitProcessStop().
> > 
> > Pavel
> 
> Good question. In one of my earlier series I had actually used
> virProcessKillPainfully(), but changed it based on a suggestion from Peter
> that it would be bad to kill it painfully if nbdkit was ever used in
> read-write mode. But apparently I forgot to handle a shutdown failure. An
> alternative would be to simply refuse to use nbdkit if the user requests
> read-write mode.

We can use the same algorithm as with the qemu process where we first
issue SIGTERM, thus if the process is responsive it can execute the
shutdown actions. Otherwise it'll get SIGKILL right after.



Re: [libvirt PATCH] qemu_nbdkit: fix possible null dereference

2023-09-20 Thread Peter Krempa
On Wed, Sep 20, 2023 at 14:01:29 +0200, Pavel Hrdina wrote:
> Function virGetConnectSecret() can return NULL so we need to check it
> since in virSecretGetSecretString() it gets dereferenced.
> 
> Reported-by: coverity
> Signed-off-by: Pavel Hrdina 
> ---
>  src/qemu/qemu_nbdkit.c | 3 +++
>  1 file changed, 3 insertions(+)

Reviewed-by: Peter Krempa 



  1   2   3   4   5   6   7   8   9   10   >