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); |