Description of problem: Disarrange of key-value pairs in iSCSI image's JSON representation will results in qemu-img's failure of determining it valid as backing image. Version-Release number of selected component (if applicable): qemu-kvm-rhev-2.12.0-6.el7 kernel-3.10.0-916.el7 How reproducible: 100% Steps to Reproduce: create snapshot chain over libiscsi: base -> sn1 -> sn2 1. create base image # qemu-img create -f qcow2 iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/2 1G 2. create sn1 # qemu-img create -f qcow2 -b 'json:{"driver":"qcow2","file":{"driver":"iscsi","target":"iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3","transport":"tcp","lun":"2","portal":"127.0.0.1"}}' iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/3 3. create sn2 # qemu-img create -f qcow2 -b 'json:{"driver":"qcow2","file":{"driver":"iscsi","target":"iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3","transport":"tcp","lun":"3","portal":"127.0.0.1"}}' iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 4. check the backing chain # qemu-img info --backing-chain iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 5. commit sn2 to base, use the JSON format of base from output of 5. # qemu-img commit -p -b 'json:{"driver": "qcow2", "file": {"lun": "2", "portal": "127.0.0.1", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}}' iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 6. disarrange the key-value pairs in the JSON format. # qemu-img commit -p -b 'json:{"driver": "qcow2", "file": {"lun": "2", "transport": "tcp", "portal": "127.0.0.1", "driver": "iscsi", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}}' iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 Actual results: from 4: # qemu-img info --backing-chain iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 image: json:{"driver": "qcow2", "file": {"lun": "4", "portal": "127.0.0.1", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}} file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: unavailable cluster_size: 65536 backing file: json:{"driver":"qcow2","file":{"driver":"iscsi","target":"iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3","transport":"tcp","lun":"3","portal":"127.0.0.1"}} Format specific information: compat: 1.1 lazy refcounts: false refcount bits: 16 corrupt: false image: json:{"driver": "qcow2", "file": {"lun": "3", "portal": "127.0.0.1", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}} file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: unavailable cluster_size: 65536 backing file: json:{"driver":"qcow2","file":{"driver":"iscsi","target":"iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3","transport":"tcp","lun":"2","portal":"127.0.0.1"}} Format specific information: compat: 1.1 lazy refcounts: false refcount bits: 16 corrupt: false image: json:{"driver": "qcow2", "file": {"lun": "2", "portal": "127.0.0.1", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}} file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: unavailable cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false refcount bits: 16 corrupt: false from 5: # qemu-img commit -p -b 'json:{"driver": "qcow2", "file": {"lun": "2", "portal": "127.0.0.1", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}}' iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 (100.00/100%) Image committed. from 6: # qemu-img commit -p -b 'json:{"driver": "qcow2", "file": {"lun": "2", "transport": "tcp", "portal": "127.0.0.1", "driver": "iscsi", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}}' iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4 (0.00/100%) qemu-img: Did not find 'json:{"driver": "qcow2", "file": {"lun": "2", "transport": "tcp", "portal": "127.0.0.1", "driver": "iscsi", "target": "iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3"}}' in the backing chain of 'iscsi://127.0.0.1/iqn.2003-01.org.linux-iscsi.intel-5130-16-1.x8664:sn.d4aeb8adfdd3/4' Expected results: disarrange of key-value pairs in JSON representation should not prevent qemu-img from recognizing if it is in backing-chain. IOW, qemu-img should parse image's JSON first instead of doing simple string comparison. Additional info:
I’m not sure we’ll change this. qemu-img commit takes a filename which is compared as a string to the filenames in the backing chain. If you modify the string, it won’t work. So I personally don’t take issue with the fact that reordering the keys stops it from working. What I do take a bit of an issue with is that bdrv_refresh_filename() meddles with the result. You may have noticed that for qemu-img create, you didn’t specify spaces in the json:{} filename, but for commit, you do need to specify them. Or let’s take simpler example. $ qemu-img create -f qcow2 base.qcow2 64M Formatting 'base.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 $ qemu-img create -f qcow2 -b file:base.qcow2 top.qcow2 Formatting 'top.qcow2', fmt=qcow2 size=67108864 backing_file=file:base.qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 So the thing is that the bdrv_refresh_filename() infrastructure will compact “file:base.qcow2” to “base.qcow2” at runtime. So, consequently, the backing chain looks like this: $ qemu-img info --backing-chain top.qcow2 image: top.qcow2 file format: qcow2 virtual size: 64M (67108864 bytes) disk size: 196K cluster_size: 65536 backing file: file:base.qcow2 Format specific information: compat: 1.1 lazy refcounts: false refcount bits: 16 corrupt: false image: base.qcow2 file format: qcow2 virtual size: 64M (67108864 bytes) disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false refcount bits: 16 corrupt: false top.qcow2’s backing file is “file:base.qcow2” (as we’ve specified), but the actual filename of the base BDS is just “base.qcow2”. So a commit to “file:base.qcow2” will not work, you’ll have to use “base.qcow2”: $ qemu-img commit -b file:base.qcow2 top.qcow2 qemu-img: Did not find 'file:base.qcow2' in the backing chain of 'top.qcow2' $ qemu-img commit -b base.qcow2 top.qcow2 Image committed. For the QMP commands, that is (in the long term at least) not really an issue because the fix is trivial: Just use node names instead of filenames. However, that won’t work with qemu-img commit. A real fix would be a bit difficult (basically impossible for arbitrary cases, but it might work for qemu-img alone).[1] That, or we just document that the filenames you can give to qemu-img commit have to exactly match the filenames for each of the entries in qemu-img info --backing-chain. Well, we can do that anyway, so we probably should. Max [1] For the record: It’d depend on having a way to tell whether a BDS’s backing file has been overridden (done in my “Fix some filename generation issues” series that also addresses BZ 1510560), and then we’d need a BDS field for storing the image header’s backing file string.
(In reply to Max Reitz from comment #2) > What I do take a bit of an issue with is that bdrv_refresh_filename() > meddles with the result. You may have noticed that for qemu-img create, you > didn’t specify spaces in the json:{} filename, but for commit, you do need > to specify them. Or let’s take simpler example. > > $ qemu-img create -f qcow2 base.qcow2 64M > Formatting 'base.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 > lazy_refcounts=off refcount_bits=16 > $ qemu-img create -f qcow2 -b file:base.qcow2 top.qcow2 > Formatting 'top.qcow2', fmt=qcow2 size=67108864 backing_file=file:base.qcow2 > cluster_size=65536 lazy_refcounts=off refcount_bits=16 > > So the thing is that the bdrv_refresh_filename() infrastructure will compact > “file:base.qcow2” to “base.qcow2” at runtime. So, consequently, the backing > chain looks like this: > > $ qemu-img info --backing-chain top.qcow2 > image: top.qcow2 > file format: qcow2 > virtual size: 64M (67108864 bytes) > disk size: 196K > cluster_size: 65536 > backing file: file:base.qcow2 > Format specific information: > compat: 1.1 > lazy refcounts: false > refcount bits: 16 > corrupt: false > > image: base.qcow2 > file format: qcow2 > virtual size: 64M (67108864 bytes) > disk size: 196K > cluster_size: 65536 > Format specific information: > compat: 1.1 > lazy refcounts: false > refcount bits: 16 > corrupt: false > > top.qcow2’s backing file is “file:base.qcow2” (as we’ve specified), but the > actual filename of the base BDS is just “base.qcow2”. So a commit to > “file:base.qcow2” will not work, you’ll have to use “base.qcow2”: > > $ qemu-img commit -b file:base.qcow2 top.qcow2 > qemu-img: Did not find 'file:base.qcow2' in the backing chain of 'top.qcow2' > $ qemu-img commit -b base.qcow2 top.qcow2 > Image committed. > > For the QMP commands, that is (in the long term at least) not really an > issue because the fix is trivial: Just use node names instead of filenames. > However, that won’t work with qemu-img commit. A real fix would be a bit > difficult (basically impossible for arbitrary cases, but it might work for > qemu-img alone). That is fixed by this upstream series: http://lists.nongnu.org/archive/html/qemu-block/2019-04/msg00302.html Max
QEMU has been recently split into sub-components and as a one-time operation to avoid breakage of tools, we are setting the QEMU sub-component of this BZ to "General". Please review and change the sub-component if necessary the next time you review this BZ. Thanks
The filter series has been merged upstream. Max will provide more details and reproducer here before we move it to POST.
The reproducer is that from comment 2: First, create a simple backing chain: $ qemu-img create -f qcow2 base.qcow2 64M Formatting 'base.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 $ qemu-img create -f qcow2 -b file:base.qcow2 -F qcow2 top.qcow2 Formatting 'top.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=file:base.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 Query the backing chain: $ qemu-img info --backing-chain top.qcow2 image: top.qcow2 [...] backing file: file:base.qcow2 [...] image: base.qcow2 [...] So we can see that the backing file name was set as and remains "file:base.qcow2", and so that should work when specifying this image as the base for a commit operation: $ qemu-img commit -b file:base.qcow2 top.qcow2 Image committed. This is the expected result, and what you get with qemu 5.2. With older qemus (e.g. 5.1), committing will not work: $ qemu-img commit -b file:base.qcow2 top.qcow2 qemu-img: Did not find 'file:base.qcow2' in the backing chain of 'top.qcow2'
According to Comment 8, reproduced it with qemu 5.1 Versions: kernel-4.18.0-240.1.1.el8_3.x86_64 qemu-kvm-5.1.0-14.module+el8.3.0+8790+80f9c6d8.1 # qemu-img create -f qcow2 base.qcow2 64M # qemu-img create -f qcow2 -b file:base.qcow2 -F qcow2 top.qcow2 # qemu-img info --backing-chain top.qcow2 image: top.qcow2 file format: qcow2 virtual size: 64 MiB (67108864 bytes) disk size: 196 KiB cluster_size: 65536 backing file: file:base.qcow2 backing file format: qcow2 Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false image: base.qcow2 file format: qcow2 virtual size: 64 MiB (67108864 bytes) disk size: 196 KiB cluster_size: 65536 Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false # qemu-img commit -b file:base.qcow2 top.qcow2 qemu-img: Did not find 'file:base.qcow2' in the backing chain of 'top.qcow2' Tested with luks format, also could reproduce it. # qemu-img create --object secret,id=image1_encrypt0,data=redhat -f qcow2 -b 'json:{"file": {"driver": "file", "filename": "/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks"}, "driver": "luks", "key-secret": "image1_encrypt0"}' /home/kvm_autotest_root/images/sn1.qcow2 # qemu-img create --object secret,id=image1_encrypt0,data=redhat -f qcow2 -b /home/kvm_autotest_root/images/sn1.qcow2 -F qcow2 /home/kvm_autotest_root/images/sn2.qcow2 # qemu-img info --backing-chain /home/kvm_autotest_root/images/sn2.qcow2 --output=json [ { "backing-filename-format": "qcow2", "virtual-size": 21474836480, "filename": "/home/kvm_autotest_root/images/sn2.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 200704, "format-specific": { "type": "qcow2", "data": { "compat": "1.1", "compression-type": "zlib", "lazy-refcounts": false, "refcount-bits": 16, "corrupt": false } }, "full-backing-filename": "/home/kvm_autotest_root/images/sn1.qcow2", "backing-filename": "/home/kvm_autotest_root/images/sn1.qcow2", "dirty-flag": false }, { "backing-filename-format": "luks", "virtual-size": 21474836480, "filename": "/home/kvm_autotest_root/images/sn1.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 200704, "format-specific": { "type": "qcow2", "data": { "compat": "1.1", "compression-type": "zlib", "lazy-refcounts": false, "refcount-bits": 16, "corrupt": false } }, "full-backing-filename": "json:{\"file\": {\"driver\": \"file\", \"filename\": \"/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks\"}, \"driver\": \"luks\", \"key-secret\": \"image1_encrypt0\"}", "backing-filename": "json:{\"file\": {\"driver\": \"file\", \"filename\": \"/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks\"}, \"driver\": \"luks\", \"key-secret\": \"image1_encrypt0\"}", "dirty-flag": false }, { "virtual-size": 21474836480, "filename": "json:{\"driver\": \"luks\", \"file\": {\"driver\": \"file\", \"filename\": \"/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks\"}, \"key-secret\": \"image1_encrypt0\"}", "format": "luks", "actual-size": 21476904960, "format-specific": { "type": "luks", "data": { "ivgen-alg": "plain64", "hash-alg": "sha256", "cipher-alg": "aes-256", "uuid": "a68a1fba-b5a6-4c91-a9a1-d42395a30785", "cipher-mode": "xts", "slots": [ { "active": true, "iters": 1424694, "key-offset": 4096, "stripes": 4000 }, { "active": false, "key-offset": 262144 }, { "active": false, "key-offset": 520192 }, { "active": false, "key-offset": 778240 }, { "active": false, "key-offset": 1036288 }, { "active": false, "key-offset": 1294336 }, { "active": false, "key-offset": 1552384 }, { "active": false, "key-offset": 1810432 } ], "payload-offset": 2068480, "master-key-iters": 311451 } }, "encrypted": true, "dirty-flag": false } ] # qemu-img commit --object secret,id=image1_encrypt0,data=redhat -f qcow2 -b 'json:{"file": {"driver": "file", "filename": "/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks"}, "driver": "luks", "key-secret": "image1_encrypt0"}' /home/kvm_autotest_root/images/sn2.qcow2 qemu-img: Did not find 'json:{"file": {"driver": "file", "filename": "/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks"}, "driver": "luks", "key-secret": "image1_encrypt0"}' in the backing chain of '/home/kvm_autotest_root/images/sn2.qcow2' Retested with qemu-kvm-5.2.0-1.module+el8.4.0+9091+650b220a, not hit this issue. Versions: kernel-4.18.0-260.el8.x86_64 qemu-kvm-5.2.0-1.module+el8.4.0+9091+650b220a # qemu-img create -f qcow2 base.qcow2 64M # qemu-img create -f qcow2 -b file:base.qcow2 -F qcow2 top.qcow2 # qemu-img info --backing-chain top.qcow2 image: top.qcow2 file format: qcow2 virtual size: 64 MiB (67108864 bytes) disk size: 196 KiB cluster_size: 65536 backing file: file:base.qcow2 backing file format: qcow2 Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false extended l2: false image: base.qcow2 file format: qcow2 virtual size: 64 MiB (67108864 bytes) disk size: 196 KiB cluster_size: 65536 Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false extended l2: false # qemu-img commit -b file:base.qcow2 top.qcow2 Image committed. Tested with luks format, it also works well. # qemu-img create --object secret,id=image1_encrypt0,data=redhat -f qcow2 -b 'json:{"file": {"driver": "file", "filename": "/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks"}, "driver": "luks", "key-secret": "image1_encrypt0"}' /home/kvm_autotest_root/images/sn1.qcow2 # qemu-img create --object secret,id=image1_encrypt0,data=redhat -f qcow2 -b /home/kvm_autotest_root/images/sn1.qcow2 -F qcow2 /home/kvm_autotest_root/images/sn2.qcow2 # qemu-img info --backing-chain /home/kvm_autotest_root/images/sn2.qcow2 --output=json [ { "backing-filename-format": "qcow2", "virtual-size": 21474836480, "filename": "/home/kvm_autotest_root/images/sn2.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 45481984, "format-specific": { "type": "qcow2", "data": { "compat": "1.1", "compression-type": "zlib", "lazy-refcounts": false, "refcount-bits": 16, "corrupt": false, "extended-l2": false } }, "full-backing-filename": "/home/kvm_autotest_root/images/sn1.qcow2", "backing-filename": "/home/kvm_autotest_root/images/sn1.qcow2", "dirty-flag": false }, { "backing-filename-format": "luks", "virtual-size": 21474836480, "filename": "/home/kvm_autotest_root/images/sn1.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 45678592, "format-specific": { "type": "qcow2", "data": { "compat": "1.1", "compression-type": "zlib", "lazy-refcounts": false, "refcount-bits": 16, "corrupt": false, "extended-l2": false } }, "full-backing-filename": "json:{\"file\": {\"driver\": \"file\", \"filename\": \"/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks\"}, \"driver\": \"luks\", \"key-secret\": \"image1_encrypt0\"}", "backing-filename": "json:{\"file\": {\"driver\": \"file\", \"filename\": \"/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks\"}, \"driver\": \"luks\", \"key-secret\": \"image1_encrypt0\"}", "dirty-flag": false }, { "virtual-size": 21474836480, "filename": "json:{\"driver\": \"luks\", \"file\": {\"driver\": \"file\", \"filename\": \"/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks\"}, \"key-secret\": \"image1_encrypt0\"}", "format": "luks", "actual-size": 21476904960, "format-specific": { "type": "luks", "data": { "ivgen-alg": "plain64", "hash-alg": "sha256", "cipher-alg": "aes-256", "uuid": "a68a1fba-b5a6-4c91-a9a1-d42395a30785", "cipher-mode": "xts", "slots": [ { "active": true, "iters": 1424694, "key-offset": 4096, "stripes": 4000 }, { "active": false, "key-offset": 262144 }, { "active": false, "key-offset": 520192 }, { "active": false, "key-offset": 778240 }, { "active": false, "key-offset": 1036288 }, { "active": false, "key-offset": 1294336 }, { "active": false, "key-offset": 1552384 }, { "active": false, "key-offset": 1810432 } ], "payload-offset": 2068480, "master-key-iters": 311451 } }, "encrypted": true, "dirty-flag": false } ] # qemu-img commit --object secret,id=image1_encrypt0,data=redhat -f qcow2 -b 'json:{"file": {"driver": "file", "filename": "/home/kvm_autotest_root/images/rhel840-64-virtio-scsi.luks"}, "driver": "luks", "key-secret": "image1_encrypt0"}' /home/kvm_autotest_root/images/sn2.qcow2 Image committed.
According to Comment 9, set status to VERIFIED.
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory (virt:av bug fix and enhancement update), and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2021:2098