Re: [Qemu-devel] [PATCH v8 2/4] block: add the command line support
On Mon, Oct 17, 2011 at 6:19 PM, Kevin Wolf wrote: > Am 26.09.2011 08:15, schrieb Zhi Yong Wu: >> On Fri, Sep 23, 2011 at 11:54 PM, Kevin Wolf wrote: +} + +static void bdrv_block_timer(void *opaque) +{ + BlockDriverState *bs = opaque; + BlockQueue *queue = bs->block_queue; + + qemu_block_queue_flush(queue); >>> >>> Hm, didn't really notice it while reading patch 1, but >>> qemu_block_queue_flush() is misleading. It's really something like >> Why do you say this is misleading? >>> qemu_block_queue_submit(). >> Right. It will resubmit all enqueued I/O requests. > > For me, flush sounds as if it waits for completion of all requests. The code is currently except one I/O error. But i think that we should not take the action, right? I don't make sure if we should keep all the enqueued request in order. > > Kevin > -- Regards, Zhi Yong Wu
Re: [Qemu-devel] [PATCH v8 2/4] block: add the command line support
Am 26.09.2011 08:15, schrieb Zhi Yong Wu: > On Fri, Sep 23, 2011 at 11:54 PM, Kevin Wolf wrote: >>> +} >>> + >>> +static void bdrv_block_timer(void *opaque) >>> +{ >>> +BlockDriverState *bs = opaque; >>> +BlockQueue *queue= bs->block_queue; >>> + >>> +qemu_block_queue_flush(queue); >> >> Hm, didn't really notice it while reading patch 1, but >> qemu_block_queue_flush() is misleading. It's really something like > Why do you say this is misleading? >> qemu_block_queue_submit(). > Right. It will resubmit all enqueued I/O requests. For me, flush sounds as if it waits for completion of all requests. Kevin
Re: [Qemu-devel] [PATCH v8 2/4] block: add the command line support
On Fri, Sep 23, 2011 at 11:54 PM, Kevin Wolf wrote: > Am 08.09.2011 12:11, schrieb Zhi Yong Wu: >> Signed-off-by: Zhi Yong Wu >> --- >> block.c | 59 >> +++ >> block.h | 5 >> block_int.h | 3 ++ >> blockdev.c | 29 +++ >> qemu-config.c | 24 ++ >> qemu-options.hx | 1 + >> 6 files changed, 121 insertions(+), 0 deletions(-) >> >> diff --git a/block.c b/block.c >> index 43742b7..cd75183 100644 >> --- a/block.c >> +++ b/block.c >> @@ -104,6 +104,57 @@ int is_windows_drive(const char *filename) >> } >> #endif >> >> +/* throttling disk I/O limits */ >> +void bdrv_io_limits_disable(BlockDriverState *bs) >> +{ >> + bs->io_limits_enabled = false; >> + >> + if (bs->block_queue) { >> + qemu_block_queue_flush(bs->block_queue); >> + qemu_del_block_queue(bs->block_queue); >> + bs->block_queue = NULL; >> + } >> + >> + if (bs->block_timer) { >> + qemu_del_timer(bs->block_timer); >> + qemu_free_timer(bs->block_timer); >> + bs->block_timer = NULL; >> + } >> + >> + bs->slice_start = 0; >> + >> + bs->slice_end = 0; > > Remove the empty line between slice_start and slice_end? Yeah, thanks. > >> +} >> + >> +static void bdrv_block_timer(void *opaque) >> +{ >> + BlockDriverState *bs = opaque; >> + BlockQueue *queue = bs->block_queue; >> + >> + qemu_block_queue_flush(queue); > > Hm, didn't really notice it while reading patch 1, but > qemu_block_queue_flush() is misleading. It's really something like Why do you say this is misleading? > qemu_block_queue_submit(). Right. It will resubmit all enqueued I/O requests. > >> +} >> + >> +void bdrv_io_limits_enable(BlockDriverState *bs) >> +{ >> + bs->block_queue = qemu_new_block_queue(); >> + bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs); >> + >> + bs->slice_start = qemu_get_clock_ns(vm_clock); >> + >> + bs->slice_end = bs->slice_start + BLOCK_IO_SLICE_TIME; >> +} > > Same as above. got it. I will remove, thanks. > >> + >> +bool bdrv_io_limits_enabled(BlockDriverState *bs) >> +{ >> + BlockIOLimit *io_limits = &bs->io_limits; >> + return io_limits->bps[BLOCK_IO_LIMIT_READ] >> + || io_limits->bps[BLOCK_IO_LIMIT_WRITE] >> + || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] >> + || io_limits->iops[BLOCK_IO_LIMIT_READ] >> + || io_limits->iops[BLOCK_IO_LIMIT_WRITE] >> + || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; >> +} >> + >> /* check if the path starts with ":" */ >> static int path_has_protocol(const char *path) >> { >> @@ -1453,6 +1504,14 @@ void bdrv_get_geometry_hint(BlockDriverState *bs, >> *psecs = bs->secs; >> } >> >> +/* throttling disk io limits */ >> +void bdrv_set_io_limits(BlockDriverState *bs, >> + BlockIOLimit *io_limits) >> +{ >> + bs->io_limits = *io_limits; >> + bs->io_limits_enabled = bdrv_io_limits_enabled(bs); >> +} >> + >> /* Recognize floppy formats */ >> typedef struct FDFormat { >> FDriveType drive; >> diff --git a/block.h b/block.h >> index 3ac0b94..a3e69db 100644 >> --- a/block.h >> +++ b/block.h >> @@ -58,6 +58,11 @@ void bdrv_info(Monitor *mon, QObject **ret_data); >> void bdrv_stats_print(Monitor *mon, const QObject *data); >> void bdrv_info_stats(Monitor *mon, QObject **ret_data); >> >> +/* disk I/O throttling */ >> +void bdrv_io_limits_enable(BlockDriverState *bs); >> +void bdrv_io_limits_disable(BlockDriverState *bs); >> +bool bdrv_io_limits_enabled(BlockDriverState *bs); >> + >> void bdrv_init(void); >> void bdrv_init_with_whitelist(void); >> BlockDriver *bdrv_find_protocol(const char *filename); >> diff --git a/block_int.h b/block_int.h >> index 201e635..368c776 100644 >> --- a/block_int.h >> +++ b/block_int.h >> @@ -257,6 +257,9 @@ void qemu_aio_release(void *p); >> >> void *qemu_blockalign(BlockDriverState *bs, size_t size); >> >> +void bdrv_set_io_limits(BlockDriverState *bs, >> + BlockIOLimit *io_limits); >> + >> #ifdef _WIN32 >> int is_windows_drive(const char *filename); >> #endif >> diff --git a/blockdev.c b/blockdev.c >> index 2602591..619ae9f 100644 >> --- a/blockdev.c >> +++ b/blockdev.c >> @@ -236,6 +236,7 @@ DriveInfo *drive_init(QemuOpts *opts, int >> default_to_scsi) >> int on_read_error, on_write_error; >> const char *devaddr; >> DriveInfo *dinfo; >> + BlockIOLimit io_limits; >> int snapshot = 0; >> int ret; >> >> @@ -354,6 +355,31 @@ DriveInfo *drive_init(QemuOpts *opts, int >> default_to_scsi) >> } >> } >> >> + /* disk I/O throttling */ >> + io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = >> + qemu_opt_get_number(opts, "bps", 0); >> + io_limits.bps[BLOCK_IO_LIMIT_READ] = >> + qemu_opt_get_number(opts, "bps_rd", 0); >> + io_limits.bps[BLOCK_IO_LIMIT_WRITE] = >> +
Re: [Qemu-devel] [PATCH v8 2/4] block: add the command line support
Am 08.09.2011 12:11, schrieb Zhi Yong Wu: > Signed-off-by: Zhi Yong Wu > --- > block.c | 59 > +++ > block.h |5 > block_int.h |3 ++ > blockdev.c | 29 +++ > qemu-config.c | 24 ++ > qemu-options.hx |1 + > 6 files changed, 121 insertions(+), 0 deletions(-) > > diff --git a/block.c b/block.c > index 43742b7..cd75183 100644 > --- a/block.c > +++ b/block.c > @@ -104,6 +104,57 @@ int is_windows_drive(const char *filename) > } > #endif > > +/* throttling disk I/O limits */ > +void bdrv_io_limits_disable(BlockDriverState *bs) > +{ > +bs->io_limits_enabled = false; > + > +if (bs->block_queue) { > +qemu_block_queue_flush(bs->block_queue); > +qemu_del_block_queue(bs->block_queue); > +bs->block_queue = NULL; > +} > + > +if (bs->block_timer) { > +qemu_del_timer(bs->block_timer); > +qemu_free_timer(bs->block_timer); > +bs->block_timer = NULL; > +} > + > +bs->slice_start = 0; > + > +bs->slice_end = 0; Remove the empty line between slice_start and slice_end? > +} > + > +static void bdrv_block_timer(void *opaque) > +{ > +BlockDriverState *bs = opaque; > +BlockQueue *queue= bs->block_queue; > + > +qemu_block_queue_flush(queue); Hm, didn't really notice it while reading patch 1, but qemu_block_queue_flush() is misleading. It's really something like qemu_block_queue_submit(). > +} > + > +void bdrv_io_limits_enable(BlockDriverState *bs) > +{ > +bs->block_queue = qemu_new_block_queue(); > +bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs); > + > +bs->slice_start = qemu_get_clock_ns(vm_clock); > + > +bs->slice_end = bs->slice_start + BLOCK_IO_SLICE_TIME; > +} Same as above. > + > +bool bdrv_io_limits_enabled(BlockDriverState *bs) > +{ > +BlockIOLimit *io_limits = &bs->io_limits; > +return io_limits->bps[BLOCK_IO_LIMIT_READ] > + || io_limits->bps[BLOCK_IO_LIMIT_WRITE] > + || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] > + || io_limits->iops[BLOCK_IO_LIMIT_READ] > + || io_limits->iops[BLOCK_IO_LIMIT_WRITE] > + || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; > +} > + > /* check if the path starts with ":" */ > static int path_has_protocol(const char *path) > { > @@ -1453,6 +1504,14 @@ void bdrv_get_geometry_hint(BlockDriverState *bs, > *psecs = bs->secs; > } > > +/* throttling disk io limits */ > +void bdrv_set_io_limits(BlockDriverState *bs, > +BlockIOLimit *io_limits) > +{ > +bs->io_limits = *io_limits; > +bs->io_limits_enabled = bdrv_io_limits_enabled(bs); > +} > + > /* Recognize floppy formats */ > typedef struct FDFormat { > FDriveType drive; > diff --git a/block.h b/block.h > index 3ac0b94..a3e69db 100644 > --- a/block.h > +++ b/block.h > @@ -58,6 +58,11 @@ void bdrv_info(Monitor *mon, QObject **ret_data); > void bdrv_stats_print(Monitor *mon, const QObject *data); > void bdrv_info_stats(Monitor *mon, QObject **ret_data); > > +/* disk I/O throttling */ > +void bdrv_io_limits_enable(BlockDriverState *bs); > +void bdrv_io_limits_disable(BlockDriverState *bs); > +bool bdrv_io_limits_enabled(BlockDriverState *bs); > + > void bdrv_init(void); > void bdrv_init_with_whitelist(void); > BlockDriver *bdrv_find_protocol(const char *filename); > diff --git a/block_int.h b/block_int.h > index 201e635..368c776 100644 > --- a/block_int.h > +++ b/block_int.h > @@ -257,6 +257,9 @@ void qemu_aio_release(void *p); > > void *qemu_blockalign(BlockDriverState *bs, size_t size); > > +void bdrv_set_io_limits(BlockDriverState *bs, > +BlockIOLimit *io_limits); > + > #ifdef _WIN32 > int is_windows_drive(const char *filename); > #endif > diff --git a/blockdev.c b/blockdev.c > index 2602591..619ae9f 100644 > --- a/blockdev.c > +++ b/blockdev.c > @@ -236,6 +236,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) > int on_read_error, on_write_error; > const char *devaddr; > DriveInfo *dinfo; > +BlockIOLimit io_limits; > int snapshot = 0; > int ret; > > @@ -354,6 +355,31 @@ DriveInfo *drive_init(QemuOpts *opts, int > default_to_scsi) > } > } > > +/* disk I/O throttling */ > +io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = > + qemu_opt_get_number(opts, "bps", 0); > +io_limits.bps[BLOCK_IO_LIMIT_READ] = > + qemu_opt_get_number(opts, "bps_rd", 0); > +io_limits.bps[BLOCK_IO_LIMIT_WRITE] = > + qemu_opt_get_number(opts, "bps_wr", 0); > +io_limits.iops[BLOCK_IO_LIMIT_TOTAL] = > + qemu_opt_get_number(opts, "iops", 0); > +io_limits.iops[BLOCK_IO_LIMIT_READ] = > + qemu_opt_get_number(opts, "iops_rd", 0); > +io_limits.iops[BLOCK_IO_LIMIT
[Qemu-devel] [PATCH v8 2/4] block: add the command line support
Signed-off-by: Zhi Yong Wu --- block.c | 59 +++ block.h |5 block_int.h |3 ++ blockdev.c | 29 +++ qemu-config.c | 24 ++ qemu-options.hx |1 + 6 files changed, 121 insertions(+), 0 deletions(-) diff --git a/block.c b/block.c index 43742b7..cd75183 100644 --- a/block.c +++ b/block.c @@ -104,6 +104,57 @@ int is_windows_drive(const char *filename) } #endif +/* throttling disk I/O limits */ +void bdrv_io_limits_disable(BlockDriverState *bs) +{ +bs->io_limits_enabled = false; + +if (bs->block_queue) { +qemu_block_queue_flush(bs->block_queue); +qemu_del_block_queue(bs->block_queue); +bs->block_queue = NULL; +} + +if (bs->block_timer) { +qemu_del_timer(bs->block_timer); +qemu_free_timer(bs->block_timer); +bs->block_timer = NULL; +} + +bs->slice_start = 0; + +bs->slice_end = 0; +} + +static void bdrv_block_timer(void *opaque) +{ +BlockDriverState *bs = opaque; +BlockQueue *queue= bs->block_queue; + +qemu_block_queue_flush(queue); +} + +void bdrv_io_limits_enable(BlockDriverState *bs) +{ +bs->block_queue = qemu_new_block_queue(); +bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs); + +bs->slice_start = qemu_get_clock_ns(vm_clock); + +bs->slice_end = bs->slice_start + BLOCK_IO_SLICE_TIME; +} + +bool bdrv_io_limits_enabled(BlockDriverState *bs) +{ +BlockIOLimit *io_limits = &bs->io_limits; +return io_limits->bps[BLOCK_IO_LIMIT_READ] + || io_limits->bps[BLOCK_IO_LIMIT_WRITE] + || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] + || io_limits->iops[BLOCK_IO_LIMIT_READ] + || io_limits->iops[BLOCK_IO_LIMIT_WRITE] + || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; +} + /* check if the path starts with ":" */ static int path_has_protocol(const char *path) { @@ -1453,6 +1504,14 @@ void bdrv_get_geometry_hint(BlockDriverState *bs, *psecs = bs->secs; } +/* throttling disk io limits */ +void bdrv_set_io_limits(BlockDriverState *bs, +BlockIOLimit *io_limits) +{ +bs->io_limits = *io_limits; +bs->io_limits_enabled = bdrv_io_limits_enabled(bs); +} + /* Recognize floppy formats */ typedef struct FDFormat { FDriveType drive; diff --git a/block.h b/block.h index 3ac0b94..a3e69db 100644 --- a/block.h +++ b/block.h @@ -58,6 +58,11 @@ void bdrv_info(Monitor *mon, QObject **ret_data); void bdrv_stats_print(Monitor *mon, const QObject *data); void bdrv_info_stats(Monitor *mon, QObject **ret_data); +/* disk I/O throttling */ +void bdrv_io_limits_enable(BlockDriverState *bs); +void bdrv_io_limits_disable(BlockDriverState *bs); +bool bdrv_io_limits_enabled(BlockDriverState *bs); + void bdrv_init(void); void bdrv_init_with_whitelist(void); BlockDriver *bdrv_find_protocol(const char *filename); diff --git a/block_int.h b/block_int.h index 201e635..368c776 100644 --- a/block_int.h +++ b/block_int.h @@ -257,6 +257,9 @@ void qemu_aio_release(void *p); void *qemu_blockalign(BlockDriverState *bs, size_t size); +void bdrv_set_io_limits(BlockDriverState *bs, +BlockIOLimit *io_limits); + #ifdef _WIN32 int is_windows_drive(const char *filename); #endif diff --git a/blockdev.c b/blockdev.c index 2602591..619ae9f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -236,6 +236,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) int on_read_error, on_write_error; const char *devaddr; DriveInfo *dinfo; +BlockIOLimit io_limits; int snapshot = 0; int ret; @@ -354,6 +355,31 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } } +/* disk I/O throttling */ +io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = + qemu_opt_get_number(opts, "bps", 0); +io_limits.bps[BLOCK_IO_LIMIT_READ] = + qemu_opt_get_number(opts, "bps_rd", 0); +io_limits.bps[BLOCK_IO_LIMIT_WRITE] = + qemu_opt_get_number(opts, "bps_wr", 0); +io_limits.iops[BLOCK_IO_LIMIT_TOTAL] = + qemu_opt_get_number(opts, "iops", 0); +io_limits.iops[BLOCK_IO_LIMIT_READ] = + qemu_opt_get_number(opts, "iops_rd", 0); +io_limits.iops[BLOCK_IO_LIMIT_WRITE] = + qemu_opt_get_number(opts, "iops_wr", 0); + +if (((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] != 0) +&& ((io_limits.bps[BLOCK_IO_LIMIT_READ] != 0) +|| (io_limits.bps[BLOCK_IO_LIMIT_WRITE] != 0))) +|| ((io_limits.iops[BLOCK_IO_LIMIT_TOTAL] != 0) +&& ((io_limits.iops[BLOCK_IO_LIMIT_READ] != 0) +|| (io_limits.iops[BLOCK_IO_LIMIT_WRITE] != 0 { +error_report("bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr)" + "cannot be used at the same time")
[Qemu-devel] [PATCH v8 2/4] block: add the command line support
Signed-off-by: Zhi Yong Wu --- block.c | 59 +++ block.h |5 block_int.h |3 ++ blockdev.c | 29 +++ qemu-config.c | 24 ++ qemu-options.hx |1 + 6 files changed, 121 insertions(+), 0 deletions(-) diff --git a/block.c b/block.c index 43742b7..cd75183 100644 --- a/block.c +++ b/block.c @@ -104,6 +104,57 @@ int is_windows_drive(const char *filename) } #endif +/* throttling disk I/O limits */ +void bdrv_io_limits_disable(BlockDriverState *bs) +{ +bs->io_limits_enabled = false; + +if (bs->block_queue) { +qemu_block_queue_flush(bs->block_queue); +qemu_del_block_queue(bs->block_queue); +bs->block_queue = NULL; +} + +if (bs->block_timer) { +qemu_del_timer(bs->block_timer); +qemu_free_timer(bs->block_timer); +bs->block_timer = NULL; +} + +bs->slice_start = 0; + +bs->slice_end = 0; +} + +static void bdrv_block_timer(void *opaque) +{ +BlockDriverState *bs = opaque; +BlockQueue *queue= bs->block_queue; + +qemu_block_queue_flush(queue); +} + +void bdrv_io_limits_enable(BlockDriverState *bs) +{ +bs->block_queue = qemu_new_block_queue(); +bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs); + +bs->slice_start = qemu_get_clock_ns(vm_clock); + +bs->slice_end = bs->slice_start + BLOCK_IO_SLICE_TIME; +} + +bool bdrv_io_limits_enabled(BlockDriverState *bs) +{ +BlockIOLimit *io_limits = &bs->io_limits; +return io_limits->bps[BLOCK_IO_LIMIT_READ] + || io_limits->bps[BLOCK_IO_LIMIT_WRITE] + || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] + || io_limits->iops[BLOCK_IO_LIMIT_READ] + || io_limits->iops[BLOCK_IO_LIMIT_WRITE] + || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; +} + /* check if the path starts with ":" */ static int path_has_protocol(const char *path) { @@ -1453,6 +1504,14 @@ void bdrv_get_geometry_hint(BlockDriverState *bs, *psecs = bs->secs; } +/* throttling disk io limits */ +void bdrv_set_io_limits(BlockDriverState *bs, +BlockIOLimit *io_limits) +{ +bs->io_limits = *io_limits; +bs->io_limits_enabled = bdrv_io_limits_enabled(bs); +} + /* Recognize floppy formats */ typedef struct FDFormat { FDriveType drive; diff --git a/block.h b/block.h index 3ac0b94..a3e69db 100644 --- a/block.h +++ b/block.h @@ -58,6 +58,11 @@ void bdrv_info(Monitor *mon, QObject **ret_data); void bdrv_stats_print(Monitor *mon, const QObject *data); void bdrv_info_stats(Monitor *mon, QObject **ret_data); +/* disk I/O throttling */ +void bdrv_io_limits_enable(BlockDriverState *bs); +void bdrv_io_limits_disable(BlockDriverState *bs); +bool bdrv_io_limits_enabled(BlockDriverState *bs); + void bdrv_init(void); void bdrv_init_with_whitelist(void); BlockDriver *bdrv_find_protocol(const char *filename); diff --git a/block_int.h b/block_int.h index 201e635..368c776 100644 --- a/block_int.h +++ b/block_int.h @@ -257,6 +257,9 @@ void qemu_aio_release(void *p); void *qemu_blockalign(BlockDriverState *bs, size_t size); +void bdrv_set_io_limits(BlockDriverState *bs, +BlockIOLimit *io_limits); + #ifdef _WIN32 int is_windows_drive(const char *filename); #endif diff --git a/blockdev.c b/blockdev.c index 2602591..619ae9f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -236,6 +236,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) int on_read_error, on_write_error; const char *devaddr; DriveInfo *dinfo; +BlockIOLimit io_limits; int snapshot = 0; int ret; @@ -354,6 +355,31 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } } +/* disk I/O throttling */ +io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = + qemu_opt_get_number(opts, "bps", 0); +io_limits.bps[BLOCK_IO_LIMIT_READ] = + qemu_opt_get_number(opts, "bps_rd", 0); +io_limits.bps[BLOCK_IO_LIMIT_WRITE] = + qemu_opt_get_number(opts, "bps_wr", 0); +io_limits.iops[BLOCK_IO_LIMIT_TOTAL] = + qemu_opt_get_number(opts, "iops", 0); +io_limits.iops[BLOCK_IO_LIMIT_READ] = + qemu_opt_get_number(opts, "iops_rd", 0); +io_limits.iops[BLOCK_IO_LIMIT_WRITE] = + qemu_opt_get_number(opts, "iops_wr", 0); + +if (((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] != 0) +&& ((io_limits.bps[BLOCK_IO_LIMIT_READ] != 0) +|| (io_limits.bps[BLOCK_IO_LIMIT_WRITE] != 0))) +|| ((io_limits.iops[BLOCK_IO_LIMIT_TOTAL] != 0) +&& ((io_limits.iops[BLOCK_IO_LIMIT_READ] != 0) +|| (io_limits.iops[BLOCK_IO_LIMIT_WRITE] != 0 { +error_report("bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr)" + "cannot be used at the same time")