Revision 6b837bc4
b/Makefile.objs | ||
---|---|---|
14 | 14 |
# block-obj-y is code used by both qemu system emulation and qemu-img |
15 | 15 |
|
16 | 16 |
block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o |
17 |
block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o |
|
17 |
block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o
|
|
18 | 18 |
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o |
19 | 19 |
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o |
20 | 20 |
|
b/qemu-common.h | ||
---|---|---|
334 | 334 |
void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, |
335 | 335 |
size_t skip); |
336 | 336 |
|
337 |
void qemu_progress_init(int enabled, float min_skip); |
|
338 |
void qemu_progress_end(void); |
|
339 |
void qemu_progress_print(float percent, int max); |
|
340 |
|
|
337 | 341 |
/* Convert a byte between binary and BCD. */ |
338 | 342 |
static inline uint8_t to_bcd(uint8_t val) |
339 | 343 |
{ |
b/qemu-img-cmds.hx | ||
---|---|---|
28 | 28 |
ETEXI |
29 | 29 |
|
30 | 30 |
DEF("convert", img_convert, |
31 |
"convert [-c] [-f fmt] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename") |
|
31 |
"convert [-c] [-p] [-f fmt] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename")
|
|
32 | 32 |
STEXI |
33 | 33 |
@item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} |
34 | 34 |
ETEXI |
... | ... | |
46 | 46 |
ETEXI |
47 | 47 |
|
48 | 48 |
DEF("rebase", img_rebase, |
49 |
"rebase [-f fmt] [-u] -b backing_file [-F backing_fmt] filename") |
|
49 |
"rebase [-f fmt] [-p] [-u] -b backing_file [-F backing_fmt] filename")
|
|
50 | 50 |
STEXI |
51 | 51 |
@item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} |
52 | 52 |
ETEXI |
b/qemu-img.c | ||
---|---|---|
77 | 77 |
" match exactly. The image doesn't need a working backing file before\n" |
78 | 78 |
" rebasing in this case (useful for renaming the backing file)\n" |
79 | 79 |
" '-h' with or without a command shows this help and lists the supported formats\n" |
80 |
" '-p' show progress of command (only certain commands)\n" |
|
80 | 81 |
"\n" |
81 | 82 |
"Parameters to snapshot subcommand:\n" |
82 | 83 |
" 'snapshot' is the name of the snapshot to create, apply or delete\n" |
... | ... | |
567 | 568 |
static int img_convert(int argc, char **argv) |
568 | 569 |
{ |
569 | 570 |
int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors; |
571 |
int progress = 0; |
|
570 | 572 |
const char *fmt, *out_fmt, *out_baseimg, *out_filename; |
571 | 573 |
BlockDriver *drv, *proto_drv; |
572 | 574 |
BlockDriverState **bs = NULL, *out_bs = NULL; |
... | ... | |
579 | 581 |
QEMUOptionParameter *out_baseimg_param; |
580 | 582 |
char *options = NULL; |
581 | 583 |
const char *snapshot_name = NULL; |
584 |
float local_progress; |
|
582 | 585 |
|
583 | 586 |
fmt = NULL; |
584 | 587 |
out_fmt = "raw"; |
585 | 588 |
out_baseimg = NULL; |
586 | 589 |
compress = 0; |
587 | 590 |
for(;;) { |
588 |
c = getopt(argc, argv, "f:O:B:s:hce6o:"); |
|
591 |
c = getopt(argc, argv, "f:O:B:s:hce6o:p");
|
|
589 | 592 |
if (c == -1) { |
590 | 593 |
break; |
591 | 594 |
} |
... | ... | |
620 | 623 |
case 's': |
621 | 624 |
snapshot_name = optarg; |
622 | 625 |
break; |
626 |
case 'p': |
|
627 |
progress = 1; |
|
628 |
break; |
|
623 | 629 |
} |
624 | 630 |
} |
625 | 631 |
|
... | ... | |
642 | 648 |
goto out; |
643 | 649 |
} |
644 | 650 |
|
651 |
qemu_progress_init(progress, 2.0); |
|
652 |
qemu_progress_print(0, 100); |
|
653 |
|
|
645 | 654 |
bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *)); |
646 | 655 |
|
647 | 656 |
total_sectors = 0; |
... | ... | |
773 | 782 |
} |
774 | 783 |
cluster_sectors = cluster_size >> 9; |
775 | 784 |
sector_num = 0; |
785 |
|
|
786 |
nb_sectors = total_sectors; |
|
787 |
local_progress = (float)100 / |
|
788 |
(nb_sectors / MIN(nb_sectors, (cluster_sectors))); |
|
789 |
|
|
776 | 790 |
for(;;) { |
777 | 791 |
int64_t bs_num; |
778 | 792 |
int remainder; |
... | ... | |
832 | 846 |
} |
833 | 847 |
} |
834 | 848 |
sector_num += n; |
849 |
qemu_progress_print(local_progress, 100); |
|
835 | 850 |
} |
836 | 851 |
/* signal EOF to align */ |
837 | 852 |
bdrv_write_compressed(out_bs, 0, NULL, 0); |
... | ... | |
839 | 854 |
int has_zero_init = bdrv_has_zero_init(out_bs); |
840 | 855 |
|
841 | 856 |
sector_num = 0; // total number of sectors converted so far |
857 |
nb_sectors = total_sectors - sector_num; |
|
858 |
local_progress = (float)100 / |
|
859 |
(nb_sectors / MIN(nb_sectors, (IO_BUF_SIZE / 512))); |
|
860 |
|
|
842 | 861 |
for(;;) { |
843 | 862 |
nb_sectors = total_sectors - sector_num; |
844 | 863 |
if (nb_sectors <= 0) { |
... | ... | |
912 | 931 |
n -= n1; |
913 | 932 |
buf1 += n1 * 512; |
914 | 933 |
} |
934 |
qemu_progress_print(local_progress, 100); |
|
915 | 935 |
} |
916 | 936 |
} |
917 | 937 |
out: |
938 |
qemu_progress_end(); |
|
918 | 939 |
free_option_parameters(create_options); |
919 | 940 |
free_option_parameters(param); |
920 | 941 |
qemu_free(buf); |
... | ... | |
1184 | 1205 |
const char *fmt, *out_basefmt, *out_baseimg; |
1185 | 1206 |
int c, flags, ret; |
1186 | 1207 |
int unsafe = 0; |
1208 |
int progress = 0; |
|
1187 | 1209 |
|
1188 | 1210 |
/* Parse commandline parameters */ |
1189 | 1211 |
fmt = NULL; |
... | ... | |
1191 | 1213 |
out_basefmt = NULL; |
1192 | 1214 |
|
1193 | 1215 |
for(;;) { |
1194 |
c = getopt(argc, argv, "uhf:F:b:"); |
|
1216 |
c = getopt(argc, argv, "uhf:F:b:p");
|
|
1195 | 1217 |
if (c == -1) { |
1196 | 1218 |
break; |
1197 | 1219 |
} |
... | ... | |
1212 | 1234 |
case 'u': |
1213 | 1235 |
unsafe = 1; |
1214 | 1236 |
break; |
1237 |
case 'p': |
|
1238 |
progress = 1; |
|
1239 |
break; |
|
1215 | 1240 |
} |
1216 | 1241 |
} |
1217 | 1242 |
|
... | ... | |
1220 | 1245 |
} |
1221 | 1246 |
filename = argv[optind++]; |
1222 | 1247 |
|
1248 |
qemu_progress_init(progress, 2.0); |
|
1249 |
qemu_progress_print(0, 100); |
|
1250 |
|
|
1223 | 1251 |
/* |
1224 | 1252 |
* Open the images. |
1225 | 1253 |
* |
... | ... | |
1295 | 1323 |
int n; |
1296 | 1324 |
uint8_t * buf_old; |
1297 | 1325 |
uint8_t * buf_new; |
1326 |
float local_progress; |
|
1298 | 1327 |
|
1299 | 1328 |
buf_old = qemu_malloc(IO_BUF_SIZE); |
1300 | 1329 |
buf_new = qemu_malloc(IO_BUF_SIZE); |
1301 | 1330 |
|
1302 | 1331 |
bdrv_get_geometry(bs, &num_sectors); |
1303 | 1332 |
|
1333 |
local_progress = (float)100 / |
|
1334 |
(num_sectors / MIN(num_sectors, (IO_BUF_SIZE / 512))); |
|
1304 | 1335 |
for (sector = 0; sector < num_sectors; sector += n) { |
1305 | 1336 |
|
1306 | 1337 |
/* How many sectors can we handle with the next read? */ |
... | ... | |
1348 | 1379 |
|
1349 | 1380 |
written += pnum; |
1350 | 1381 |
} |
1382 |
qemu_progress_print(local_progress, 100); |
|
1351 | 1383 |
} |
1352 | 1384 |
|
1353 | 1385 |
qemu_free(buf_old); |
... | ... | |
1368 | 1400 |
out_baseimg, strerror(-ret)); |
1369 | 1401 |
} |
1370 | 1402 |
|
1403 |
qemu_progress_print(100, 0); |
|
1371 | 1404 |
/* |
1372 | 1405 |
* TODO At this point it is possible to check if any clusters that are |
1373 | 1406 |
* allocated in the COW file are the same in the backing file. If so, they |
... | ... | |
1375 | 1408 |
* backing file, in case of a crash this would lead to corruption. |
1376 | 1409 |
*/ |
1377 | 1410 |
out: |
1411 |
qemu_progress_end(); |
|
1378 | 1412 |
/* Cleanup */ |
1379 | 1413 |
if (!unsafe) { |
1380 | 1414 |
bdrv_delete(bs_old_backing); |
b/qemu-progress.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU progress printing utility functions |
|
3 |
* |
|
4 |
* Copyright (C) 2011 Jes Sorensen <Jes.Sorensen@redhat.com> |
|
5 |
* |
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
* of this software and associated documentation files (the "Software"), to deal |
|
8 |
* in the Software without restriction, including without limitation the rights |
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
* copies of the Software, and to permit persons to whom the Software is |
|
11 |
* furnished to do so, subject to the following conditions: |
|
12 |
* |
|
13 |
* The above copyright notice and this permission notice shall be included in |
|
14 |
* all copies or substantial portions of the Software. |
|
15 |
* |
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 |
* THE SOFTWARE. |
|
23 |
*/ |
|
24 |
|
|
25 |
#include "qemu-common.h" |
|
26 |
#include "osdep.h" |
|
27 |
#include "sysemu.h" |
|
28 |
#include <stdio.h> |
|
29 |
|
|
30 |
struct progress_state { |
|
31 |
int enabled; |
|
32 |
float current; |
|
33 |
float last_print; |
|
34 |
float min_skip; |
|
35 |
}; |
|
36 |
|
|
37 |
static struct progress_state state; |
|
38 |
|
|
39 |
/* |
|
40 |
* Simple progress print function. |
|
41 |
* @percent relative percent of current operation |
|
42 |
* @max percent of total operation |
|
43 |
*/ |
|
44 |
static void progress_simple_print(void) |
|
45 |
{ |
|
46 |
if (state.enabled) { |
|
47 |
printf(" (%3.2f/100%%)\r", state.current); |
|
48 |
fflush(stdout); |
|
49 |
} |
|
50 |
} |
|
51 |
|
|
52 |
static void progress_simple_end(void) |
|
53 |
{ |
|
54 |
if (state.enabled) { |
|
55 |
printf("\n"); |
|
56 |
} |
|
57 |
} |
|
58 |
|
|
59 |
void qemu_progress_init(int enabled, float min_skip) |
|
60 |
{ |
|
61 |
state.enabled = enabled; |
|
62 |
state.min_skip = min_skip; |
|
63 |
} |
|
64 |
|
|
65 |
void qemu_progress_end(void) |
|
66 |
{ |
|
67 |
progress_simple_end(); |
|
68 |
} |
|
69 |
|
|
70 |
void qemu_progress_print(float percent, int max) |
|
71 |
{ |
|
72 |
float current; |
|
73 |
|
|
74 |
if (max == 0) { |
|
75 |
current = percent; |
|
76 |
} else { |
|
77 |
current = state.current + percent / 100 * max; |
|
78 |
} |
|
79 |
if (current > 100) { |
|
80 |
current = 100; |
|
81 |
} |
|
82 |
state.current = current; |
|
83 |
|
|
84 |
if (current > (state.last_print + state.min_skip) || |
|
85 |
(current == 100) || (current == 0)) { |
|
86 |
state.last_print = state.current; |
|
87 |
progress_simple_print(); |
|
88 |
} |
|
89 |
} |
Also available in: Unified diff