duxsco
duxsco

Reputation: 361

How large is the qcow2 header?

My raw VM images are currently stored within a LUKS encrypted file (e.g. /var/lib/libvirt/images/win7.img) and accessed the following way using libvirt:

<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/mapper/win7.img'/>
  <target dev='vda' bus='virtio'/>
</disk>

I back them up with the help of btrfs's snapshot functionality:

# sample backup procedure
IMG_PATH="/var/lib/libvirt/images"
virsh shutdown win7
cryptsetup luksClose /dev/mapper/win7.img
DATE=$(date --utc +%Y-%m-%d-%H%M%S)
btrfs subvolume snapshot -r ${IMG_PATH}/ ${IMG_PATH}/${DATE}
cryptsetup luksOpen --key-file /root/libvirt.key ${IMG_PATH}/win7.img
virsh start win7
btrfs send ${IMG_PATH}/${DATE} | btrfs receive /mnt/backup/images/

# subsequent backup
virsh shutdown win7
cryptsetup luksClose /dev/mapper/win7.img
NEW_DATE=$(date --utc +%Y-%m-%d-%H%M%S)
btrfs subvolume snapshot -r ${IMG_PATH}/ ${IMG_PATH}/${NEW_DATE}
cryptsetup luksOpen --key-file /root/libvirt.key ${IMG_PATH}/win7.img
virsh start win7
btrfs send -p ${IMG_PATH}/${DATE} ${IMG_PATH}/${NEW_DATE} | btrfs receive /mnt/backup/images/
btrfs subvolume delete ${IMG_PATH}/${DATE}

Now, I intend to save some space by converting the raw images to compressed qcow2:

# create a sparse and LUKS encrypted image
# the LUKS header is 2 MiB large
# therefore "seek=51202" instead of "seek=51200" for a 50 GiB virtual disk
IMG_PATH="/var/lib/libvirt/images"
dd bs=1048576 count=0 seek=51202 if=/dev/zero of=${IMG_PATH}/win7_new.img
cryptsetup luksFormat -c aes-xts-plain -h sha512 -s 512 ${IMG_PATH}/win7_new.img
cryptsetup luksAddKey ${IMG_PATH}/win7_new.img /root/libvirt.key
cryptsetup luksOpen --key-file /root/libvirt.key ${IMG_PATH}/win7_new.img win7_new.img

# copy the content from the old image to the new compressed image and delete the old one
qemu-img convert -f raw -O qcow2 -c /dev/mapper/win7.img /dev/mapper/win7_new.img
cryptsetup luksClose /dev/mapper/win7.img
cryptsetup luksClose /dev/mapper/win7_new.img
rm -f ${IMG_PATH}/win7.img
mv ${IMG_PATH}/win7_new.img ${IMG_PATH}/win7.img

The new libvirt xml code is as follows:

<disk type='block' device='disk'>
  <driver name='qemu' type='qcow2'/>
  <source dev='/dev/mapper/win7.img'/>
  <target dev='vda' bus='virtio'/>
</disk>

My question: I know the LUKS header size "256 bits equals a total header size of 1'052'672 Bytes and 512 bits one of 2MiB." (6.2 How do I backup a LUKS header?), but couldn't find any solid information on the qcow2 header size. Is it fixed or does it depend on the virtual disk size? How large is the qcow2 header?

Upvotes: 1

Views: 898

Answers (1)

DanielB
DanielB

Reputation: 2816

The qcow2 header is 1 cluster in size, and the default cluster size is 64kb, but on top of that you need to add in the variable sized L1 and L2 tables, and cluster refcount tables, whose size depends on the virtual image size. When doing preallocation even the qcow2 code does not calculate the exact size required - it does a close approximation as the true calculation is quite hard. The upshot is that there's no real good way to get an exact figure. Best bet is to just determine overhead by doing a prealloc test with your largest expected image size. eg say you expect the largest image to be 20 GB in size,

$ qemu-img create -f qcow2 -o preallocation=falloc demo.img 20G

Formatting 'demo.img', fmt=qcow2 size=21474836480 encryption=off cluster_size=65536 preallocation=falloc lazy_refcounts=off refcount_bits=16

$ ls -al demo.img -rw-r--r--. 1 berrange berrange 21478375424 Dec 21 23:11 demo.img

21478375424-21474836480 == 3538944

So, a 20 GB image has approx 3.5 MB of overhead in qcow2.

Upvotes: 0

Related Questions