Revision 0563e191

b/block.c
30 30
#include "qjson.h"
31 31
#include "qemu-coroutine.h"
32 32
#include "qmp-commands.h"
33
#include "qemu-timer.h"
33 34

  
34 35
#ifdef CONFIG_BSD
35 36
#include <sys/types.h>
......
105 106
}
106 107
#endif
107 108

  
109
/* throttling disk I/O limits */
110
static void bdrv_block_timer(void *opaque)
111
{
112
    BlockDriverState *bs = opaque;
113

  
114
    qemu_co_queue_next(&bs->throttled_reqs);
115
}
116

  
117
void bdrv_io_limits_enable(BlockDriverState *bs)
118
{
119
    qemu_co_queue_init(&bs->throttled_reqs);
120
    bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs);
121
    bs->slice_time  = 5 * BLOCK_IO_SLICE_TIME;
122
    bs->slice_start = qemu_get_clock_ns(vm_clock);
123
    bs->slice_end   = bs->slice_start + bs->slice_time;
124
    memset(&bs->io_base, 0, sizeof(bs->io_base));
125
    bs->io_limits_enabled = true;
126
}
127

  
128
bool bdrv_io_limits_enabled(BlockDriverState *bs)
129
{
130
    BlockIOLimit *io_limits = &bs->io_limits;
131
    return io_limits->bps[BLOCK_IO_LIMIT_READ]
132
         || io_limits->bps[BLOCK_IO_LIMIT_WRITE]
133
         || io_limits->bps[BLOCK_IO_LIMIT_TOTAL]
134
         || io_limits->iops[BLOCK_IO_LIMIT_READ]
135
         || io_limits->iops[BLOCK_IO_LIMIT_WRITE]
136
         || io_limits->iops[BLOCK_IO_LIMIT_TOTAL];
137
}
138

  
108 139
/* check if the path starts with "<protocol>:" */
109 140
static int path_has_protocol(const char *path)
110 141
{
......
1526 1557
    *psecs = bs->secs;
1527 1558
}
1528 1559

  
1560
/* throttling disk io limits */
1561
void bdrv_set_io_limits(BlockDriverState *bs,
1562
                        BlockIOLimit *io_limits)
1563
{
1564
    bs->io_limits = *io_limits;
1565
    bs->io_limits_enabled = bdrv_io_limits_enabled(bs);
1566
}
1567

  
1529 1568
/* Recognize floppy formats */
1530 1569
typedef struct FDFormat {
1531 1570
    FDriveType drive;
b/block.h
98 98
void bdrv_stats_print(Monitor *mon, const QObject *data);
99 99
void bdrv_info_stats(Monitor *mon, QObject **ret_data);
100 100

  
101
/* disk I/O throttling */
102
void bdrv_io_limits_enable(BlockDriverState *bs);
103
bool bdrv_io_limits_enabled(BlockDriverState *bs);
104

  
101 105
void bdrv_init(void);
102 106
void bdrv_init_with_whitelist(void);
103 107
BlockDriver *bdrv_find_protocol(const char *filename);
b/block_int.h
34 34
#define BLOCK_FLAG_ENCRYPT	1
35 35
#define BLOCK_FLAG_COMPAT6	4
36 36

  
37
#define BLOCK_IO_LIMIT_READ     0
38
#define BLOCK_IO_LIMIT_WRITE    1
39
#define BLOCK_IO_LIMIT_TOTAL    2
40

  
41
#define BLOCK_IO_SLICE_TIME     100000000
42

  
37 43
#define BLOCK_OPT_SIZE          "size"
38 44
#define BLOCK_OPT_ENCRYPT       "encryption"
39 45
#define BLOCK_OPT_COMPAT6       "compat6"
......
50 56
    BlockDriverAIOCB *free_aiocb;
51 57
} AIOPool;
52 58

  
59
typedef struct BlockIOLimit {
60
    int64_t bps[3];
61
    int64_t iops[3];
62
} BlockIOLimit;
63

  
64
typedef struct BlockIOBaseValue {
65
    uint64_t bytes[2];
66
    uint64_t ios[2];
67
} BlockIOBaseValue;
68

  
53 69
struct BlockDriver {
54 70
    const char *format_name;
55 71
    int instance_size;
......
201 217

  
202 218
    void *sync_aiocb;
203 219

  
220
    /* the time for latest disk I/O */
221
    int64_t slice_time;
222
    int64_t slice_start;
223
    int64_t slice_end;
224
    BlockIOLimit io_limits;
225
    BlockIOBaseValue  io_base;
226
    CoQueue      throttled_reqs;
227
    QEMUTimer    *block_timer;
228
    bool         io_limits_enabled;
229

  
204 230
    /* I/O stats (display with "info blockstats"). */
205 231
    uint64_t nr_bytes[BDRV_MAX_IOTYPE];
206 232
    uint64_t nr_ops[BDRV_MAX_IOTYPE];
......
244 270
                   BlockDriverCompletionFunc *cb, void *opaque);
245 271
void qemu_aio_release(void *p);
246 272

  
273
void bdrv_set_io_limits(BlockDriverState *bs,
274
                        BlockIOLimit *io_limits);
275

  
247 276
#ifdef _WIN32
248 277
int is_windows_drive(const char *filename);
249 278
#endif
b/blockdev.c
216 216
    }
217 217
}
218 218

  
219
static bool do_check_io_limits(BlockIOLimit *io_limits)
220
{
221
    bool bps_flag;
222
    bool iops_flag;
223

  
224
    assert(io_limits);
225

  
226
    bps_flag  = (io_limits->bps[BLOCK_IO_LIMIT_TOTAL] != 0)
227
                 && ((io_limits->bps[BLOCK_IO_LIMIT_READ] != 0)
228
                 || (io_limits->bps[BLOCK_IO_LIMIT_WRITE] != 0));
229
    iops_flag = (io_limits->iops[BLOCK_IO_LIMIT_TOTAL] != 0)
230
                 && ((io_limits->iops[BLOCK_IO_LIMIT_READ] != 0)
231
                 || (io_limits->iops[BLOCK_IO_LIMIT_WRITE] != 0));
232
    if (bps_flag || iops_flag) {
233
        return false;
234
    }
235

  
236
    return true;
237
}
238

  
219 239
DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
220 240
{
221 241
    const char *buf;
......
235 255
    int on_read_error, on_write_error;
236 256
    const char *devaddr;
237 257
    DriveInfo *dinfo;
258
    BlockIOLimit io_limits;
238 259
    int snapshot = 0;
239 260
    int ret;
240 261

  
......
353 374
        }
354 375
    }
355 376

  
377
    /* disk I/O throttling */
378
    io_limits.bps[BLOCK_IO_LIMIT_TOTAL]  =
379
                           qemu_opt_get_number(opts, "bps", 0);
380
    io_limits.bps[BLOCK_IO_LIMIT_READ]   =
381
                           qemu_opt_get_number(opts, "bps_rd", 0);
382
    io_limits.bps[BLOCK_IO_LIMIT_WRITE]  =
383
                           qemu_opt_get_number(opts, "bps_wr", 0);
384
    io_limits.iops[BLOCK_IO_LIMIT_TOTAL] =
385
                           qemu_opt_get_number(opts, "iops", 0);
386
    io_limits.iops[BLOCK_IO_LIMIT_READ]  =
387
                           qemu_opt_get_number(opts, "iops_rd", 0);
388
    io_limits.iops[BLOCK_IO_LIMIT_WRITE] =
389
                           qemu_opt_get_number(opts, "iops_wr", 0);
390

  
391
    if (!do_check_io_limits(&io_limits)) {
392
        error_report("bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr) "
393
                     "cannot be used at the same time");
394
        return NULL;
395
    }
396

  
356 397
    on_write_error = BLOCK_ERR_STOP_ENOSPC;
357 398
    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
358 399
        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
......
460 501

  
461 502
    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
462 503

  
504
    /* disk I/O throttling */
505
    bdrv_set_io_limits(dinfo->bdrv, &io_limits);
506

  
463 507
    switch(type) {
464 508
    case IF_IDE:
465 509
    case IF_SCSI:
b/qemu-config.c
85 85
            .name = "readonly",
86 86
            .type = QEMU_OPT_BOOL,
87 87
            .help = "open drive file as read-only",
88
        },{
89
            .name = "iops",
90
            .type = QEMU_OPT_NUMBER,
91
            .help = "limit total I/O operations per second",
92
        },{
93
            .name = "iops_rd",
94
            .type = QEMU_OPT_NUMBER,
95
            .help = "limit read operations per second",
96
        },{
97
            .name = "iops_wr",
98
            .type = QEMU_OPT_NUMBER,
99
            .help = "limit write operations per second",
100
        },{
101
            .name = "bps",
102
            .type = QEMU_OPT_NUMBER,
103
            .help = "limit total bytes per second",
104
        },{
105
            .name = "bps_rd",
106
            .type = QEMU_OPT_NUMBER,
107
            .help = "limit read bytes per second",
108
        },{
109
            .name = "bps_wr",
110
            .type = QEMU_OPT_NUMBER,
111
            .help = "limit write bytes per second",
88 112
        },
89 113
        { /* end of list */ }
90 114
    },
b/qemu-options.hx
136 136
    "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
137 137
    "       [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
138 138
    "       [,readonly=on|off]\n"
139
    "       [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]][[,iops=i]|[[,iops_rd=r][,iops_wr=w]]\n"
139 140
    "                use 'file' as a drive image\n", QEMU_ARCH_ALL)
140 141
STEXI
141 142
@item -drive @var{option}[,@var{option}[,@var{option}[,...]]]

Also available in: Unified diff