Commit 93c65b47a6fb9ba0e2b89269a751ba3433a33427
1 parent
f8de1660
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
Showing
2 changed files
with
55 additions
and
15 deletions
block-raw-posix.c
... | ... | @@ -1378,11 +1378,47 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, |
1378 | 1378 | } |
1379 | 1379 | #endif /* !linux && !FreeBSD */ |
1380 | 1380 | |
1381 | +#if defined(__linux__) || defined(__FreeBSD__) | |
1382 | +static int hdev_create(const char *filename, int64_t total_size, | |
1383 | + const char *backing_file, int flags) | |
1384 | +{ | |
1385 | + int fd; | |
1386 | + int ret = 0; | |
1387 | + struct stat stat_buf; | |
1388 | + | |
1389 | + if (flags || backing_file) | |
1390 | + return -ENOTSUP; | |
1391 | + | |
1392 | + fd = open(filename, O_WRONLY | O_BINARY); | |
1393 | + if (fd < 0) | |
1394 | + return -EIO; | |
1395 | + | |
1396 | + if (fstat(fd, &stat_buf) < 0) | |
1397 | + ret = -EIO; | |
1398 | + else if (!S_ISBLK(stat_buf.st_mode)) | |
1399 | + ret = -EIO; | |
1400 | + else if (lseek(fd, 0, SEEK_END) < total_size * 512) | |
1401 | + ret = -ENOSPC; | |
1402 | + | |
1403 | + close(fd); | |
1404 | + return ret; | |
1405 | +} | |
1406 | + | |
1407 | +#else /* !(linux || freebsd) */ | |
1408 | + | |
1409 | +static int hdev_create(const char *filename, int64_t total_size, | |
1410 | + const char *backing_file, int flags) | |
1411 | +{ | |
1412 | + return -ENOTSUP; | |
1413 | +} | |
1414 | +#endif | |
1415 | + | |
1381 | 1416 | BlockDriver bdrv_host_device = { |
1382 | 1417 | .format_name = "host_device", |
1383 | 1418 | .instance_size = sizeof(BDRVRawState), |
1384 | 1419 | .bdrv_open = hdev_open, |
1385 | 1420 | .bdrv_close = raw_close, |
1421 | + .bdrv_create = hdev_create, | |
1386 | 1422 | .bdrv_flush = raw_flush, |
1387 | 1423 | |
1388 | 1424 | #ifdef CONFIG_AIO | ... | ... |
qemu-img.c
... | ... | @@ -493,7 +493,7 @@ static int img_convert(int argc, char **argv) |
493 | 493 | ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags); |
494 | 494 | if (ret < 0) { |
495 | 495 | if (ret == -ENOTSUP) { |
496 | - error("Formatting not supported for file format '%s'", fmt); | |
496 | + error("Formatting not supported for file format '%s'", out_fmt); | |
497 | 497 | } else { |
498 | 498 | error("Error while formatting '%s'", out_filename); |
499 | 499 | } |
... | ... | @@ -592,18 +592,17 @@ static int img_convert(int argc, char **argv) |
592 | 592 | if (n > bs_offset + bs_sectors - sector_num) |
593 | 593 | n = bs_offset + bs_sectors - sector_num; |
594 | 594 | |
595 | - /* If the output image is being created as a copy on write image, | |
596 | - assume that sectors which are unallocated in the input image | |
597 | - are present in both the output's and input's base images (no | |
598 | - need to copy them). */ | |
599 | - if (out_baseimg) { | |
600 | - if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, n, &n1)) { | |
601 | - sector_num += n1; | |
602 | - continue; | |
603 | - } | |
604 | - /* The next 'n1' sectors are allocated in the input image. Copy | |
605 | - only those as they may be followed by unallocated sectors. */ | |
606 | - n = n1; | |
595 | + if (drv != &bdrv_host_device) { | |
596 | + if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, | |
597 | + n, &n1)) { | |
598 | + sector_num += n1; | |
599 | + continue; | |
600 | + } | |
601 | + /* The next 'n1' sectors are allocated in the input image. Copy | |
602 | + only those as they may be followed by unallocated sectors. */ | |
603 | + n = n1; | |
604 | + } else { | |
605 | + n1 = n; | |
607 | 606 | } |
608 | 607 | |
609 | 608 | 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) |
615 | 614 | while (n > 0) { |
616 | 615 | /* If the output image is being created as a copy on write image, |
617 | 616 | copy all sectors even the ones containing only NUL bytes, |
618 | - because they may differ from the sectors in the base image. */ | |
619 | - if (out_baseimg || is_allocated_sectors(buf1, n, &n1)) { | |
617 | + because they may differ from the sectors in the base image. | |
618 | + | |
619 | + If the output is to a host device, we also write out | |
620 | + sectors that are entirely 0, since whatever data was | |
621 | + already there is garbage, not 0s. */ | |
622 | + if (drv == &bdrv_host_device || out_baseimg || | |
623 | + is_allocated_sectors(buf1, n, &n1)) { | |
620 | 624 | if (bdrv_write(out_bs, sector_num, buf1, n1) < 0) |
621 | 625 | error("error while writing"); |
622 | 626 | } | ... | ... |