X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/3eb98f760e54f897a7ecf88e63f9eade6b00f614..5a0948d36c4cbc1c5534afac6fee99de55245d12:/qemu-img.c diff --git a/qemu-img.c b/qemu-img.c index 79983772de..95a24b9762 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -38,10 +38,10 @@ #include "qemu/option.h" #include "qemu/error-report.h" #include "qemu/log.h" +#include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/units.h" #include "qom/object_interfaces.h" -#include "sysemu/sysemu.h" #include "sysemu/block-backend.h" #include "block/block_int.h" #include "block/blockjob.h" @@ -214,6 +214,14 @@ static QemuOptsList qemu_object_opts = { }, }; +static bool qemu_img_object_print_help(const char *type, QemuOpts *opts) +{ + if (user_creatable_print_help(type, opts)) { + exit(0); + } + return true; +} + static QemuOptsList qemu_source_opts = { .name = "source", .implied_opt_name = "file", @@ -516,7 +524,7 @@ static int img_create(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { goto fail; } @@ -766,7 +774,7 @@ static int img_check(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -979,7 +987,7 @@ static int img_commit(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -1362,7 +1370,7 @@ static int img_compare(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { ret = 2; goto out4; } @@ -1578,6 +1586,7 @@ typedef struct ImgConvertState { bool has_zero_init; bool compressed; bool unallocated_blocks_are_zero; + bool target_is_new; bool target_has_backing; int64_t target_backing_sectors; /* negative if unknown */ bool wr_in_order; @@ -1975,9 +1984,11 @@ static int convert_do_copy(ImgConvertState *s) int64_t sector_num = 0; /* Check whether we have zero initialisation or can get it efficiently */ - s->has_zero_init = s->min_sparse && !s->target_has_backing - ? bdrv_has_zero_init(blk_bs(s->target)) - : false; + if (s->target_is_new && s->min_sparse && !s->target_has_backing) { + s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target)); + } else { + s->has_zero_init = false; + } if (!s->has_zero_init && !s->target_has_backing && bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) @@ -2138,7 +2149,7 @@ static int img_convert(int argc, char **argv) int64_t sval; sval = cvtnum(optarg); - if (sval < 0 || sval & (BDRV_SECTOR_SIZE - 1) || + if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) || sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) { error_report("Invalid buffer size for sparse output specified. " "Valid sizes are multiples of %llu up to %llu. Select " @@ -2207,7 +2218,7 @@ static int img_convert(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { goto fail_getopt; } @@ -2231,6 +2242,11 @@ static int img_convert(int argc, char **argv) goto fail_getopt; } + if (skip_create && options) { + warn_report("-o has no effect when skipping image creation"); + warn_report("This will become an error in future QEMU versions."); + } + s.src_num = argc - optind - 1; out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL; @@ -2380,7 +2396,7 @@ static int img_convert(int argc, char **argv) const char *preallocation = qemu_opt_get(opts, BLOCK_OPT_PREALLOC); - if (drv && !drv->bdrv_co_pwritev_compressed) { + if (drv && !block_driver_can_compress(drv)) { error_report("Compression not supported for this file format"); ret = -1; goto out; @@ -2423,6 +2439,8 @@ static int img_convert(int argc, char **argv) } } + s.target_is_new = !skip_create; + flags = s.min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR; ret = bdrv_parse_cache_mode(cache, &flags, &writethrough); if (ret < 0) { @@ -2449,7 +2467,7 @@ static int img_convert(int argc, char **argv) } out_bs = blk_bs(s.target); - if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) { + if (s.compressed && !block_driver_can_compress(out_bs->drv)) { error_report("Compression not supported for this file format"); ret = -1; goto out; @@ -2766,7 +2784,7 @@ static int img_info(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -2992,7 +3010,7 @@ static int img_map(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -3144,7 +3162,7 @@ static int img_snapshot(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -3311,7 +3329,7 @@ static int img_rebase(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -3638,7 +3656,7 @@ static int img_resize(int argc, char **argv) Error *err = NULL; int c, ret, relative; const char *filename, *fmt, *size; - int64_t n, total_size, current_size, new_size; + int64_t n, total_size, current_size; bool quiet = false; BlockBackend *blk = NULL; PreallocMode prealloc = PREALLOC_MODE_OFF; @@ -3732,7 +3750,7 @@ static int img_resize(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { return 1; } @@ -3813,43 +3831,17 @@ static int img_resize(int argc, char **argv) } } - ret = blk_truncate(blk, total_size, prealloc, &err); - if (ret < 0) { + /* + * The user expects the image to have the desired size after + * resizing, so pass @exact=true. It is of no use to report + * success when the image has not actually been resized. + */ + ret = blk_truncate(blk, total_size, true, prealloc, &err); + if (!ret) { + qprintf(quiet, "Image resized.\n"); + } else { error_report_err(err); - goto out; - } - - new_size = blk_getlength(blk); - if (new_size < 0) { - error_report("Failed to verify truncated image length: %s", - strerror(-new_size)); - ret = -1; - goto out; - } - - /* Some block drivers implement a truncation method, but only so - * the user can cause qemu to refresh the image's size from disk. - * The idea is that the user resizes the image outside of qemu and - * then invokes block_resize to inform qemu about it. - * (This includes iscsi and file-posix for device files.) - * Of course, that is not the behavior someone invoking - * qemu-img resize would find useful, so we catch that behavior - * here and tell the user. */ - if (new_size != total_size && new_size == current_size) { - error_report("Image was not resized; resizing may not be supported " - "for this image"); - ret = -1; - goto out; } - - if (new_size != total_size) { - warn_report("Image should have been resized to %" PRIi64 - " bytes, but was resized to %" PRIi64 " bytes", - total_size, new_size); - } - - qprintf(quiet, "Image resized.\n"); - out: blk_unref(blk); if (ret) { @@ -3976,7 +3968,7 @@ static int img_amend(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { ret = -1; goto out_no_progress; } @@ -4620,7 +4612,7 @@ static int img_dd(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { ret = -1; goto out; } @@ -4897,7 +4889,7 @@ static int img_measure(int argc, char **argv) if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, - NULL, &error_fatal)) { + qemu_img_object_print_help, &error_fatal)) { goto out; }