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