Commit 93c65b47a6fb9ba0e2b89269a751ba3433a33427

Authored by aliguori
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 }
... ...