Merge ~rafaeldtinoco/ubuntu/+source/libvirt:focal-clustersize into ubuntu/+source/libvirt:ubuntu/focal-devel

Proposed by Rafael David Tinoco
Status: Needs review
Proposed branch: ~rafaeldtinoco/ubuntu/+source/libvirt:focal-clustersize
Merge into: ubuntu/+source/libvirt:ubuntu/focal-devel
Diff against target: 986 lines (+934/-0)
8 files modified
debian/changelog (+12/-0)
debian/patches/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch (+53/-0)
debian/patches/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch (+47/-0)
debian/patches/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch (+40/-0)
debian/patches/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch (+352/-0)
debian/patches/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch (+191/-0)
debian/patches/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch (+228/-0)
debian/patches/series (+11/-0)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Lucas Kanashiro (community) Approve
Rafael David Tinoco (community) Approve
Review via email: mp+403263@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Alright, this is a set of patches to be applied on top of libvirt 6.0.0-0ubuntu8.9 (focal). It can also be applied to other branches based on focal's version.

@lucas,

(1)

The xml stanza clusterSize is being added to libvirt so the qcow2 image file can be created with that parameter. A quick way to achieve the same without libvirt is:

# qemu-img create -f qcow2 -o cluster_size=2M /var/lib/libvirt/images/guest-disk01.qcow2 5G

and verify it has "cluster_size: 2097152" with

# qemu-img info /var/lib/libvirt/images/guest-disk01.qcow2

(2)

Libvirt NEEDS the qcow2 volume to be created, and managed, through it in order to test this feature. This means that you can create a managed volume by having the following XML:

$ cat ./guest-disk01.xml

<volume type='file'>
  <name>guest-disk01.qcow2</name>
  <key>/var/lib/libvirt/images/guest-disk01.qcow2</key>
  <source>
  </source>
  <capacity unit='bytes'>5368709120</capacity>
  <allocation unit='bytes'>6295552</allocation>
  <physical unit='bytes'>6291464</physical>
  <target>
    <path>/var/lib/libvirt/images/guest-disk01.qcow2</path>
    <format type='qcow2'/>
    <permissions>
      <mode>0644</mode>
      <owner>0</owner>
      <group>0</group>
    </permissions>
    <timestamps>
      <atime>1621917565.209401319</atime>
      <mtime>1621917565.261402011</mtime>
      <ctime>1621917565.261402011</ctime>
    </timestamps>
    <compat>1.1</compat>
    <clusterSize unit='B'>2097152</clusterSize>
    <features/>
  </target>
</volume>

for example, and define the volume with it:

$ virsh vol-create --pool default --file ./guest-disk01.xml
Vol guest-disk01.qcow2 created from ./guest-disk01.xml

and, in order to make sure the feature worked, verify by hand if the cluster_size was set in the managed qcow2 file:

$ sudo qemu-img info /var/lib/libvirt/images/guest-disk01.qcow2
image: /var/lib/libvirt/images/guest-disk01.qcow2
file format: qcow2
virtual size: 5 GiB (5368709120 bytes)
disk size: 6 MiB
cluster_size: 2097152
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Regarding the patchset:

* Add support for QCOW2 cluster_size option:
  + d/p/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch
  + d/p/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch
  + d/p/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch
  + d/p/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch
  + d/p/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch
  + d/p/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch

You will follow clean cherry-picks but 2 of them, which I classified as 'backports'. Explanation on why they are backports was added to their git logs. The *only* (perhaps) discussion that could be raised from this set *would* be whether we should have:

  + d/p/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch

cherry-picked together. It mainly relocates a function from one place to another. I thought it was easier to have it in the set so we don't have to declare the function prototype in the header for the subsequent patch to work (adding a delta that does not exist upstream).

Let me know if you have any doubs, and feel free to merge this patchset to any other repository you feel like ;).

-rafaeldtinoco

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

BTW, forgot to mention, ignore the last commit as it has a delta I added so I could better emulate other environment. Let me know if you want me to have it removed or you are good in doing it by yourself during review time. Thanks.

Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :
Download full text (3.6 KiB)

Thanks for the MP and the detailed steps on how to test this feature.

I tried to build the package from your branch locally in Focal to performed the test you described, but it FTBFS for me. Is it working for you? The following test is failing during the build:

FAIL: storagevolxml2xmltest
===========================

TEST: storagevolxml2xmltest
 1) Storage Vol XML-2-XML vol-file ... OK
 2) Storage Vol XML-2-XML vol-file-naming ... OK
 3) Storage Vol XML-2-XML vol-file-backing ... OK
 4) Storage Vol XML-2-XML vol-file-iso ... OK
 5) Storage Vol XML-2-XML vol-qcow2 ... OK
 6) Storage Vol XML-2-XML vol-qcow2-1.1 ... OK
 7) Storage Vol XML-2-XML vol-qcow2-lazy ... OK
 8) Storage Vol XML-2-XML vol-qcow2-0.10-lazy ... OK
 9) Storage Vol XML-2-XML vol-qcow2-nobacking ... OK
10) Storage Vol XML-2-XML vol-qcow2-encryption ... OK
11) Storage Vol XML-2-XML vol-qcow2-clusterSize ...
In '/<<PKGBUILDDIR>>/debian/build/../../tests/storagevolxml2xmlout/vol-qcow2-clusterSize.xml':
Offset 104
Expect [c]
Actual [source>
  </source>
  <c]
                                                                      ... FAILED
12) Storage Vol XML-2-XML vol-luks ... OK
13) Storage Vol XML-2-XML vol-luks-cipher ... OK
14) Storage Vol XML-2-XML vol-partition ... OK
15) Storage Vol XML-2-XML vol-logical ... OK
16) Storage Vol XML-2-XML vol-logical-backing ... OK
17) Storage Vol XML-2-XML vol-sheepdog ... OK
18) Storage Vol XML-2-XML vol-gluster-dir ... OK
19) Storage Vol XML-2-XML vol-gluster-dir-neg-uid ... OK
20) Storage Vol XML-2-XML vol-qcow2-nocapacity ... OK
FAIL storagevolxml2xmltest (exit status: 1)

Apart from that, I have some questions for you:

1) In the diff there are some changes introduced in d/control and d/rules not mentioned in the changelog, those changes were added in the "IBM layer - Ignore" commit (bc66b07c). Don't we want to advertise those things in the changelog? This is minor, I can add the existent IBM delta to the changelog when putting it in the virt-stack-ibmcloud git repository.

2) You prepared this package based on Focal but in the IBM proposed PPA we have packages targeting Bionic only. Did you try to build this version in Bionic?

3) The version we have in the proposed PPA is 6.0.0-0ubuntu8.8~ibmcloud0.6. Are you sure IBM wants to move to 6.0.0-0ubuntu8.9? This is the changelog entry for -0ubuntu8.9:

libvirt (6.0.0-0ubuntu8.9) focal; urgency=medium

  * d/p/u/lp-1921754*: add EPYC-Rome-v2 as v1 missed IBRS and thereby fails
    on some HW/Guest combinations e.g. Windows 10 on Threadripper
    (LP: #1921754)
  * d/p/u/lp-1921880*: add EPYC-Milan features and named cpu type support
    (LP...

Read more...

review: Needs Fixing
Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

1) In the diff there are some changes introduced in d/control and d/rules not mentioned in the changelog, those changes were added in the "IBM layer - Ignore" commit (bc66b07c). Don't we want to advertise those things in the changelog? This is minor, I can add the existent IBM delta to the changelog when putting it in the virt-stack-ibmcloud git repository.

> This is an external layer (already included in another internal repo for other builds). I added as a last commit so the build would be the same as the one we get from internal repos.

2) You prepared this package based on Focal but in the IBM proposed PPA we have packages targeting Bionic only. Did you try to build this version in Bionic?

> That is why we have the "IBM layer - Ignore" commit. It makes the focal-dev branch compatible to Bionic (as a backport). So this repo will build in Bionic and, if you remove the first commit, it will build in Focal as well.

3) The version we have in the proposed PPA is 6.0.0-0ubuntu8.8~ibmcloud0.6. Are you sure IBM wants to move to 6.0.0-0ubuntu8.9? This is the changelog entry for -0ubuntu8.9:

libvirt (6.0.0-0ubuntu8.9) focal; urgency=medium

> Version present in the 'build' PPA is 6.0.0-0ubuntu8.9~ibmcloud0.1. The correct version for a package to be put there is the next version: 6.0.0-0ubuntu8.9~ibmcloud0.2. I have not followed correct versioning for that PPA, I was searching for patch review, not package logical one, for now.

4) Considering we want to import 6.0.0-0ubuntu8.9 and apply those patches on top of it, do we really want to use your version string 6.0.0-0ubuntu8.9+20210524~clustersize01? Or follow the pattern and use 6.0.0-0ubuntu8.9~ibmcloud0.1?

> NO =), I used it locally only.

The patch set looks sane to me.

> Thanks! I'll check the tests failure and reply here.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

make[3]: Entering directory '/home/rafaeldtinoco/work/sources/ubuntu/libvirt/build/tests'
PASS: virshtest
PASS: sockettest
PASS: virhostcputest
PASS: virbuftest
PASS: commandtest
PASS: seclabeltest
PASS: virhashtest
PASS: virconftest
PASS: viratomictest
PASS: utiltest
PASS: shunloadtest
PASS: virtimetest
PASS: viruritest
PASS: virkeyfiletest
PASS: viralloctest
PASS: virauthconfigtest
PASS: virbitmaptest
SKIP: vircgrouptest
PASS: vircryptotest
PASS: virpcitest
PASS: virendiantest
PASS: virfiletest
PASS: virfilecachetest
PASS: virfirewalltest
PASS: viriscsitest
PASS: virkeycodetest
PASS: virlockspacetest
PASS: virlogtest
PASS: virrotatingfiletest
PASS: virschematest
PASS: virstringtest
PASS: virportallocatortest
PASS: sysinfotest
PASS: virkmodtest
PASS: vircapstest
PASS: domaincapstest
PASS: domainconftest
PASS: virhostdevtest
PASS: virnetdevtest
PASS: virtypedparamtest
PASS: vshtabletest
PASS: virerrortest
PASS: virnetmessagetest
PASS: virnetsockettest
PASS: virnetdaemontest
PASS: virnetserverclienttest
PASS: virnettlscontexttest
PASS: virnettlssessiontest
PASS: fchosttest
PASS: scsihosttest
PASS: vircaps2xmltest
PASS: virresctrltest
PASS: fdstreamtest
PASS: virdbustest
PASS: virsystemdtest
PASS: virpolkittest
PASS: qemuxml2argvtest
PASS: qemuxml2xmltest
PASS: qemudomaincheckpointxml2xmltest
PASS: qemudomainsnapshotxml2xmltest
PASS: qemumonitorjsontest
PASS: qemuhotplugtest
PASS: qemuagenttest
PASS: qemucapabilitiestest
PASS: qemucaps2xmltest
PASS: qemumemlocktest
PASS: qemucommandutiltest
PASS: qemublocktest
PASS: qemumigparamstest
PASS: qemusecuritytest
PASS: qemufirmwaretest
PASS: qemuvhostusertest
PASS: openvzutilstest
PASS: esxutilstest
PASS: vmx2xmltest
PASS: xml2vmxtest
PASS: vmwarevertest
PASS: virjsontest
PASS: networkxml2xmlupdatetest
PASS: virnetworkportxml2xmltest
PASS: nwfilterxml2xmltest
PASS: virnwfilterbindingxml2xmltest
PASS: nwfilterebiptablestest
PASS: nwfilterxml2firewalltest
PASS: storagevolxml2argvtest
PASS: storagepoolxml2argvtest
PASS: virstorageutiltest
PASS: storagepoolxml2xmltest
PASS: storagepoolcapstest
PASS: virstoragetest
PASS: virscsitest
FAIL: storagevolxml2xmltest
PASS: nodedevxml2xmltest
PASS: interfacexml2xmltest
PASS: cputest
PASS: metadatatest
PASS: secretxml2xmltest
PASS: genericxml2xmltest
PASS: virusbtest
PASS: virnetdevbandwidthtest
PASS: eventtest
PASS: virdrivermoduletest
PASS: virdriverconnvalidatetest
PASS: objecteventtest
PASS: virmacmaptest
PASS: virnetdevopenvswitchtest
PASS: libvirtd-fail
PASS: libvirtd-pool
PASS: virsh-cpuset
PASS: virsh-define-dev-segfault
PASS: virsh-int-overflow
SKIP: virsh-optparse
PASS: virsh-read-bufsiz
PASS: virsh-read-non-seekable
PASS: virsh-schedinfo
PASS: virsh-self-test
PASS: virt-admin-self-test
PASS: virsh-checkpoint
PASS: virsh-snapshot
PASS: virsh-start
PASS: virsh-undefine
PASS: virsh-uriprecedence
PASS: virsh-vcpupin
============================================================================
Testsuite summary for libvirt 6.0.0
============================================================================
# TOTAL: 123
# PASS: 120
# SKIP: 2
# XFAIL: 0
# FAIL: 1
# XPASS: 0
# ERROR: 0

FAILED TEST:

FAIL: storagevolxml2xmltest, working on it.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :
Download full text (3.2 KiB)

Alright @lucas,

Now tests are good:

PASS: virshtest
PASS: sockettest
PASS: virhostcputest
PASS: virbuftest
PASS: commandtest
PASS: seclabeltest
PASS: virhashtest
PASS: virconftest
PASS: viratomictest
PASS: utiltest
PASS: shunloadtest
PASS: virtimetest
PASS: viruritest
PASS: virkeyfiletest
PASS: viralloctest
PASS: virauthconfigtest
PASS: virbitmaptest
PASS: vircgrouptest
PASS: vircryptotest
PASS: virpcitest
PASS: virendiantest
PASS: virfiletest
PASS: virfilecachetest
PASS: virfirewalltest
PASS: viriscsitest
PASS: virkeycodetest
PASS: virlockspacetest
PASS: virlogtest
PASS: virrotatingfiletest
PASS: virschematest
PASS: virstringtest
PASS: virportallocatortest
PASS: sysinfotest
PASS: virkmodtest
PASS: vircapstest
PASS: domaincapstest
PASS: domainconftest
PASS: virhostdevtest
PASS: virnetdevtest
PASS: virtypedparamtest
PASS: vshtabletest
PASS: virerrortest
PASS: virnetmessagetest
PASS: virnetsockettest
PASS: virnetdaemontest
PASS: virnetserverclienttest
PASS: virnettlscontexttest
PASS: virnettlssessiontest
PASS: fchosttest
PASS: scsihosttest
PASS: vircaps2xmltest
PASS: virresctrltest
PASS: fdstreamtest
PASS: virdbustest
PASS: virsystemdtest
PASS: virpolkittest
PASS: qemuxml2argvtest
PASS: qemuxml2xmltest
PASS: qemudomaincheckpointxml2xmltest
PASS: qemudomainsnapshotxml2xmltest
PASS: qemumonitorjsontest
PASS: qemuhotplugtest
PASS: qemuagenttest
PASS: qemucapabilitiestest
PASS: qemucaps2xmltest
PASS: qemumemlocktest
PASS: qemucommandutiltest
PASS: qemublocktest
PASS: qemumigparamstest
PASS: qemusecuritytest
PASS: qemufirmwaretest
PASS: qemuvhostusertest
PASS: openvzutilstest
PASS: esxutilstest
PASS: vmx2xmltest
PASS: xml2vmxtest
PASS: vmwarevertest
PASS: virjsontest
PASS: networkxml2xmlupdatetest
PASS: virnetworkportxml2xmltest
PASS: nwfilterxml2xmltest
PASS: virnwfilterbindingxml2xmltest
PASS: nwfilterebiptablestest
PASS: nwfilterxml2firewalltest
PASS: storagevolxml2argvtest
PASS: storagepoolxml2argvtest
PASS: virstorageutiltest
PASS: storagepoolxml2xmltest
PASS: storagepoolcapstest
PASS: virstoragetest
PASS: virscsitest
PASS: storagevolxml2xmltest
PASS: nodedevxml2xmltest
PASS: interfacexml2xmltest
PASS: cputest
PASS: metadatatest
PASS: secretxml2xmltest
PASS: genericxml2xmltest
PASS: virusbtest
PASS: virnetdevbandwidthtest
PASS: eventtest
PASS: virdrivermoduletest
PASS: virdriverconnvalidatetest
PASS: objecteventtest
PASS: virmacmaptest
PASS: virnetdevopenvswitchtest
PASS: libvirtd-fail
PASS: libvirtd-pool
PASS: virsh-cpuset
PASS: virsh-define-dev-segfault
PASS: virsh-int-overflow
SKIP: virsh-optparse
PASS: virsh-read-bufsiz
PASS: virsh-read-non-seekable
PASS: virsh-schedinfo
PASS: virsh-self-test
PASS: virt-admin-self-test
PASS: virsh-checkpoint
PASS: virsh-snapshot
PASS: virsh-start
PASS: virsh-undefine
PASS: virsh-uriprecedence
PASS: virsh-vcpupin
============================================================================
Testsuite summary for libvirt 6.0.0
============================================================================
# TOTAL: 123
# PASS: 122
# SKIP: 1
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0

Problem was an extra stanza added by default in the XML output of the created test. That happens because of the libvirt version ...

Read more...

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Good to go. Feel free to merge to 'other repos' if you feel like it.

Thanks a lot

review: Approve
Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Rafael, I am still unable to build the package in Focal. The same test is still failing for me, however, the error is different now:

FAIL: storagevolxml2xmltest
===========================

TEST: storagevolxml2xmltest
 1) Storage Vol XML-2-XML vol-file ... OK
 2) Storage Vol XML-2-XML vol-file-naming ... OK
 3) Storage Vol XML-2-XML vol-file-backing ... OK
 4) Storage Vol XML-2-XML vol-file-iso ... OK
 5) Storage Vol XML-2-XML vol-qcow2 ... OK
 6) Storage Vol XML-2-XML vol-qcow2-1.1 ... OK
 7) Storage Vol XML-2-XML vol-qcow2-lazy ... OK
 8) Storage Vol XML-2-XML vol-qcow2-0.10-lazy ... OK
 9) Storage Vol XML-2-XML vol-qcow2-nobacking ... OK
10) Storage Vol XML-2-XML vol-qcow2-encryption ... OK
11) Storage Vol XML-2-XML vol-qcow2-clusterSize ...
In '/<<PKGBUILDDIR>>/debian/build/../../tests/storagevolxml2xmlout/vol-qcow2-clusterSize.xml':
Offset 524
Expect []
Actual [ </target>
</volume>
]
                                                                      ... FAILED
12) Storage Vol XML-2-XML vol-luks ... OK
13) Storage Vol XML-2-XML vol-luks-cipher ... OK
14) Storage Vol XML-2-XML vol-partition ... OK
15) Storage Vol XML-2-XML vol-logical ... OK
16) Storage Vol XML-2-XML vol-logical-backing ... OK
17) Storage Vol XML-2-XML vol-sheepdog ... OK
18) Storage Vol XML-2-XML vol-gluster-dir ... OK
19) Storage Vol XML-2-XML vol-gluster-dir-neg-uid ... OK
20) Storage Vol XML-2-XML vol-qcow2-nocapacity ... OK
FAIL storagevolxml2xmltest (exit status: 1)

Did you forget to git push any local change? I am wondering why this test is passing for you but failing for me.

review: Needs Fixing
Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

The real problem is that a virsh vol-dumpxml is including a:

<source>
</source>

at the final XML, which causes no harm but the test compares with given output (brought by my set) and says its wrong. The backport is good and works.

This behaviour is fixed by:

commit 6423e30828
Author: Peter Krempa <email address hidden>
Date: Thu Feb 25 10:11:05 2021

    virStorageVolDefFormat: Don't format empty <source>

    If there are no source extents the volume XML has an empty <source>
    element. Remove it if there's nothing in it by using
    virXMLFormatElement.

    Signed-off-by: Peter Krempa <email address hidden>
    Reviewed-by: Michal Privoznik <email address hidden>

but if bringing this patch before my patchset ... other tests break and I dont want to go deep into why previous tests are being broken by this.

Previous attempt I tried to include <source></source> in the XML and it worked for my local builds, when test would compare the output of the vol-dumpxml sub-command it would find a local file exactly the same as expected.

I'm afraid I did not test with all other patches included, that is why its failing in dpkg-buildpackage. Being in hurry is enemy of perfection, as usually said.

I'm fixing this now and will make sure it works for the dpkg-buildpackage of both focal and bionic.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

The focal PPA:

https://launchpad.net/~rafaeldtinoco/+archive/ubuntu/libvirtclustersize

with the contents of this MR.

The test with that PPA's packages:

$ virsh pool-create-as --name default --type dir --source-path /var/lib/libvirt/images --target /var/lib/libvirt/images
Pool default created

$ virsh vol-create --pool default --file ./guest01-disk01.xml
Vol guest-disk01.qcow2 created from ./guest01-disk01.xml

$ sudo qemu-img info /var/lib/libvirt/images/guest-disk01.qcow2
image: /var/lib/libvirt/images/guest-disk01.qcow2
file format: qcow2
virtual size: 5 GiB (5368709120 bytes)
disk size: 6.13 MiB
cluster_size: 2097152
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

$ virsh vol-dumpxml --pool default --vol guest-disk01.qcow2
<volume type='file'>
  <name>guest-disk01.qcow2</name>
  <key>/var/lib/libvirt/images/guest-disk01.qcow2</key>
  <source>
  </source>
  <capacity unit='bytes'>5368709120</capacity>
  <allocation unit='bytes'>6425088</allocation>
  <physical unit='bytes'>6291464</physical>
  <target>
    <path>/var/lib/libvirt/images/guest-disk01.qcow2</path>
    <format type='qcow2'/>
    <permissions>
      <mode>0644</mode>
      <owner>0</owner>
      <group>0</group>
    </permissions>
    <timestamps>
      <atime>1622086325.115175639</atime>
      <mtime>1622086325.147176059</mtime>
      <ctime>1622086325.147176059</ctime>
    </timestamps>
    <compat>1.1</compat>
    <clusterSize unit='B'>2097152</clusterSize>
    <features/>
  </target>
</volume>

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

If you check that PPA's build log:

...
PASS: storagepoolcapstest
PASS: storagepoolxml2xmltest
PASS: virscsitest
PASS: nsstest
PASS: nssguesttest
PASS: storagevolxml2xmltest
PASS: nodedevxml2xmltest
PASS: interfacexml2xmltest
PASS: metadatatest
PASS: secretxml2xmltest
PASS: virstoragetest
PASS: virusbtest
PASS: genericxml2xmltest
...

So the test storagevolxml2xmltest has passed.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Indeed there is something strange with the focal's libvirt tests, like the one commit fixing empty XML blocks. I don't think we should worry with this as the build works, the expected results, out of my patchset, are good and all seems fine. We can leave that to @paelzer when he is back IF he wants to pursue that, IMO.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Just pushed my latest branch, the one I used to build the PPA.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Okay, now, for the Bionic backport you can grab these 2 patches:

https://paste.ubuntu.com/p/JgBmvMB4tq/

and

https://paste.ubuntu.com/p/H6tBGfcz4T/

on top of the source package directly from the private PPA (with all delta it has).

You will have d/p/ibm/:

$ cat 0001-Add-support-for-QCOW2-clusterSize-option.patch | diffstat -l
ibm/clusz-conf-Move-and-rename-virDomainParseScaledValue.patch
ibm/clusz-storage-add-support-for-QCOW2-cluster_size-option.patch
ibm/clusz-storage_file-add-support-to-probe-cluster_size-from.patch
series

which are the 3 needed patches (as the other 3 patches are already included).

With this, you will be able to build the same binary private PPA has with these extra feature.

Ah, the tests for the Bionic backport (with all other patches) have worked and should work in the **build PPA** as well.

Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Thanks for the analysis and the fix Rafael. Just to make sure everything is all right I built it locally successfully this time, and also followed the steps you described above to test the feature. All looks good!

I'll start to move those patches to the virt-stack-ibmcloud git repository and soon after upload it to the IBM build PPA.

review: Approve
Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Thanks Lucas!

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Thank you!
LGTM as well

I had to smile about "Being in hurry is enemy of perfection, as usually said.". I sometimes refer to "Perfection is the enemy of progress". Now I wondered if we can derive from that "Being in a Hurry == Progress". Unless this isn't a bijective relation ... anyway :-)

review: Approve

Unmerged commits

e59a822... by Rafael David Tinoco

changelog

c83fec2... by Rafael David Tinoco

* Add support for QCOW2 cluster_size option:
  + d/p/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch
  + d/p/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch
  + d/p/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch
  + d/p/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch
  + d/p/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch
  + d/p/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index fa7efba..c883c1e 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,15 @@
6+libvirt (6.0.0-0ubuntu8.9+hf20210524~01) focal; urgency=medium
7+
8+ * Add support for QCOW2 cluster_size option:
9+ + d/p/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch
10+ + d/p/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch
11+ + d/p/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch
12+ + d/p/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch
13+ + d/p/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch
14+ + d/p/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch
15+
16+ -- Rafael David Tinoco <rafaeldtinoco@ubuntu.com> Tue, 25 May 2021 02:52:28 +0000
17+
18 libvirt (6.0.0-0ubuntu8.9) focal; urgency=medium
19
20 * d/p/u/lp-1921754*: add EPYC-Rome-v2 as v1 missed IBRS and thereby fails
21diff --git a/debian/patches/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch b/debian/patches/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch
22new file mode 100644
23index 0000000..67df248
24--- /dev/null
25+++ b/debian/patches/clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch
26@@ -0,0 +1,53 @@
27+From fd49364d8b3e30db1891685ec8a7886ba05f2476 Mon Sep 17 00:00:00 2001
28+Description: qemu: monitor: Detect image cluster size from 'query-named-block-nodes'
29+Author: Peter Krempa <pkrempa@redhat.com>
30+Origin: upstream, https://github.com/libvirt/libvirt/commit/fd49364d8b3e30db1891685ec8a7886ba05f2476
31+Bug: https://gitlab.com/libvirt/libvirt/-/issues/154
32+Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
33+Last-Update: 2021-05-24
34+
35+qemu: monitor: Detect image cluster size from 'query-named-block-nodes'
36+
37+Configuring the cluster size of an image may have performance
38+implications. This patch allows us to detect cluster size for existing
39+images so that we will be able to propagate it to new images which are
40+based on existing images e.g. during snapshots/block-copy/etc.
41+
42+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
43+Reviewed-by: Eric Blake <eblake@redhat.com>
44+---
45+ src/qemu/qemu_monitor.h | 3 +++
46+ src/qemu/qemu_monitor_json.c | 3 +++
47+ 2 files changed, 6 insertions(+)
48+
49+diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
50+index 3f3b81cddd..d4ce0b4a05 100644
51+--- a/src/qemu/qemu_monitor.h
52++++ b/src/qemu/qemu_monitor.h
53+@@ -697,6 +697,9 @@ struct _qemuBlockNamedNodeData {
54+
55+ qemuBlockNamedNodeDataBitmapPtr *bitmaps;
56+ size_t nbitmaps;
57++
58++ /* the cluster size of the image is valid only when > 0 */
59++ unsigned long long clusterSize;
60+ };
61+
62+ virHashTablePtr
63+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
64+index e5164d218a..fcbe94a5f1 100644
65+--- a/src/qemu/qemu_monitor_json.c
66++++ b/src/qemu/qemu_monitor_json.c
67+@@ -2970,6 +2970,9 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
68+ if (virJSONValueObjectGetNumberUlong(img, "actual-size", &ent->physical) < 0)
69+ ent->physical = ent->capacity;
70+
71++ /* try looking up the cluster size */
72++ ignore_value(virJSONValueObjectGetNumberUlong(img, "cluster-size", &ent->clusterSize));
73++
74+ if ((bitmaps = virJSONValueObjectGetArray(val, "dirty-bitmaps")))
75+ qemuMonitorJSONBlockGetNamedNodeDataBitmaps(bitmaps, ent);
76+
77+--
78+2.25.1
79+
80diff --git a/debian/patches/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch b/debian/patches/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch
81new file mode 100644
82index 0000000..b964de4
83--- /dev/null
84+++ b/debian/patches/clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch
85@@ -0,0 +1,47 @@
86+From e60620e28b63378bb215bfd61b525a60b6660983 Mon Sep 17 00:00:00 2001
87+Description: qemu: block: Allow specifying cluster size when using 'blockdev-create'
88+Author: Peter Krempa <pkrempa@redhat.com>
89+Origin: upstream, https://github.com/libvirt/libvirt/commit/e60620e28b63378bb215bfd61b525a60b6660983
90+Bug: https://gitlab.com/libvirt/libvirt/-/issues/154
91+Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
92+Last-Update: 2021-05-24
93+
94+qemu: block: Allow specifying cluster size when using 'blockdev-create'
95+
96+'blockdev-create' allows us to create the image with a custom cluster
97+size if we wish to. Wire it up for 'qcow2'.
98+
99+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
100+Reviewed-by: Eric Blake <eblake@redhat.com>
101+---
102+ src/qemu/qemu_block.c | 1 +
103+ src/util/virstoragefile.h | 1 +
104+ 2 files changed, 2 insertions(+)
105+
106+diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
107+index eab21bc107..639ff37e1f 100644
108+--- a/src/qemu/qemu_block.c
109++++ b/src/qemu/qemu_block.c
110+@@ -2149,6 +2149,7 @@ qemuBlockStorageSourceCreateGetFormatPropsQcow2(virStorageSourcePtr src,
111+ "s:file", src->nodestorage,
112+ "U:size", src->capacity,
113+ "S:version", qcow2version,
114++ "P:cluster-size", src->clusterSize,
115+ NULL) < 0)
116+ return -1;
117+
118+diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
119+index 39e50a989d..7ec31652d5 100644
120+--- a/src/util/virstoragefile.h
121++++ b/src/util/virstoragefile.h
122+@@ -291,6 +291,7 @@ struct _virStorageSource {
123+ unsigned long long capacity; /* in bytes, 0 if unknown */
124+ unsigned long long allocation; /* in bytes, 0 if unknown */
125+ unsigned long long physical; /* in bytes, 0 if unknown */
126++ unsigned long long clusterSize; /* in bytes, 0 if unknown */
127+ bool has_allocation; /* Set to true when provided in XML */
128+
129+ size_t nseclabels;
130+--
131+2.25.1
132+
133diff --git a/debian/patches/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch b/debian/patches/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch
134new file mode 100644
135index 0000000..a9ad5bc
136--- /dev/null
137+++ b/debian/patches/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch
138@@ -0,0 +1,40 @@
139+From de79fad40fb6a970fab9dd566ed83ecf56877ea2 Mon Sep 17 00:00:00 2001
140+Description: qemuBlockStorageSourceCreateDetectSize: Propagate cluster size for 'qcow2'
141+Author: Peter Krempa <pkrempa@redhat.com>
142+Origin: upstream, https://github.com/libvirt/libvirt/commit/de79fad40fb6a970fab9dd566ed83ecf56877ea2
143+Bug: https://gitlab.com/libvirt/libvirt/-/issues/154
144+Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
145+Last-Update: 2021-05-24
146+
147+qemuBlockStorageSourceCreateDetectSize: Propagate cluster size for 'qcow2'
148+
149+Propagate the cluster size from the original image as the user might
150+have configured a custom cluster size for performance reasons. Propagate
151+the cluster size of a qcow2 image to the new overlay or copy.
152+
153+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
154+Reviewed-by: Eric Blake <eblake@redhat.com>
155+---
156+ src/qemu/qemu_block.c | 6 ++++++
157+ 1 file changed, 6 insertions(+)
158+
159+diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
160+index 639ff37e1f..e0af61954d 100644
161+--- a/src/qemu/qemu_block.c
162++++ b/src/qemu/qemu_block.c
163+@@ -2604,6 +2604,12 @@ qemuBlockStorageSourceCreateDetectSize(virHashTablePtr blockNamedNodeData,
164+ return -1;
165+ }
166+
167++ /* propagate cluster size if the images are compatible */
168++ if (templ->format == VIR_STORAGE_FILE_QCOW2 &&
169++ src->format == VIR_STORAGE_FILE_QCOW2 &&
170++ src->clusterSize == 0)
171++ src->clusterSize = entry->clusterSize;
172++
173+ if (src->format == VIR_STORAGE_FILE_RAW) {
174+ src->physical = entry->capacity;
175+ } else {
176+--
177+2.25.1
178+
179diff --git a/debian/patches/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch b/debian/patches/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch
180new file mode 100644
181index 0000000..fc04190
182--- /dev/null
183+++ b/debian/patches/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch
184@@ -0,0 +1,352 @@
185+From 04bd77a19f8312493151ce377da40577b1470a0b Mon Sep 17 00:00:00 2001
186+Description: conf: Move and rename virDomainParseScaledValue()
187+Author: Michal Privoznik <mprivozn@redhat.com>
188+Origin: backport, https://github.com/libvirt/libvirt/commit/04bd77a19f8312493151ce377da40577b1470a0b
189+Bug: https://gitlab.com/libvirt/libvirt/-/issues/154
190+Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
191+Last-Update: 2021-05-24
192+
193+conf: Move and rename virDomainParseScaledValue()
194+
195+There is nothing domain specific about the function, thus it
196+should not have virDomain prefix. Also, the fact that it is a
197+static function makes it impossible to use from other files.
198+Move the function to virxml.c and drop the 'Domain' infix.
199+
200+[Backport]
201+ This commit renames, relocates and declares a function without
202+ changing its logic: makes cherry-picking the feature "QCOW2
203+ cluster_size option" fast forward without changing its logic.
204+
205+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
206+Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
207+Signed-off-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
208+---
209+ src/conf/domain_conf.c | 135 ++++++++++-----------------------------
210+ src/libvirt_private.syms | 1 +
211+ src/util/virxml.c | 72 +++++++++++++++++++++
212+ src/util/virxml.h | 8 +++
213+ 4 files changed, 114 insertions(+), 102 deletions(-)
214+
215+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
216+index ee57152da7..aac6c6df07 100644
217+--- a/src/conf/domain_conf.c
218++++ b/src/conf/domain_conf.c
219+@@ -10459,75 +10459,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
220+ goto cleanup;
221+ }
222+
223+-/**
224+- * virDomainParseScaledValue:
225+- * @xpath: XPath to memory amount
226+- * @units_xpath: XPath to units attribute
227+- * @ctxt: XPath context
228+- * @val: scaled value is stored here
229+- * @scale: default scale for @val
230+- * @max: maximal @val allowed
231+- * @required: is the value required?
232+- *
233+- * Parse a value located at @xpath within @ctxt, and store the
234+- * result into @val. The value is scaled by units located at
235+- * @units_xpath (or the 'unit' attribute under @xpath if
236+- * @units_xpath is NULL). If units are not present, the default
237+- * @scale is used. If @required is set, then the value must
238+- * exist; otherwise, the value is optional. The resulting value
239+- * is in bytes.
240+- *
241+- * Returns 1 on success,
242+- * 0 if the value was not present and !@required,
243+- * -1 on failure after issuing error.
244+- */
245+-static int
246+-virDomainParseScaledValue(const char *xpath,
247+- const char *units_xpath,
248+- xmlXPathContextPtr ctxt,
249+- unsigned long long *val,
250+- unsigned long long scale,
251+- unsigned long long max,
252+- bool required)
253+-{
254+- unsigned long long bytes;
255+- g_autofree char *xpath_full = NULL;
256+- g_autofree char *unit = NULL;
257+- g_autofree char *bytes_str = NULL;
258+-
259+- *val = 0;
260+- xpath_full = g_strdup_printf("string(%s)", xpath);
261+-
262+- bytes_str = virXPathString(xpath_full, ctxt);
263+- if (!bytes_str) {
264+- if (!required)
265+- return 0;
266+- virReportError(VIR_ERR_XML_ERROR,
267+- _("missing element or attribute '%s'"),
268+- xpath);
269+- return -1;
270+- }
271+- VIR_FREE(xpath_full);
272+-
273+- if (virStrToLong_ullp(bytes_str, NULL, 10, &bytes) < 0) {
274+- virReportError(VIR_ERR_XML_ERROR,
275+- _("Invalid value '%s' for element or attribute '%s'"),
276+- bytes_str, xpath);
277+- return -1;
278+- }
279+-
280+- if (units_xpath)
281+- xpath_full = g_strdup_printf("string(%s)", units_xpath);
282+- else
283+- xpath_full = g_strdup_printf("string(%s/@unit)", xpath);
284+- unit = virXPathString(xpath_full, ctxt);
285+-
286+- if (virScaleInteger(&bytes, unit, scale, max) < 0)
287+- return -1;
288+-
289+- *val = bytes;
290+- return 1;
291+-}
292+
293+
294+ /**
295+@@ -10564,8 +10495,8 @@ virDomainParseMemory(const char *xpath,
296+
297+ max = virMemoryMaxValue(capped);
298+
299+- if (virDomainParseScaledValue(xpath, units_xpath, ctxt,
300+- &bytes, 1024, max, required) < 0)
301++ if (virParseScaledValue(xpath, units_xpath, ctxt,
302++ &bytes, 1024, max, required) < 0)
303+ return -1;
304+
305+ /* Yes, we really do use kibibytes for our internal sizing. */
306+@@ -10607,9 +10538,9 @@ virDomainParseMemoryLimit(const char *xpath,
307+ int ret;
308+ unsigned long long bytes;
309+
310+- ret = virDomainParseScaledValue(xpath, units_xpath, ctxt, &bytes, 1024,
311+- VIR_DOMAIN_MEMORY_PARAM_UNLIMITED << 10,
312+- false);
313++ ret = virParseScaledValue(xpath, units_xpath, ctxt, &bytes, 1024,
314++ VIR_DOMAIN_MEMORY_PARAM_UNLIMITED << 10,
315++ false);
316+
317+ if (ret < 0)
318+ return -1;
319+@@ -10938,9 +10869,9 @@ virDomainControllerDefParseXML(virDomainXMLOptionPtr xmlopt,
320+ "have an address"));
321+ goto error;
322+ }
323+- if ((rc = virDomainParseScaledValue("./pcihole64", NULL,
324+- ctxt, &bytes, 1024,
325+- 1024ULL * ULONG_MAX, false)) < 0)
326++ if ((rc = virParseScaledValue("./pcihole64", NULL,
327++ ctxt, &bytes, 1024,
328++ 1024ULL * ULONG_MAX, false)) < 0)
329+ goto error;
330+
331+ if (rc == 1)
332+@@ -11151,14 +11082,14 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt,
333+ }
334+ }
335+
336+- if (virDomainParseScaledValue("./space_hard_limit[1]",
337+- NULL, ctxt, &def->space_hard_limit,
338+- 1, ULLONG_MAX, false) < 0)
339++ if (virParseScaledValue("./space_hard_limit[1]",
340++ NULL, ctxt, &def->space_hard_limit,
341++ 1, ULLONG_MAX, false) < 0)
342+ goto error;
343+
344+- if (virDomainParseScaledValue("./space_soft_limit[1]",
345+- NULL, ctxt, &def->space_soft_limit,
346+- 1, ULLONG_MAX, false) < 0)
347++ if (virParseScaledValue("./space_soft_limit[1]",
348++ NULL, ctxt, &def->space_soft_limit,
349++ 1, ULLONG_MAX, false) < 0)
350+ goto error;
351+
352+ cur = node->children;
353+@@ -14931,8 +14862,8 @@ virDomainShmemDefParseXML(virDomainXMLOptionPtr xmlopt,
354+ goto cleanup;
355+ }
356+
357+- if (virDomainParseScaledValue("./size[1]", NULL, ctxt,
358+- &def->size, 1, ULLONG_MAX, false) < 0)
359++ if (virParseScaledValue("./size[1]", NULL, ctxt,
360++ &def->size, 1, ULLONG_MAX, false) < 0)
361+ goto cleanup;
362+
363+ if ((server = virXPathNode("./server[1]", ctxt))) {
364+@@ -19308,9 +19239,9 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt,
365+ return -1;
366+ }
367+
368+- if (virDomainParseScaledValue("./@size", "./@unit",
369+- ctxt, &size, 1024,
370+- ULLONG_MAX, true) < 0)
371++ if (virParseScaledValue("./@size", "./@unit",
372++ ctxt, &size, 1024,
373++ ULLONG_MAX, true) < 0)
374+ return -1;
375+
376+ if (virResctrlAllocSetCacheSize(alloc, level, type, cache, size) < 0)
377+@@ -20417,13 +20348,13 @@ virDomainDefParseXML(xmlDocPtr xml,
378+ VIR_FREE(tmp);
379+ }
380+
381+- if (virDomainParseScaledValue("./features/hpt/maxpagesize",
382+- NULL,
383+- ctxt,
384+- &def->hpt_maxpagesize,
385+- 1024,
386+- ULLONG_MAX,
387+- false) < 0) {
388++ if (virParseScaledValue("./features/hpt/maxpagesize",
389++ NULL,
390++ ctxt,
391++ &def->hpt_maxpagesize,
392++ 1024,
393++ ULLONG_MAX,
394++ false) < 0) {
395+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
396+ "%s",
397+ _("Unable to parse HPT maxpagesize setting"));
398+@@ -20649,13 +20580,13 @@ virDomainDefParseXML(xmlDocPtr xml,
399+ }
400+
401+ if (def->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) {
402+- int rv = virDomainParseScaledValue("string(./features/smm/tseg)",
403+- "string(./features/smm/tseg/@unit)",
404+- ctxt,
405+- &def->tseg_size,
406+- 1024 * 1024, /* Defaults to mebibytes */
407+- ULLONG_MAX,
408+- false);
409++ int rv = virParseScaledValue("string(./features/smm/tseg)",
410++ "string(./features/smm/tseg/@unit)",
411++ ctxt,
412++ &def->tseg_size,
413++ 1024 * 1024, /* Defaults to mebibytes */
414++ ULLONG_MAX,
415++ false);
416+ if (rv < 0)
417+ goto error;
418+ def->tseg_specified = rv;
419+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
420+index b97906b852..7bd5e3f445 100644
421+--- a/src/libvirt_private.syms
422++++ b/src/libvirt_private.syms
423+@@ -3435,6 +3435,7 @@ virVsockSetGuestCid;
424+
425+
426+ # util/virxml.h
427++virParseScaledValue;
428+ virXMLCheckIllegalChars;
429+ virXMLChildElementCount;
430+ virXMLExtractNamespaceXML;
431+diff --git a/src/util/virxml.c b/src/util/virxml.c
432+index 0e66d1623b..bae2e6aca5 100644
433+--- a/src/util/virxml.c
434++++ b/src/util/virxml.c
435+@@ -33,6 +33,7 @@
436+ #include "viralloc.h"
437+ #include "virfile.h"
438+ #include "virstring.h"
439++#include "virutil.h"
440+
441+ #define VIR_FROM_THIS VIR_FROM_XML
442+
443+@@ -1433,3 +1434,74 @@ virXMLNamespaceRegister(xmlXPathContextPtr ctxt,
444+
445+ return 0;
446+ }
447++
448++
449++/**
450++ * virParseScaledValue:
451++ * @xpath: XPath to memory amount
452++ * @units_xpath: XPath to units attribute
453++ * @ctxt: XPath context
454++ * @val: scaled value is stored here
455++ * @scale: default scale for @val
456++ * @max: maximal @val allowed
457++ * @required: is the value required?
458++ *
459++ * Parse a value located at @xpath within @ctxt, and store the
460++ * result into @val. The value is scaled by units located at
461++ * @units_xpath (or the 'unit' attribute under @xpath if
462++ * @units_xpath is NULL). If units are not present, the default
463++ * @scale is used. If @required is set, then the value must
464++ * exist; otherwise, the value is optional. The resulting value
465++ * is in bytes.
466++ *
467++ * Returns 1 on success,
468++ * 0 if the value was not present and !@required,
469++ * -1 on failure after issuing error.
470++ */
471++int
472++virParseScaledValue(const char *xpath,
473++ const char *units_xpath,
474++ xmlXPathContextPtr ctxt,
475++ unsigned long long *val,
476++ unsigned long long scale,
477++ unsigned long long max,
478++ bool required)
479++{
480++ unsigned long long bytes;
481++ g_autofree char *xpath_full = NULL;
482++ g_autofree char *unit = NULL;
483++ g_autofree char *bytes_str = NULL;
484++
485++ *val = 0;
486++ xpath_full = g_strdup_printf("string(%s)", xpath);
487++
488++ bytes_str = virXPathString(xpath_full, ctxt);
489++ if (!bytes_str) {
490++ if (!required)
491++ return 0;
492++ virReportError(VIR_ERR_XML_ERROR,
493++ _("missing element or attribute '%s'"),
494++ xpath);
495++ return -1;
496++ }
497++ VIR_FREE(xpath_full);
498++
499++ if (virStrToLong_ullp(bytes_str, NULL, 10, &bytes) < 0) {
500++ virReportError(VIR_ERR_XML_ERROR,
501++ _("Invalid value '%s' for element or attribute '%s'"),
502++ bytes_str, xpath);
503++ return -1;
504++ }
505++
506++ if (units_xpath)
507++ xpath_full = g_strdup_printf("string(%s)", units_xpath);
508++ else
509++ xpath_full = g_strdup_printf("string(%s/@unit)", xpath);
510++ unit = virXPathString(xpath_full, ctxt);
511++
512++ if (virScaleInteger(&bytes, unit, scale, max) < 0)
513++ return -1;
514++
515++ *val = bytes;
516++ return 1;
517++}
518+diff --git a/src/util/virxml.h b/src/util/virxml.h
519+index 26ab9f9c2d..39b261687a 100644
520+--- a/src/util/virxml.h
521++++ b/src/util/virxml.h
522+@@ -269,3 +269,11 @@ virXMLNamespaceFormatNS(virBufferPtr buf,
523+ int
524+ virXMLNamespaceRegister(xmlXPathContextPtr ctxt,
525+ virXMLNamespace const *ns);
526++
527++int virParseScaledValue(const char *xpath,
528++ const char *units_xpath,
529++ xmlXPathContextPtr ctxt,
530++ unsigned long long *val,
531++ unsigned long long scale,
532++ unsigned long long max,
533++ bool required);
534+--
535+2.25.1
536+
537diff --git a/debian/patches/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch b/debian/patches/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch
538new file mode 100644
539index 0000000..ee13577
540--- /dev/null
541+++ b/debian/patches/clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch
542@@ -0,0 +1,191 @@
543+From 3e1d2c93a3edce65ce8cb589edb07e2f830c9c12 Mon Sep 17 00:00:00 2001
544+Description: storage: add support for QCOW2 cluster_size option
545+Author: Pavel Hrdina <phrdina@redhat.com>
546+Origin: upstream, https://github.com/libvirt/libvirt/commit/3e1d2c93a3edce65ce8cb589edb07e2f830c9c12
547+Bug: https://gitlab.com/libvirt/libvirt/-/issues/154
548+Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
549+Last-Update: 2021-05-24
550+
551+storage: add support for QCOW2 cluster_size option
552+
553+The default value hard-coded in QEMU (64KiB) is not always the ideal.
554+Having a possibility to set the cluster_size by user may in specific
555+use-cases improve performance for QCOW2 images.
556+
557+QEMU internally has some limits, the value has to be between 512B and
558+2048KiB and must by power of two, except when the image has Extended L2
559+Entries the minimal value has to be 16KiB.
560+
561+Since qemu-img ensures the value is correct and the limit is not always
562+the same libvirt will not duplicate any of these checks as the error
563+message from qemu-img is good enough:
564+
565+ Cluster size must be a power of two between 512 and 2048k
566+
567+Resolves: https://gitlab.com/libvirt/libvirt/-/issues/154
568+
569+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
570+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
571+---
572+ docs/formatstorage.html.in | 6 ++++++
573+ docs/schemas/storagecommon.rng | 6 ++++++
574+ docs/schemas/storagevol.rng | 3 +++
575+ src/conf/storage_conf.c | 12 ++++++++++++
576+ src/storage/storage_util.c | 5 +++++
577+ .../qcow2-clusterSize.argv | 6 ++++++
578+ tests/storagevolxml2argvtest.c | 4 ++++
579+ .../vol-qcow2-clusterSize.xml | 17 +++++++++++++++++
580+ .../vol-qcow2-clusterSize.xml | 17 +++++++++++++++++
581+ tests/storagevolxml2xmltest.c | 1 +
582+ 10 files changed, 77 insertions(+)
583+ create mode 100644 tests/storagevolxml2argvdata/qcow2-clusterSize.argv
584+ create mode 100644 tests/storagevolxml2xmlin/vol-qcow2-clusterSize.xml
585+ create mode 100644 tests/storagevolxml2xmlout/vol-qcow2-clusterSize.xml
586+
587+--- a/docs/formatstorage.html.in
588++++ b/docs/formatstorage.html.in
589+@@ -766,6 +766,7 @@
590+ &lt;/encryption&gt;
591+ &lt;compat&gt;1.1&lt;/compat&gt;
592+ &lt;nocow/&gt;
593++ &lt;clusterSize unit='KiB'&gt;64&lt;/clusterSize&gt;
594+ &lt;features&gt;
595+ &lt;lazy_refcounts/&gt;
596+ &lt;/features&gt;
597+@@ -842,6 +843,11 @@
598+ the file image is used in VM. To create non-raw file images, it
599+ requires QEMU version since 2.1. <span class="since">Since 1.2.7</span>
600+ </dd>
601++ <dt><code>clusterSize</code></dt>
602++ <dd>Changes the qcow2 cluster size which can affect image file size
603++ and performance.
604++ <span class="since">Since 7.4.0</span>
605++ </dd>
606+ <dt><code>features</code></dt>
607+ <dd>Format-specific features. Only used for <code>qcow2</code> now.
608+ Valid sub-elements are:
609+--- a/docs/schemas/storagecommon.rng
610++++ b/docs/schemas/storagecommon.rng
611+@@ -111,6 +111,12 @@
612+ </element>
613+ </define>
614+
615++ <define name="clusterSize">
616++ <element name="clusterSize">
617++ <ref name="scaledInteger"/>
618++ </element>
619++ </define>
620++
621+ <define name='compat'>
622+ <element name='compat'>
623+ <data type='string'>
624+--- a/docs/schemas/storagevol.rng
625++++ b/docs/schemas/storagevol.rng
626+@@ -125,6 +125,9 @@
627+ </element>
628+ </optional>
629+ <optional>
630++ <ref name="clusterSize"/>
631++ </optional>
632++ <optional>
633+ <ref name='fileFormatFeatures'/>
634+ </optional>
635+ </interleave>
636+--- a/src/conf/storage_conf.c
637++++ b/src/conf/storage_conf.c
638+@@ -1397,6 +1397,13 @@
639+ if (virXPathNode("./target/nocow", ctxt))
640+ def->target.nocow = true;
641+
642++ if (virParseScaledValue("./target/clusterSize",
643++ "./target/clusterSize/@unit",
644++ ctxt, &def->target.clusterSize,
645++ 1, ULLONG_MAX, false) < 0) {
646++ return NULL;
647++ }
648++
649+ if (virXPathNode("./target/features", ctxt)) {
650+ if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
651+ return NULL;
652+@@ -1562,6 +1569,11 @@
653+
654+ virBufferEscapeString(buf, "<compat>%s</compat>\n", def->compat);
655+
656++ if (def->clusterSize > 0) {
657++ virBufferAsprintf(buf, "<clusterSize unit='B'>%llu</clusterSize>\n",
658++ def->clusterSize);
659++ }
660++
661+ if (def->features) {
662+ size_t i;
663+ bool empty = virBitmapIsAllClear(def->features);
664+--- a/src/storage/storage_util.c
665++++ b/src/storage/storage_util.c
666+@@ -693,6 +693,7 @@
667+ const char *path;
668+ unsigned long long size_arg;
669+ unsigned long long allocation;
670++ unsigned long long clusterSize;
671+ bool encryption;
672+ bool preallocate;
673+ const char *compat;
674+@@ -739,6 +740,9 @@
675+ else if (info->format == VIR_STORAGE_FILE_QCOW2)
676+ virBufferAddLit(&buf, "compat=0.10,");
677+
678++ if (info->clusterSize > 0)
679++ virBufferAsprintf(&buf, "cluster_size=%llu,", info->clusterSize);
680++
681+ if (info->features && info->format == VIR_STORAGE_FILE_QCOW2) {
682+ if (virBitmapIsBitSet(info->features,
683+ VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS)) {
684+@@ -1069,6 +1073,7 @@
685+ .compat = vol->target.compat,
686+ .features = vol->target.features,
687+ .nocow = vol->target.nocow,
688++ .clusterSize = vol->target.clusterSize,
689+ .secretAlias = NULL,
690+ };
691+ virStorageEncryptionPtr enc = vol->target.encryption;
692+--- /dev/null
693++++ b/tests/storagevolxml2argvdata/qcow2-clusterSize.argv
694+@@ -0,0 +1,6 @@
695++qemu-img \
696++create \
697++-f qcow2 \
698++-o compat=0.10,cluster_size=131072 \
699++/var/lib/libvirt/images/OtherDemo.img \
700++5242880K
701+--- a/tests/storagevolxml2argvtest.c
702++++ b/tests/storagevolxml2argvtest.c
703+@@ -238,6 +238,10 @@
704+ "pool-dir", "vol-qcow2-nocapacity-backing", NULL, NULL,
705+ "qcow2-nocapacity", 0);
706+
707++ DO_TEST("pool-dir", "vol-qcow2-clusterSize",
708++ NULL, NULL,
709++ "qcow2-clusterSize", 0);
710++
711+ DO_TEST("pool-dir", "vol-file-iso",
712+ NULL, NULL,
713+ "iso", 0);
714+--- /dev/null
715++++ b/tests/storagevolxml2xmlin/vol-qcow2-clusterSize.xml
716+@@ -0,0 +1,17 @@
717++<volume>
718++ <name>OtherDemo.img</name>
719++ <key>/var/lib/libvirt/images/OtherDemo.img</key>
720++ <capacity unit="G">5</capacity>
721++ <allocation>294912</allocation>
722++ <target>
723++ <path>/var/lib/libvirt/images/OtherDemo.img</path>
724++ <format type='qcow2'/>
725++ <permissions>
726++ <mode>0644</mode>
727++ <owner>0</owner>
728++ <group>0</group>
729++ <label>unconfined_u:object_r:virt_image_t:s0</label>
730++ </permissions>
731++ <clusterSize unit='KiB'>128</clusterSize>
732++ </target>
733++</volume>
734diff --git a/debian/patches/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch b/debian/patches/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch
735new file mode 100644
736index 0000000..4966303
737--- /dev/null
738+++ b/debian/patches/clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch
739@@ -0,0 +1,228 @@
740+From 93344aed27c686239ff53b8912eb4476be5e9ef7 Mon Sep 17 00:00:00 2001
741+Description: storage_file: add support to probe cluster_size from QCOW2 images
742+Author: Pavel Hrdina <phrdina@redhat.com>
743+Origin: backport, https://github.com/libvirt/libvirt/commit/93344aed27c686239ff53b8912eb4476be5e9ef7
744+Bug: https://gitlab.com/libvirt/libvirt/-/issues/154
745+Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
746+Last-Update: 2021-05-24
747+
748+storage_file: add support to probe cluster_size from QCOW2 images
749+
750+From QEMU docs/interop/qcow2.txt :
751+
752+ Byte 20 - 23: cluster_bits
753+ Number of bits that are used for addressing an offset
754+ within a cluster (1 << cluster_bits is the cluster size).
755+
756+With this patch libvirt will be able to report the current cluster_size
757+for all existing storage volumes managed by storage driver.
758+
759+[Backport]
760+
761+ Commit 2cdd833eae ("util: move virStorageFileProbe code into
762+ storage_file") did move the src/util/virstoragefile.c into
763+ storage_file/storage_file_probe.c. For backport purposes that
764+ move is not needed for this patch to be functional.
765+
766+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
767+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
768+Signed-off-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
769+---
770+ src/storage/storage_util.c | 3 ++
771+ src/util/virstoragefile.c | 62 +++++++++++++++++++++++++++-----------
772+ 2 files changed, 48 insertions(+), 17 deletions(-)
773+
774+diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
775+index 08e6ab31b1..0e06db341f 100644
776+--- a/src/storage/storage_util.c
777++++ b/src/storage/storage_util.c
778+@@ -3400,6 +3400,9 @@ storageBackendProbeTarget(virStorageSourcePtr target,
779+ if (meta->capacity)
780+ target->capacity = meta->capacity;
781+
782++ if (meta->clusterSize > 0)
783++ target->clusterSize = meta->clusterSize;
784++
785+ if (encryption && meta->encryption) {
786+ if (meta->encryption->payload_offset != -1)
787+ target->capacity -= meta->encryption->payload_offset * 512;
788+diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
789+index 1397f532fd..7e3957de0f 100644
790+--- a/src/util/virstoragefile.c
791++++ b/src/util/virstoragefile.c
792+@@ -170,6 +170,8 @@ struct FileTypeInfo {
793+ * or NULL if there is no COW base image, to RES;
794+ * return BACKING_STORE_* */
795+ const struct FileEncryptionInfo *cryptInfo; /* Encryption info */
796++ unsigned long long (*getClusterSize)(const char *buf,
797++ size_t buf_size);
798+ int (*getBackingStore)(char **res, int *format,
799+ const char *buf, size_t buf_size);
800+ int (*getFeatures)(virBitmapPtr *features, int format,
801+@@ -179,6 +181,9 @@ struct FileTypeInfo {
802+
803+ static int cowGetBackingStore(char **, int *,
804+ const char *, size_t);
805++static unsigned long long
806++qcow2GetClusterSize(const char *buf,
807++ size_t buf_size);
808+ static int qcowXGetBackingStore(char **, int *,
809+ const char *, size_t);
810+ static int qcow2GetFeatures(virBitmapPtr *features, int format,
811+@@ -191,7 +196,8 @@ qedGetBackingStore(char **, int *, const char *, size_t);
812+ #define QCOWX_HDR_VERSION (4)
813+ #define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4)
814+ #define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8)
815+-#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4)
816++#define QCOWX_HDR_CLUSTER_BITS_OFFSET (QCOWX_HDR_BACKING_FILE_SIZE+4)
817++#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_CLUSTER_BITS_OFFSET+4)
818+
819+ #define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1+2)
820+ #define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8)
821+@@ -298,18 +304,18 @@ static struct FileEncryptionInfo const qcow2EncryptionInfo[] = {
822+
823+ static struct FileTypeInfo const fileTypeInfo[] = {
824+ [VIR_STORAGE_FILE_NONE] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
825+- -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
826++ -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL, NULL },
827+ [VIR_STORAGE_FILE_RAW] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
828+ -1, 0, {0}, 0, 0, 0,
829+ luksEncryptionInfo,
830+- NULL, NULL },
831++ NULL, NULL, NULL },
832+ [VIR_STORAGE_FILE_DIR] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
833+- -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
834++ -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL, NULL },
835+ [VIR_STORAGE_FILE_BOCHS] = {
836+ /*"Bochs Virtual HD Image", */ /* Untested */
837+ 0, NULL, NULL,
838+ LV_LITTLE_ENDIAN, 64, 4, {0x20000},
839+- 32+16+16+4+4+4+4+4, 8, 1, NULL, NULL, NULL
840++ 32+16+16+4+4+4+4+4, 8, 1, NULL, NULL, NULL, NULL
841+ },
842+ [VIR_STORAGE_FILE_CLOOP] = {
843+ /* #!/bin/sh
844+@@ -318,7 +324,7 @@ static struct FileTypeInfo const fileTypeInfo[] = {
845+ */ /* Untested */
846+ 0, NULL, NULL,
847+ LV_LITTLE_ENDIAN, -1, 0, {0},
848+- -1, 0, 0, NULL, NULL, NULL
849++ -1, 0, 0, NULL, NULL, NULL, NULL
850+ },
851+ [VIR_STORAGE_FILE_DMG] = {
852+ /* XXX QEMU says there's no magic for dmg,
853+@@ -326,51 +332,52 @@ static struct FileTypeInfo const fileTypeInfo[] = {
854+ * would have to match) but then disables that check. */
855+ 0, NULL, ".dmg",
856+ 0, -1, 0, {0},
857+- -1, 0, 0, NULL, NULL, NULL
858++ -1, 0, 0, NULL, NULL, NULL, NULL
859+ },
860+ [VIR_STORAGE_FILE_ISO] = {
861+ 32769, "CD001", ".iso",
862+ LV_LITTLE_ENDIAN, -2, 0, {0},
863+- -1, 0, 0, NULL, NULL, NULL
864++ -1, 0, 0, NULL, NULL, NULL, NULL
865+ },
866+ [VIR_STORAGE_FILE_VPC] = {
867+ 0, "conectix", NULL,
868+ LV_BIG_ENDIAN, 12, 4, {0x10000},
869+- 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, NULL, NULL, NULL
870++ 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, NULL, NULL, NULL, NULL
871+ },
872+ /* TODO: add getBackingStore function */
873+ [VIR_STORAGE_FILE_VDI] = {
874+ 64, "\x7f\x10\xda\xbe", ".vdi",
875+ LV_LITTLE_ENDIAN, 68, 4, {0x00010001},
876+- 64 + 5 * 4 + 256 + 7 * 4, 8, 1, NULL, NULL, NULL},
877++ 64 + 5 * 4 + 256 + 7 * 4, 8, 1, NULL, NULL, NULL, NULL},
878+
879+ /* Not direct file formats, but used for various drivers */
880+ [VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
881+- -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
882++ -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL, NULL },
883+ [VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
884+- -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
885++ -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL, NULL },
886+ [VIR_STORAGE_FILE_PLOOP] = { 0, "WithouFreSpacExt", NULL, LV_LITTLE_ENDIAN,
887+ -2, 0, {0}, PLOOP_IMAGE_SIZE_OFFSET, 0,
888+- PLOOP_SIZE_MULTIPLIER, NULL, NULL, NULL },
889++ PLOOP_SIZE_MULTIPLIER, NULL, NULL, NULL, NULL },
890+
891+ /* All formats with a backing store probe below here */
892+ [VIR_STORAGE_FILE_COW] = {
893+ 0, "OOOM", NULL,
894+ LV_BIG_ENDIAN, 4, 4, {2},
895+- 4+4+1024+4, 8, 1, NULL, cowGetBackingStore, NULL
896++ 4+4+1024+4, 8, 1, NULL, NULL, cowGetBackingStore, NULL
897+ },
898+ [VIR_STORAGE_FILE_QCOW] = {
899+ 0, "QFI", NULL,
900+ LV_BIG_ENDIAN, 4, 4, {1},
901+ QCOWX_HDR_IMAGE_SIZE, 8, 1,
902+ qcow1EncryptionInfo,
903+- qcowXGetBackingStore, NULL
904++ NULL, qcowXGetBackingStore, NULL
905+ },
906+ [VIR_STORAGE_FILE_QCOW2] = {
907+ 0, "QFI", NULL,
908+ LV_BIG_ENDIAN, 4, 4, {2, 3},
909+ QCOWX_HDR_IMAGE_SIZE, 8, 1,
910+ qcow2EncryptionInfo,
911++ qcow2GetClusterSize,
912+ qcowXGetBackingStore,
913+ qcow2GetFeatures
914+ },
915+@@ -378,12 +385,12 @@ static struct FileTypeInfo const fileTypeInfo[] = {
916+ /* https://wiki.qemu.org/Features/QED */
917+ 0, "QED", NULL,
918+ LV_LITTLE_ENDIAN, -2, 0, {0},
919+- QED_HDR_IMAGE_SIZE, 8, 1, NULL, qedGetBackingStore, NULL
920++ QED_HDR_IMAGE_SIZE, 8, 1, NULL, NULL, qedGetBackingStore, NULL
921+ },
922+ [VIR_STORAGE_FILE_VMDK] = {
923+ 0, "KDMV", NULL,
924+ LV_LITTLE_ENDIAN, 4, 4, {1, 2, 3},
925+- 4+4+4, 8, 512, NULL, vmdk4GetBackingStore, NULL
926++ 4+4+4, 8, 512, NULL, NULL, vmdk4GetBackingStore, NULL
927+ },
928+ };
929+ verify(G_N_ELEMENTS(fileTypeInfo) == VIR_STORAGE_FILE_LAST);
930+@@ -543,6 +550,24 @@ qcow2GetExtensions(const char *buf,
931+ }
932+
933+
934++static unsigned long long
935++qcow2GetClusterSize(const char *buf,
936++ size_t buf_size)
937++{
938++ int clusterBits = 0;
939++
940++ if ((QCOWX_HDR_CLUSTER_BITS_OFFSET + 4) > buf_size)
941++ return 0;
942++
943++ clusterBits = virReadBufInt32BE(buf + QCOWX_HDR_CLUSTER_BITS_OFFSET);
944++
945++ if (clusterBits > 0)
946++ return 1 << clusterBits;
947++
948++ return 0;
949++}
950++
951++
952+ static int
953+ qcowXGetBackingStore(char **res,
954+ int *format,
955+@@ -1030,6 +1055,9 @@ virStorageFileGetMetadataInternal(virStorageSourcePtr meta,
956+ meta->capacity *= fileTypeInfo[meta->format].sizeMultiplier;
957+ }
958+
959++ if (fileTypeInfo[meta->format].getClusterSize != NULL)
960++ meta->clusterSize = fileTypeInfo[meta->format].getClusterSize(buf, len);
961++
962+ VIR_FREE(meta->backingStoreRaw);
963+ if (fileTypeInfo[meta->format].getBackingStore != NULL) {
964+ int store = fileTypeInfo[meta->format].getBackingStore(&meta->backingStoreRaw,
965+--
966+2.25.1
967+
968diff --git a/debian/patches/series b/debian/patches/series
969index 33f754c..37fb113 100644
970--- a/debian/patches/series
971+++ b/debian/patches/series
972@@ -155,3 +155,14 @@ ubuntu/lp-1922907-cputest-Add-data-for-Intel-R-Xeon-R-Platinum-9242-CP.patch
973 ubuntu/lp-1922907-cputest-Add-data-for-Intel-R-Xeon-R-Gold-6130-CPU.patch
974 ubuntu/lp-1922907-cpu_map-Distinguish-Cascadelake-Server-from-Skylake-.patch
975 ubuntu/lp-1922907-cleanup-test-data.patch
976+
977+# backport QCOW2 cluster_size support
978+# (https://gitlab.com/libvirt/libvirt/-/issues/154)
979+
980+clustersize/0001-qemu-monitor-Detect-image-cluster-size-from-query-na.patch
981+clustersize/0002-qemu-block-Allow-specifying-cluster-size-when-using-.patch
982+clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch
983+clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch
984+clustersize/0005-storage-add-support-for-QCOW2-cluster_size-option.patch
985+clustersize/0006-storage_file-add-support-to-probe-cluster_size-from-.patch
986+

Subscribers

People subscribed via source and target branches