mirror of https://github.com/xemu-project/xemu.git
Add host_device support to qemu-img. (Nolan Leake)
This patch allows the use a host_device as the destination for "qemu-img convert". I added a ->bdrv_create function host_device. It merely verifies that the device exists and is large enough. A check is needed in the qemu-img convert loop to ensure that we write out all 0 sectors to the host_device. Otherwise they end up with stale garbage where all zero sectors were expected. I also made the check against bdrv_is_allocated enabled for everything _except_ host devices, since there is no point in making the block backend write a bunch of zeros just so that we can memcmp them immediately afterwards. Host devices can't benefit from this because there is no way to differentiate between a sector being unallocated because it was never written, or because it was written with all zeros and then made a trip through qemu-img convert. Finally, there is an unrelated fix for a typo in the error message printed if the destination device does not support ->bdrv_create. Signed-off-by: Nolan Leake <nolan <at> sigbus.net> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6978 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
f8de16605c
commit
93c65b47a6
|
@ -1378,11 +1378,47 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
|
||||||
}
|
}
|
||||||
#endif /* !linux && !FreeBSD */
|
#endif /* !linux && !FreeBSD */
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
|
static int hdev_create(const char *filename, int64_t total_size,
|
||||||
|
const char *backing_file, int flags)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int ret = 0;
|
||||||
|
struct stat stat_buf;
|
||||||
|
|
||||||
|
if (flags || backing_file)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
fd = open(filename, O_WRONLY | O_BINARY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (fstat(fd, &stat_buf) < 0)
|
||||||
|
ret = -EIO;
|
||||||
|
else if (!S_ISBLK(stat_buf.st_mode))
|
||||||
|
ret = -EIO;
|
||||||
|
else if (lseek(fd, 0, SEEK_END) < total_size * 512)
|
||||||
|
ret = -ENOSPC;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !(linux || freebsd) */
|
||||||
|
|
||||||
|
static int hdev_create(const char *filename, int64_t total_size,
|
||||||
|
const char *backing_file, int flags)
|
||||||
|
{
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BlockDriver bdrv_host_device = {
|
BlockDriver bdrv_host_device = {
|
||||||
.format_name = "host_device",
|
.format_name = "host_device",
|
||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_open = hdev_open,
|
.bdrv_open = hdev_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
|
.bdrv_create = hdev_create,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
#ifdef CONFIG_AIO
|
#ifdef CONFIG_AIO
|
||||||
|
|
34
qemu-img.c
34
qemu-img.c
|
@ -493,7 +493,7 @@ static int img_convert(int argc, char **argv)
|
||||||
ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
|
ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == -ENOTSUP) {
|
if (ret == -ENOTSUP) {
|
||||||
error("Formatting not supported for file format '%s'", fmt);
|
error("Formatting not supported for file format '%s'", out_fmt);
|
||||||
} else {
|
} else {
|
||||||
error("Error while formatting '%s'", out_filename);
|
error("Error while formatting '%s'", out_filename);
|
||||||
}
|
}
|
||||||
|
@ -592,18 +592,17 @@ static int img_convert(int argc, char **argv)
|
||||||
if (n > bs_offset + bs_sectors - sector_num)
|
if (n > bs_offset + bs_sectors - sector_num)
|
||||||
n = bs_offset + bs_sectors - sector_num;
|
n = bs_offset + bs_sectors - sector_num;
|
||||||
|
|
||||||
/* If the output image is being created as a copy on write image,
|
if (drv != &bdrv_host_device) {
|
||||||
assume that sectors which are unallocated in the input image
|
if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
|
||||||
are present in both the output's and input's base images (no
|
n, &n1)) {
|
||||||
need to copy them). */
|
sector_num += n1;
|
||||||
if (out_baseimg) {
|
continue;
|
||||||
if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, n, &n1)) {
|
}
|
||||||
sector_num += n1;
|
/* The next 'n1' sectors are allocated in the input image. Copy
|
||||||
continue;
|
only those as they may be followed by unallocated sectors. */
|
||||||
}
|
n = n1;
|
||||||
/* The next 'n1' sectors are allocated in the input image. Copy
|
} else {
|
||||||
only those as they may be followed by unallocated sectors. */
|
n1 = n;
|
||||||
n = n1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
|
if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
|
||||||
|
@ -615,8 +614,13 @@ static int img_convert(int argc, char **argv)
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
/* If the output image is being created as a copy on write image,
|
/* If the output image is being created as a copy on write image,
|
||||||
copy all sectors even the ones containing only NUL bytes,
|
copy all sectors even the ones containing only NUL bytes,
|
||||||
because they may differ from the sectors in the base image. */
|
because they may differ from the sectors in the base image.
|
||||||
if (out_baseimg || is_allocated_sectors(buf1, n, &n1)) {
|
|
||||||
|
If the output is to a host device, we also write out
|
||||||
|
sectors that are entirely 0, since whatever data was
|
||||||
|
already there is garbage, not 0s. */
|
||||||
|
if (drv == &bdrv_host_device || out_baseimg ||
|
||||||
|
is_allocated_sectors(buf1, n, &n1)) {
|
||||||
if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
|
if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
|
||||||
error("error while writing");
|
error("error while writing");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue