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 | } | ... | ... |