Commit 9ea2ea7146042d54fc3d17d0269ae865cbf55dcf
Committed by
Anthony Liguori
1 parent
0e7e1989
Convert qemu-img create to new bdrv_create
This patch changes qemu-img to actually use the new bdrv_create interface. It translates the old-style qemu-img options which have been bdrv_create2 parameters or flags so far to option structures. As the generic approach, it introduces an -o option which accepts any parameter the driver knows. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
1 changed file
with
87 additions
and
46 deletions
qemu-img.c
| @@ -22,6 +22,7 @@ | @@ -22,6 +22,7 @@ | ||
| 22 | * THE SOFTWARE. | 22 | * THE SOFTWARE. |
| 23 | */ | 23 | */ |
| 24 | #include "qemu-common.h" | 24 | #include "qemu-common.h" |
| 25 | +#include "qemu-option.h" | ||
| 25 | #include "osdep.h" | 26 | #include "osdep.h" |
| 26 | #include "block_int.h" | 27 | #include "block_int.h" |
| 27 | #include <stdio.h> | 28 | #include <stdio.h> |
| @@ -221,14 +222,13 @@ static int img_create(int argc, char **argv) | @@ -221,14 +222,13 @@ static int img_create(int argc, char **argv) | ||
| 221 | const char *base_fmt = NULL; | 222 | const char *base_fmt = NULL; |
| 222 | const char *filename; | 223 | const char *filename; |
| 223 | const char *base_filename = NULL; | 224 | const char *base_filename = NULL; |
| 224 | - uint64_t size; | ||
| 225 | - double sizef; | ||
| 226 | - const char *p; | ||
| 227 | BlockDriver *drv; | 225 | BlockDriver *drv; |
| 226 | + QEMUOptionParameter *param = NULL; | ||
| 227 | + char *options = NULL; | ||
| 228 | 228 | ||
| 229 | flags = 0; | 229 | flags = 0; |
| 230 | for(;;) { | 230 | for(;;) { |
| 231 | - c = getopt(argc, argv, "F:b:f:he6"); | 231 | + c = getopt(argc, argv, "F:b:f:he6o:"); |
| 232 | if (c == -1) | 232 | if (c == -1) |
| 233 | break; | 233 | break; |
| 234 | switch(c) { | 234 | switch(c) { |
| @@ -250,59 +250,100 @@ static int img_create(int argc, char **argv) | @@ -250,59 +250,100 @@ static int img_create(int argc, char **argv) | ||
| 250 | case '6': | 250 | case '6': |
| 251 | flags |= BLOCK_FLAG_COMPAT6; | 251 | flags |= BLOCK_FLAG_COMPAT6; |
| 252 | break; | 252 | break; |
| 253 | + case 'o': | ||
| 254 | + options = optarg; | ||
| 255 | + break; | ||
| 253 | } | 256 | } |
| 254 | } | 257 | } |
| 255 | if (optind >= argc) | 258 | if (optind >= argc) |
| 256 | help(); | 259 | help(); |
| 257 | filename = argv[optind++]; | 260 | filename = argv[optind++]; |
| 258 | - size = 0; | ||
| 259 | - if (base_filename) { | ||
| 260 | - BlockDriverState *bs; | ||
| 261 | - BlockDriver *base_drv = NULL; | ||
| 262 | 261 | ||
| 263 | - if (base_fmt) { | ||
| 264 | - base_drv = bdrv_find_format(base_fmt); | ||
| 265 | - if (base_drv == NULL) | ||
| 266 | - error("Unknown basefile format '%s'", base_fmt); | ||
| 267 | - } | 262 | + /* Find driver and parse its options */ |
| 263 | + drv = bdrv_find_format(fmt); | ||
| 264 | + if (!drv) | ||
| 265 | + error("Unknown file format '%s'", fmt); | ||
| 268 | 266 | ||
| 269 | - bs = bdrv_new_open(base_filename, base_fmt); | ||
| 270 | - bdrv_get_geometry(bs, &size); | ||
| 271 | - size *= 512; | ||
| 272 | - bdrv_delete(bs); | 267 | + if (options) { |
| 268 | + param = parse_option_parameters(options, drv->create_options, param); | ||
| 269 | + if (param == NULL) { | ||
| 270 | + error("Invalid options for file format '%s'.", fmt); | ||
| 271 | + } | ||
| 273 | } else { | 272 | } else { |
| 274 | - if (optind >= argc) | ||
| 275 | - help(); | ||
| 276 | - p = argv[optind]; | ||
| 277 | - sizef = strtod(p, (char **)&p); | ||
| 278 | - if (*p == 'M') { | ||
| 279 | - size = (uint64_t)(sizef * 1024 * 1024); | ||
| 280 | - } else if (*p == 'G') { | ||
| 281 | - size = (uint64_t)(sizef * 1024 * 1024 * 1024); | ||
| 282 | - } else if (*p == 'k' || *p == 'K' || *p == '\0') { | ||
| 283 | - size = (uint64_t)(sizef * 1024); | ||
| 284 | - } else { | ||
| 285 | - help(); | 273 | + param = parse_option_parameters("", drv->create_options, param); |
| 274 | + } | ||
| 275 | + | ||
| 276 | + /* Add size to parameters */ | ||
| 277 | + if (optind < argc) { | ||
| 278 | + set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]); | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + /* Add old-style options to parameters */ | ||
| 282 | + if (flags & BLOCK_FLAG_ENCRYPT) { | ||
| 283 | + if (set_option_parameter(param, BLOCK_OPT_ENCRYPT, "on")) { | ||
| 284 | + error("Encryption not supported for file format '%s'", fmt); | ||
| 286 | } | 285 | } |
| 287 | } | 286 | } |
| 288 | - drv = bdrv_find_format(fmt); | ||
| 289 | - if (!drv) | ||
| 290 | - error("Unknown file format '%s'", fmt); | ||
| 291 | - printf("Formatting '%s', fmt=%s", | ||
| 292 | - filename, fmt); | ||
| 293 | - if (flags & BLOCK_FLAG_ENCRYPT) | ||
| 294 | - printf(", encrypted"); | ||
| 295 | - if (flags & BLOCK_FLAG_COMPAT6) | ||
| 296 | - printf(", compatibility level=6"); | 287 | + if (flags & BLOCK_FLAG_COMPAT6) { |
| 288 | + if (set_option_parameter(param, BLOCK_OPT_COMPAT6, "on")) { | ||
| 289 | + error("VMDK version 6 not supported for file format '%s'", fmt); | ||
| 290 | + } | ||
| 291 | + } | ||
| 292 | + | ||
| 297 | if (base_filename) { | 293 | if (base_filename) { |
| 298 | - printf(", backing_file=%s", | ||
| 299 | - base_filename); | ||
| 300 | - if (base_fmt) | ||
| 301 | - printf(", backing_fmt=%s", | ||
| 302 | - base_fmt); | ||
| 303 | - } | ||
| 304 | - printf(", size=%" PRIu64 " kB\n", size / 1024); | ||
| 305 | - ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags); | 294 | + if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, base_filename)) { |
| 295 | + error("Backing file not supported for file format '%s'", fmt); | ||
| 296 | + } | ||
| 297 | + } | ||
| 298 | + if (base_fmt) { | ||
| 299 | + if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) { | ||
| 300 | + error("Backing file format not supported for file format '%s'", fmt); | ||
| 301 | + } | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + // The size for the image must always be specified, with one exception: | ||
| 305 | + // If we are using a backing file, we can obtain the size from there | ||
| 306 | + if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == 0) { | ||
| 307 | + | ||
| 308 | + QEMUOptionParameter *backing_file = | ||
| 309 | + get_option_parameter(param, BLOCK_OPT_BACKING_FILE); | ||
| 310 | + QEMUOptionParameter *backing_fmt = | ||
| 311 | + get_option_parameter(param, BLOCK_OPT_BACKING_FMT); | ||
| 312 | + | ||
| 313 | + if (backing_file && backing_file->value.s) { | ||
| 314 | + BlockDriverState *bs; | ||
| 315 | + uint64_t size; | ||
| 316 | + const char *fmt = NULL; | ||
| 317 | + char buf[32]; | ||
| 318 | + | ||
| 319 | + if (backing_fmt && backing_fmt->value.s) { | ||
| 320 | + if (bdrv_find_format(backing_fmt->value.s)) { | ||
| 321 | + fmt = backing_fmt->value.s; | ||
| 322 | + } else { | ||
| 323 | + error("Unknown backing file format '%s'", | ||
| 324 | + backing_fmt->value.s); | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + bs = bdrv_new_open(backing_file->value.s, fmt); | ||
| 329 | + bdrv_get_geometry(bs, &size); | ||
| 330 | + size *= 512; | ||
| 331 | + bdrv_delete(bs); | ||
| 332 | + | ||
| 333 | + snprintf(buf, sizeof(buf), "%" PRId64, size); | ||
| 334 | + set_option_parameter(param, BLOCK_OPT_SIZE, buf); | ||
| 335 | + } else { | ||
| 336 | + error("Image creation needs a size parameter"); | ||
| 337 | + } | ||
| 338 | + } | ||
| 339 | + | ||
| 340 | + printf("Formatting '%s', fmt=%s ", filename, fmt); | ||
| 341 | + print_option_parameters(param); | ||
| 342 | + puts(""); | ||
| 343 | + | ||
| 344 | + ret = bdrv_create(drv, filename, param); | ||
| 345 | + free_option_parameters(param); | ||
| 346 | + | ||
| 306 | if (ret < 0) { | 347 | if (ret < 0) { |
| 307 | if (ret == -ENOTSUP) { | 348 | if (ret == -ENOTSUP) { |
| 308 | error("Formatting or formatting option not supported for file format '%s'", fmt); | 349 | error("Formatting or formatting option not supported for file format '%s'", fmt); |