When open the vpc snapshot based FIXED format, its backing file, this FIXED vpc image, could be probed as a raw image, because that the find_image_format just checkout the first sector.
Add a re-probe for the last sector to FIXED base vpc image,when get a NULL or raw driver in first sector probe. Signed-off-by: Xiaodong Gong <gongxiaodo...@huawei.com> --- block.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/block.c b/block.c index d45e4dd..e183515 100644 --- a/block.c +++ b/block.c @@ -702,20 +702,24 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, return drv; } -static int find_image_format(BlockDriverState *bs, const char *filename, - BlockDriver **pdrv, Error **errp) +static int probe_image_format(BlockDriverState *bs, const char *filename, + int64_t offset, BlockDriver **pdrv, Error **errp, + bool isfoot) { BlockDriver *drv; uint8_t buf[BLOCK_PROBE_BUF_SIZE]; int ret = 0; - /* Return the raw BlockDriver * to scsi-generic devices or empty drives */ - if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { - *pdrv = &bdrv_raw; + if (!bs || !filename) { + *pdrv = NULL; return ret; } - ret = bdrv_pread(bs, 0, buf, sizeof(buf)); + if (offset + sizeof(buf) > bs->total_sectors << BDRV_SECTOR_BITS) { + return ret; + } + + ret = bdrv_pread(bs, offset, buf, sizeof(buf)); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read image for determining its " "format"); @@ -724,12 +728,49 @@ static int find_image_format(BlockDriverState *bs, const char *filename, } drv = bdrv_probe_all(buf, ret, filename); - if (!drv) { + if (!drv && isfoot) { error_setg(errp, "Could not determine image format: No compatible " "driver found"); ret = -ENOENT; } *pdrv = drv; + + return ret; +} + +static int find_image_format(BlockDriverState *bs, const char *filename, + BlockDriver **pdrv, Error **errp) +{ + int last_sector_offset; + int ret = 0; + + *pdrv = NULL; + + /* Return the raw BlockDriver * to scsi-generic devices or empty drives */ + if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { + *pdrv = &bdrv_raw; + return ret; + } + + /* probe the header to guess image format */ + ret = probe_image_format(bs, filename, 0, pdrv, errp, false); + if (ret < 0) { + return ret; + } + + /* The FIXED base img of VHD only has the footer in tail. The drv could + * be NULL or raw */ + if (*pdrv && *pdrv != &bdrv_raw) { + return ret; + } + + last_sector_offset = (bs->total_sectors - 1) << BDRV_SECTOR_BITS; + ret = probe_image_format(bs, filename, last_sector_offset, pdrv, + errp, true); + if (ret < 0) { + return ret; + } + return ret; } -- 1.8.3.1