On the other hand, I think the starting point for a generic in-place
converter would be a loop that does something like bdrv_is_allocated()
but translates the guest position in the block device into an offset
into the image file. That, together with some sort of free map or
space allocation bitmap would allow a generic approach to figuring out
the data mapping and which parts of the file can be safely used.
We can discuss the detailed API later, but I agree that the critical
thing to convert is the mapping.
You would probably open the file with the source format driver read-only
and with the destination driver read-write. For qcow2 you would start
with writing a refcount table that marks the whole file as used, other
formats use the file size anyway. Then you can start creating L1 and L2
tables and copy the mapping over. Once this is done, you do an fsck to
free the metadata of the old format.
One thing that may become tricky is the image header which both drivers
may want to use and which is fixed at offset 0. And of course, you must
make sure that the image is safe at any point if the converter crashes.
For image header issue, this is the approach that comes to mind.
Lets say, destination format is qcow2.
BDRVQcowState is responsible for header fields inside BlockDriverState.
We need qcow2 image header to initiliaze all the fields of
BDRVQcowState, which is done by bdrv_open(qcow2_open()).
So initially, for the qcow2 driver, we do not copy the qcow2 image
header (we keep the source header). We can then manually set fields of
BDRVQcowState with the desired header fields.
And after all other metadata has been copied for the qcow2 format, we
can replace the source image header with the qcow2 header.
Thanks,
Dushyant