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