aboutsummaryrefslogtreecommitdiff
path: root/qemu-img.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu-img.c')
-rw-r--r--qemu-img.c208
1 files changed, 99 insertions, 109 deletions
diff --git a/qemu-img.c b/qemu-img.c
index e148af8a3e..0155e36283 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -261,6 +261,7 @@ static int print_block_option_help(const char *filename, const char *fmt)
{
BlockDriver *drv, *proto_drv;
QemuOptsList *create_opts = NULL;
+ Error *local_err = NULL;
/* Find driver and parse its options */
drv = bdrv_find_format(fmt);
@@ -271,9 +272,10 @@ static int print_block_option_help(const char *filename, const char *fmt)
create_opts = qemu_opts_append(create_opts, drv->create_opts);
if (filename) {
- proto_drv = bdrv_find_protocol(filename, true);
+ proto_drv = bdrv_find_protocol(filename, true, &local_err);
if (!proto_drv) {
- error_report("Unknown protocol '%s'", filename);
+ qerror_report_err(local_err);
+ error_free(local_err);
qemu_opts_free(create_opts);
return 1;
}
@@ -291,32 +293,24 @@ static BlockBackend *img_open(const char *id, const char *filename,
{
BlockBackend *blk;
BlockDriverState *bs;
- BlockDriver *drv;
char password[256];
Error *local_err = NULL;
- int ret;
-
- blk = blk_new_with_bs(id, &error_abort);
- bs = blk_bs(blk);
+ QDict *options = NULL;
if (fmt) {
- drv = bdrv_find_format(fmt);
- if (!drv) {
- error_report("Unknown file format '%s'", fmt);
- goto fail;
- }
- } else {
- drv = NULL;
+ options = qdict_new();
+ qdict_put(options, "driver", qstring_from_str(fmt));
}
- ret = bdrv_open(&bs, filename, NULL, NULL, flags, drv, &local_err);
- if (ret < 0) {
+ blk = blk_new_open(id, filename, NULL, options, flags, &local_err);
+ if (!blk) {
error_report("Could not open '%s': %s", filename,
error_get_pretty(local_err));
error_free(local_err);
goto fail;
}
+ bs = blk_bs(blk);
if (bdrv_is_encrypted(bs) && require_io) {
qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
if (read_password(password, sizeof(password)) < 0) {
@@ -1016,19 +1010,19 @@ static int64_t sectors_to_process(int64_t total, int64_t from)
* Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
* data and negative value on error.
*
- * @param bs: Driver used for accessing file
+ * @param blk: BlockBackend for the image
* @param sect_num: Number of first sector to check
* @param sect_count: Number of sectors to check
* @param filename: Name of disk file we are checking (logging purpose)
* @param buffer: Allocated buffer for storing read data
* @param quiet: Flag for quiet mode
*/
-static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
+static int check_empty_sectors(BlockBackend *blk, int64_t sect_num,
int sect_count, const char *filename,
uint8_t *buffer, bool quiet)
{
int pnum, ret = 0;
- ret = bdrv_read(bs, sect_num, buffer, sect_count);
+ ret = blk_read(blk, sect_num, buffer, sect_count);
if (ret < 0) {
error_report("Error while reading offset %" PRId64 " of %s: %s",
sectors_to_bytes(sect_num), filename, strerror(-ret));
@@ -1138,16 +1132,16 @@ static int img_compare(int argc, char **argv)
}
bs2 = blk_bs(blk2);
- buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
- buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
- total_sectors1 = bdrv_nb_sectors(bs1);
+ buf1 = blk_blockalign(blk1, IO_BUF_SIZE);
+ buf2 = blk_blockalign(blk2, IO_BUF_SIZE);
+ total_sectors1 = blk_nb_sectors(blk1);
if (total_sectors1 < 0) {
error_report("Can't get size of %s: %s",
filename1, strerror(-total_sectors1));
ret = 4;
goto out;
}
- total_sectors2 = bdrv_nb_sectors(bs2);
+ total_sectors2 = blk_nb_sectors(blk2);
if (total_sectors2 < 0) {
error_report("Can't get size of %s: %s",
filename2, strerror(-total_sectors2));
@@ -1189,7 +1183,7 @@ static int img_compare(int argc, char **argv)
if (allocated1 == allocated2) {
if (allocated1) {
- ret = bdrv_read(bs1, sector_num, buf1, nb_sectors);
+ ret = blk_read(blk1, sector_num, buf1, nb_sectors);
if (ret < 0) {
error_report("Error while reading offset %" PRId64 " of %s:"
" %s", sectors_to_bytes(sector_num), filename1,
@@ -1197,7 +1191,7 @@ static int img_compare(int argc, char **argv)
ret = 4;
goto out;
}
- ret = bdrv_read(bs2, sector_num, buf2, nb_sectors);
+ ret = blk_read(blk2, sector_num, buf2, nb_sectors);
if (ret < 0) {
error_report("Error while reading offset %" PRId64
" of %s: %s", sectors_to_bytes(sector_num),
@@ -1224,10 +1218,10 @@ static int img_compare(int argc, char **argv)
}
if (allocated1) {
- ret = check_empty_sectors(bs1, sector_num, nb_sectors,
+ ret = check_empty_sectors(blk1, sector_num, nb_sectors,
filename1, buf1, quiet);
} else {
- ret = check_empty_sectors(bs2, sector_num, nb_sectors,
+ ret = check_empty_sectors(blk2, sector_num, nb_sectors,
filename2, buf1, quiet);
}
if (ret) {
@@ -1244,18 +1238,18 @@ static int img_compare(int argc, char **argv)
}
if (total_sectors1 != total_sectors2) {
- BlockDriverState *bs_over;
+ BlockBackend *blk_over;
int64_t total_sectors_over;
const char *filename_over;
qprintf(quiet, "Warning: Image size mismatch!\n");
if (total_sectors1 > total_sectors2) {
total_sectors_over = total_sectors1;
- bs_over = bs1;
+ blk_over = blk1;
filename_over = filename1;
} else {
total_sectors_over = total_sectors2;
- bs_over = bs2;
+ blk_over = blk2;
filename_over = filename2;
}
@@ -1264,7 +1258,7 @@ static int img_compare(int argc, char **argv)
if (nb_sectors <= 0) {
break;
}
- ret = bdrv_is_allocated_above(bs_over, NULL, sector_num,
+ ret = bdrv_is_allocated_above(blk_bs(blk_over), NULL, sector_num,
nb_sectors, &pnum);
if (ret < 0) {
ret = 3;
@@ -1275,7 +1269,7 @@ static int img_compare(int argc, char **argv)
}
nb_sectors = pnum;
if (ret) {
- ret = check_empty_sectors(bs_over, sector_num, nb_sectors,
+ ret = check_empty_sectors(blk_over, sector_num, nb_sectors,
filename_over, buf1, quiet);
if (ret) {
if (ret < 0) {
@@ -1484,7 +1478,7 @@ static int img_convert(int argc, char **argv)
goto out;
}
bs[bs_i] = blk_bs(blk[bs_i]);
- bs_sectors[bs_i] = bdrv_nb_sectors(bs[bs_i]);
+ bs_sectors[bs_i] = blk_nb_sectors(blk[bs_i]);
if (bs_sectors[bs_i] < 0) {
error_report("Could not get size of %s: %s",
argv[optind + bs_i], strerror(-bs_sectors[bs_i]));
@@ -1524,41 +1518,44 @@ static int img_convert(int argc, char **argv)
goto out;
}
- proto_drv = bdrv_find_protocol(out_filename, true);
+ proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
if (!proto_drv) {
- error_report("Unknown protocol '%s'", out_filename);
+ qerror_report_err(local_err);
+ error_free(local_err);
ret = -1;
goto out;
}
- if (!drv->create_opts) {
- error_report("Format driver '%s' does not support image creation",
- drv->format_name);
- ret = -1;
- goto out;
- }
+ if (!skip_create) {
+ if (!drv->create_opts) {
+ error_report("Format driver '%s' does not support image creation",
+ drv->format_name);
+ ret = -1;
+ goto out;
+ }
- if (!proto_drv->create_opts) {
- error_report("Protocol driver '%s' does not support image creation",
- proto_drv->format_name);
- ret = -1;
- goto out;
- }
+ if (!proto_drv->create_opts) {
+ error_report("Protocol driver '%s' does not support image creation",
+ proto_drv->format_name);
+ ret = -1;
+ goto out;
+ }
- create_opts = qemu_opts_append(create_opts, drv->create_opts);
- create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
+ create_opts = qemu_opts_append(create_opts, drv->create_opts);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
- opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
- if (options && qemu_opts_do_parse(opts, options, NULL)) {
- error_report("Invalid options for file format '%s'", out_fmt);
- ret = -1;
- goto out;
- }
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
+ error_report("Invalid options for file format '%s'", out_fmt);
+ ret = -1;
+ goto out;
+ }
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
- ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
- if (ret < 0) {
- goto out;
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
+ ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
+ if (ret < 0) {
+ goto out;
+ }
}
/* Get backing file name if -o backing_file was used */
@@ -1633,10 +1630,10 @@ static int img_convert(int argc, char **argv)
out_bs->bl.discard_alignment))
);
- buf = qemu_blockalign(out_bs, bufsectors * BDRV_SECTOR_SIZE);
+ buf = blk_blockalign(out_blk, bufsectors * BDRV_SECTOR_SIZE);
if (skip_create) {
- int64_t output_sectors = bdrv_nb_sectors(out_bs);
+ int64_t output_sectors = blk_nb_sectors(out_blk);
if (output_sectors < 0) {
error_report("unable to get output image length: %s\n",
strerror(-output_sectors));
@@ -1704,7 +1701,7 @@ static int img_convert(int argc, char **argv)
nlow = remainder > bs_sectors[bs_i] - bs_num
? bs_sectors[bs_i] - bs_num : remainder;
- ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
+ ret = blk_read(blk[bs_i], bs_num, buf2, nlow);
if (ret < 0) {
error_report("error while reading sector %" PRId64 ": %s",
bs_num, strerror(-ret));
@@ -1719,7 +1716,7 @@ static int img_convert(int argc, char **argv)
assert (remainder == 0);
if (!buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)) {
- ret = bdrv_write_compressed(out_bs, sector_num, buf, n);
+ ret = blk_write_compressed(out_blk, sector_num, buf, n);
if (ret != 0) {
error_report("error while compressing sector %" PRId64
": %s", sector_num, strerror(-ret));
@@ -1730,7 +1727,7 @@ static int img_convert(int argc, char **argv)
qemu_progress_print(100.0 * sector_num / total_sectors, 0);
}
/* signal EOF to align */
- bdrv_write_compressed(out_bs, 0, NULL, 0);
+ blk_write_compressed(out_blk, 0, NULL, 0);
} else {
int64_t sectors_to_read, sectors_read, sector_num_next_status;
bool count_allocated_sectors;
@@ -1831,7 +1828,7 @@ restart:
}
n1 = n;
- ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
+ ret = blk_read(blk[bs_i], sector_num - bs_offset, buf, n);
if (ret < 0) {
error_report("error while reading sector %" PRId64 ": %s",
sector_num - bs_offset, strerror(-ret));
@@ -1844,7 +1841,7 @@ restart:
while (n > 0) {
if (!has_zero_init ||
is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
- ret = bdrv_write(out_bs, sector_num, buf1, n1);
+ ret = blk_write(out_blk, sector_num, buf1, n1);
if (ret < 0) {
error_report("error while writing sector %" PRId64
": %s", sector_num, strerror(-ret));
@@ -2268,7 +2265,7 @@ static int img_map(int argc, char **argv)
printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
}
- length = bdrv_getlength(bs);
+ length = blk_getlength(blk);
while (curr.start + curr.length < length) {
int64_t nsectors_left;
int64_t sector_num;
@@ -2437,8 +2434,7 @@ static int img_snapshot(int argc, char **argv)
static int img_rebase(int argc, char **argv)
{
BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
- BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
- BlockDriver *old_backing_drv, *new_backing_drv;
+ BlockDriverState *bs = NULL;
char *filename;
const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg;
int c, flags, src_flags, ret;
@@ -2532,22 +2528,8 @@ static int img_rebase(int argc, char **argv)
}
bs = blk_bs(blk);
- /* Find the right drivers for the backing files */
- old_backing_drv = NULL;
- new_backing_drv = NULL;
-
- if (!unsafe && bs->backing_format[0] != '\0') {
- old_backing_drv = bdrv_find_format(bs->backing_format);
- if (old_backing_drv == NULL) {
- error_report("Invalid format name: '%s'", bs->backing_format);
- ret = -1;
- goto out;
- }
- }
-
if (out_basefmt != NULL) {
- new_backing_drv = bdrv_find_format(out_basefmt);
- if (new_backing_drv == NULL) {
+ if (bdrv_find_format(out_basefmt) == NULL) {
error_report("Invalid format name: '%s'", out_basefmt);
ret = -1;
goto out;
@@ -2557,24 +2539,34 @@ static int img_rebase(int argc, char **argv)
/* For safe rebasing we need to compare old and new backing file */
if (!unsafe) {
char backing_name[PATH_MAX];
+ QDict *options = NULL;
+
+ if (bs->backing_format[0] != '\0') {
+ options = qdict_new();
+ qdict_put(options, "driver", qstring_from_str(bs->backing_format));
+ }
- blk_old_backing = blk_new_with_bs("old_backing", &error_abort);
- bs_old_backing = blk_bs(blk_old_backing);
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
- ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
- old_backing_drv, &local_err);
- if (ret) {
+ blk_old_backing = blk_new_open("old_backing", backing_name, NULL,
+ options, src_flags, &local_err);
+ if (!blk_old_backing) {
error_report("Could not open old backing file '%s': %s",
backing_name, error_get_pretty(local_err));
error_free(local_err);
goto out;
}
+
if (out_baseimg[0]) {
- blk_new_backing = blk_new_with_bs("new_backing", &error_abort);
- bs_new_backing = blk_bs(blk_new_backing);
- ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
- new_backing_drv, &local_err);
- if (ret) {
+ if (out_basefmt) {
+ options = qdict_new();
+ qdict_put(options, "driver", qstring_from_str(out_basefmt));
+ } else {
+ options = NULL;
+ }
+
+ blk_new_backing = blk_new_open("new_backing", out_baseimg, NULL,
+ options, src_flags, &local_err);
+ if (!blk_new_backing) {
error_report("Could not open new backing file '%s': %s",
out_baseimg, error_get_pretty(local_err));
error_free(local_err);
@@ -2602,17 +2594,17 @@ static int img_rebase(int argc, char **argv)
uint8_t * buf_new;
float local_progress = 0;
- buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
- buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
+ buf_old = blk_blockalign(blk, IO_BUF_SIZE);
+ buf_new = blk_blockalign(blk, IO_BUF_SIZE);
- num_sectors = bdrv_nb_sectors(bs);
+ num_sectors = blk_nb_sectors(blk);
if (num_sectors < 0) {
error_report("Could not get size of '%s': %s",
filename, strerror(-num_sectors));
ret = -1;
goto out;
}
- old_backing_num_sectors = bdrv_nb_sectors(bs_old_backing);
+ old_backing_num_sectors = blk_nb_sectors(blk_old_backing);
if (old_backing_num_sectors < 0) {
char backing_name[PATH_MAX];
@@ -2622,8 +2614,8 @@ static int img_rebase(int argc, char **argv)
ret = -1;
goto out;
}
- if (bs_new_backing) {
- new_backing_num_sectors = bdrv_nb_sectors(bs_new_backing);
+ if (blk_new_backing) {
+ new_backing_num_sectors = blk_nb_sectors(blk_new_backing);
if (new_backing_num_sectors < 0) {
error_report("Could not get size of '%s': %s",
out_baseimg, strerror(-new_backing_num_sectors));
@@ -2668,21 +2660,21 @@ static int img_rebase(int argc, char **argv)
n = old_backing_num_sectors - sector;
}
- ret = bdrv_read(bs_old_backing, sector, buf_old, n);
+ ret = blk_read(blk_old_backing, sector, buf_old, n);
if (ret < 0) {
error_report("error while reading from old backing file");
goto out;
}
}
- if (sector >= new_backing_num_sectors || !bs_new_backing) {
+ if (sector >= new_backing_num_sectors || !blk_new_backing) {
memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
} else {
if (sector + n > new_backing_num_sectors) {
n = new_backing_num_sectors - sector;
}
- ret = bdrv_read(bs_new_backing, sector, buf_new, n);
+ ret = blk_read(blk_new_backing, sector, buf_new, n);
if (ret < 0) {
error_report("error while reading from new backing file");
goto out;
@@ -2698,8 +2690,8 @@ static int img_rebase(int argc, char **argv)
if (compare_sectors(buf_old + written * 512,
buf_new + written * 512, n - written, &pnum))
{
- ret = bdrv_write(bs, sector + written,
- buf_old + written * 512, pnum);
+ ret = blk_write(blk, sector + written,
+ buf_old + written * 512, pnum);
if (ret < 0) {
error_report("Error while writing to COW image: %s",
strerror(-ret));
@@ -2764,7 +2756,6 @@ static int img_resize(int argc, char **argv)
int64_t n, total_size;
bool quiet = false;
BlockBackend *blk = NULL;
- BlockDriverState *bs = NULL;
QemuOpts *param;
static QemuOptsList resize_options = {
.name = "resize_options",
@@ -2846,10 +2837,9 @@ static int img_resize(int argc, char **argv)
ret = -1;
goto out;
}
- bs = blk_bs(blk);
if (relative) {
- total_size = bdrv_getlength(bs) + n * relative;
+ total_size = blk_getlength(blk) + n * relative;
} else {
total_size = n;
}
@@ -2859,7 +2849,7 @@ static int img_resize(int argc, char **argv)
goto out;
}
- ret = bdrv_truncate(bs, total_size);
+ ret = blk_truncate(blk, total_size);
switch (ret) {
case 0:
qprintf(quiet, "Image resized.\n");