Merge ~rafaeldtinoco/ubuntu/+source/libvirt:focal-clustersize into ubuntu/+source/libvirt:ubuntu/focal-devel
- Git
- lp:~rafaeldtinoco/ubuntu/+source/libvirt
- focal-clustersize
- Merge into ubuntu/focal-devel
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) |
Related bugs: |
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 |
Commit message
Description of the change
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
Regarding the patchset:
* Add support for QCOW2 cluster_size option:
+ d/p/clustersize
+ d/p/clustersize
+ d/p/clustersize
+ d/p/clustersize
+ d/p/clustersize
+ d/p/clustersize
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
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
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.
Lucas Kanashiro (lucaskanashiro) wrote : | # |
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: storagevolxml2x
=======
TEST: storagevolxml2x
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-
11) Storage Vol XML-2-XML vol-qcow2-
In '/<<PKGBUILDDIR
Offset 104
Expect [c]
Actual [source>
</source>
<c]
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-
20) Storage Vol XML-2-XML vol-qcow2-
FAIL storagevolxml2x
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.
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...
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.
libvirt (6.0.0-0ubuntu8.9) focal; urgency=medium
> Version present in the 'build' PPA is 6.0.0-0ubuntu8.
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.
> NO =), I used it locally only.
The patch set looks sane to me.
> Thanks! I'll check the tests failure and reply here.
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
make[3]: Entering directory '/home/
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: virportallocato
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: virnetservercli
PASS: virnettlscontex
PASS: virnettlssessio
PASS: fchosttest
PASS: scsihosttest
PASS: vircaps2xmltest
PASS: virresctrltest
PASS: fdstreamtest
PASS: virdbustest
PASS: virsystemdtest
PASS: virpolkittest
PASS: qemuxml2argvtest
PASS: qemuxml2xmltest
PASS: qemudomaincheck
PASS: qemudomainsnaps
PASS: qemumonitorjsontest
PASS: qemuhotplugtest
PASS: qemuagenttest
PASS: qemucapabilitie
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: networkxml2xmlu
PASS: virnetworkportx
PASS: nwfilterxml2xmltest
PASS: virnwfilterbind
PASS: nwfilterebiptab
PASS: nwfilterxml2fir
PASS: storagevolxml2a
PASS: storagepoolxml2
PASS: virstorageutiltest
PASS: storagepoolxml2
PASS: storagepoolcapstest
PASS: virstoragetest
PASS: virscsitest
FAIL: storagevolxml2x
PASS: nodedevxml2xmltest
PASS: interfacexml2xm
PASS: cputest
PASS: metadatatest
PASS: secretxml2xmltest
PASS: genericxml2xmltest
PASS: virusbtest
PASS: virnetdevbandwi
PASS: eventtest
PASS: virdrivermoduletest
PASS: virdriverconnva
PASS: objecteventtest
PASS: virmacmaptest
PASS: virnetdevopenvs
PASS: libvirtd-fail
PASS: libvirtd-pool
PASS: virsh-cpuset
PASS: virsh-define-
PASS: virsh-int-overflow
SKIP: virsh-optparse
PASS: virsh-read-bufsiz
PASS: virsh-read-
PASS: virsh-schedinfo
PASS: virsh-self-test
PASS: virt-admin-
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: storagevolxml2x
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
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: virportallocato
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: virnetservercli
PASS: virnettlscontex
PASS: virnettlssessio
PASS: fchosttest
PASS: scsihosttest
PASS: vircaps2xmltest
PASS: virresctrltest
PASS: fdstreamtest
PASS: virdbustest
PASS: virsystemdtest
PASS: virpolkittest
PASS: qemuxml2argvtest
PASS: qemuxml2xmltest
PASS: qemudomaincheck
PASS: qemudomainsnaps
PASS: qemumonitorjsontest
PASS: qemuhotplugtest
PASS: qemuagenttest
PASS: qemucapabilitie
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: networkxml2xmlu
PASS: virnetworkportx
PASS: nwfilterxml2xmltest
PASS: virnwfilterbind
PASS: nwfilterebiptab
PASS: nwfilterxml2fir
PASS: storagevolxml2a
PASS: storagepoolxml2
PASS: virstorageutiltest
PASS: storagepoolxml2
PASS: storagepoolcapstest
PASS: virstoragetest
PASS: virscsitest
PASS: storagevolxml2x
PASS: nodedevxml2xmltest
PASS: interfacexml2xm
PASS: cputest
PASS: metadatatest
PASS: secretxml2xmltest
PASS: genericxml2xmltest
PASS: virusbtest
PASS: virnetdevbandwi
PASS: eventtest
PASS: virdrivermoduletest
PASS: virdriverconnva
PASS: objecteventtest
PASS: virmacmaptest
PASS: virnetdevopenvs
PASS: libvirtd-fail
PASS: libvirtd-pool
PASS: virsh-cpuset
PASS: virsh-define-
PASS: virsh-int-overflow
SKIP: virsh-optparse
PASS: virsh-read-bufsiz
PASS: virsh-read-
PASS: virsh-schedinfo
PASS: virsh-self-test
PASS: virt-admin-
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 ...
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
Good to go. Feel free to merge to 'other repos' if you feel like it.
Thanks a lot
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: storagevolxml2x
=======
TEST: storagevolxml2x
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-
11) Storage Vol XML-2-XML vol-qcow2-
In '/<<PKGBUILDDIR
Offset 524
Expect []
Actual [ </target>
</volume>
]
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-
20) Storage Vol XML-2-XML vol-qcow2-
FAIL storagevolxml2x
Did you forget to git push any local change? I am wondering why this test is passing for you but failing for me.
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
virStorageV
If there are no source extents the volume XML has an empty <source>
element. Remove it if there's nothing in it by using
virXMLForma
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.
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
The focal PPA:
https:/
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/
Pool default created
$ virsh vol-create --pool default --file ./guest01-
Vol guest-disk01.qcow2 created from ./guest01-
$ sudo qemu-img info /var/lib/
image: /var/lib/
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>
<key>
<source>
</source>
<capacity unit='bytes'
<allocation unit='bytes'
<physical unit='bytes'
<target>
<path>
<format type='qcow2'/>
<permissions>
<
<
<
</permissions>
<timestamps>
<
<
<
</timestamps>
<compat>
<clusterSize unit='B'
<features/>
</target>
</volume>
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
If you check that PPA's build log:
...
PASS: storagepoolcapstest
PASS: storagepoolxml2
PASS: virscsitest
PASS: nsstest
PASS: nssguesttest
PASS: storagevolxml2x
PASS: nodedevxml2xmltest
PASS: interfacexml2xm
PASS: metadatatest
PASS: secretxml2xmltest
PASS: virstoragetest
PASS: virusbtest
PASS: genericxml2xmltest
...
So the test storagevolxml2x
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.
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
Just pushed my latest branch, the one I used to build the PPA.
Rafael David Tinoco (rafaeldtinoco) wrote : | # |
Okay, now, for the Bionic backport you can grab these 2 patches:
https:/
and
https:/
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-
ibm/clusz-
ibm/clusz-
ibm/clusz-
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.
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.
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 :-)
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-qemuBlock StorageSourceCr eateDetectSize- Propagate- clu.patch
+ d/p/clustersize/0004-conf- Move-and- rename- virDomainParseS caledValue. 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
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index 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 |
21 | diff --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 |
22 | new file mode 100644 |
23 | index 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 | + |
80 | diff --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 |
81 | new file mode 100644 |
82 | index 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 | + |
133 | diff --git a/debian/patches/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch b/debian/patches/clustersize/0003-qemuBlockStorageSourceCreateDetectSize-Propagate-clu.patch |
134 | new file mode 100644 |
135 | index 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 | + |
179 | diff --git a/debian/patches/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch b/debian/patches/clustersize/0004-conf-Move-and-rename-virDomainParseScaledValue.patch |
180 | new file mode 100644 |
181 | index 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 | + |
537 | diff --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 |
538 | new file mode 100644 |
539 | index 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 | + </encryption> |
591 | + <compat>1.1</compat> |
592 | + <nocow/> |
593 | ++ <clusterSize unit='KiB'>64</clusterSize> |
594 | + <features> |
595 | + <lazy_refcounts/> |
596 | + </features> |
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> |
734 | diff --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 |
735 | new file mode 100644 |
736 | index 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 | + |
968 | diff --git a/debian/patches/series b/debian/patches/series |
969 | index 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 | + |
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'> guest-disk01. qcow2</ name> /var/lib/ libvirt/ images/ guest-disk01. qcow2</ key> >5368709120< /capacity> >6295552< /allocation> >6291464< /physical> /var/lib/ libvirt/ images/ guest-disk01. qcow2</ path> mode>0644< /mode> owner>0< /owner> group>0< /group> atime>162191756 5.209401319< /atime> mtime>162191756 5.261402011< /mtime> ctime>162191756 5.261402011< /ctime> 1.1</compat> >2097152< /clusterSize>
<name>
<key>
<source>
</source>
<capacity unit='bytes'
<allocation unit='bytes'
<physical unit='bytes'
<target>
<path>
<format type='qcow2'/>
<permissions>
<
<
<
</permissions>
<timestamps>
<
<
<
</timestamps>
<compat>
<clusterSize unit='B'
<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 libvirt/ images/ guest-disk01. qcow2
image: /var/lib/
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