qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

throttle.c (20285B)


      1 /*
      2  * QEMU throttling infrastructure
      3  *
      4  * Copyright (C) Nodalink, EURL. 2013-2014
      5  * Copyright (C) Igalia, S.L. 2015
      6  *
      7  * Authors:
      8  *   BenoƮt Canet <benoit.canet@nodalink.com>
      9  *   Alberto Garcia <berto@igalia.com>
     10  *
     11  * This program is free software; you can redistribute it and/or
     12  * modify it under the terms of the GNU General Public License as
     13  * published by the Free Software Foundation; either version 2 or
     14  * (at your option) version 3 of the License.
     15  *
     16  * This program is distributed in the hope that it will be useful,
     17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19  * GNU General Public License for more details.
     20  *
     21  * You should have received a copy of the GNU General Public License
     22  * along with this program; if not, see <http://www.gnu.org/licenses/>.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "qapi/error.h"
     27 #include "qemu/throttle.h"
     28 #include "qemu/timer.h"
     29 #include "block/aio.h"
     30 
     31 /* This function make a bucket leak
     32  *
     33  * @bkt:   the bucket to make leak
     34  * @delta_ns: the time delta
     35  */
     36 void throttle_leak_bucket(LeakyBucket *bkt, int64_t delta_ns)
     37 {
     38     double leak;
     39 
     40     /* compute how much to leak */
     41     leak = (bkt->avg * (double) delta_ns) / NANOSECONDS_PER_SECOND;
     42 
     43     /* make the bucket leak */
     44     bkt->level = MAX(bkt->level - leak, 0);
     45 
     46     /* if we allow bursts for more than one second we also need to
     47      * keep track of bkt->burst_level so the bkt->max goal per second
     48      * is attained */
     49     if (bkt->burst_length > 1) {
     50         leak = (bkt->max * (double) delta_ns) / NANOSECONDS_PER_SECOND;
     51         bkt->burst_level = MAX(bkt->burst_level - leak, 0);
     52     }
     53 }
     54 
     55 /* Calculate the time delta since last leak and make proportionals leaks
     56  *
     57  * @now:      the current timestamp in ns
     58  */
     59 static void throttle_do_leak(ThrottleState *ts, int64_t now)
     60 {
     61     /* compute the time elapsed since the last leak */
     62     int64_t delta_ns = now - ts->previous_leak;
     63     int i;
     64 
     65     ts->previous_leak = now;
     66 
     67     if (delta_ns <= 0) {
     68         return;
     69     }
     70 
     71     /* make each bucket leak */
     72     for (i = 0; i < BUCKETS_COUNT; i++) {
     73         throttle_leak_bucket(&ts->cfg.buckets[i], delta_ns);
     74     }
     75 }
     76 
     77 /* do the real job of computing the time to wait
     78  *
     79  * @limit: the throttling limit
     80  * @extra: the number of operation to delay
     81  * @ret:   the time to wait in ns
     82  */
     83 static int64_t throttle_do_compute_wait(double limit, double extra)
     84 {
     85     double wait = extra * NANOSECONDS_PER_SECOND;
     86     wait /= limit;
     87     return wait;
     88 }
     89 
     90 /* This function compute the wait time in ns that a leaky bucket should trigger
     91  *
     92  * @bkt: the leaky bucket we operate on
     93  * @ret: the resulting wait time in ns or 0 if the operation can go through
     94  */
     95 int64_t throttle_compute_wait(LeakyBucket *bkt)
     96 {
     97     double extra; /* the number of extra units blocking the io */
     98     double bucket_size;   /* I/O before throttling to bkt->avg */
     99     double burst_bucket_size; /* Before throttling to bkt->max */
    100 
    101     if (!bkt->avg) {
    102         return 0;
    103     }
    104 
    105     if (!bkt->max) {
    106         /* If bkt->max is 0 we still want to allow short bursts of I/O
    107          * from the guest, otherwise every other request will be throttled
    108          * and performance will suffer considerably. */
    109         bucket_size = (double) bkt->avg / 10;
    110         burst_bucket_size = 0;
    111     } else {
    112         /* If we have a burst limit then we have to wait until all I/O
    113          * at burst rate has finished before throttling to bkt->avg */
    114         bucket_size = bkt->max * bkt->burst_length;
    115         burst_bucket_size = (double) bkt->max / 10;
    116     }
    117 
    118     /* If the main bucket is full then we have to wait */
    119     extra = bkt->level - bucket_size;
    120     if (extra > 0) {
    121         return throttle_do_compute_wait(bkt->avg, extra);
    122     }
    123 
    124     /* If the main bucket is not full yet we still have to check the
    125      * burst bucket in order to enforce the burst limit */
    126     if (bkt->burst_length > 1) {
    127         assert(bkt->max > 0); /* see throttle_is_valid() */
    128         extra = bkt->burst_level - burst_bucket_size;
    129         if (extra > 0) {
    130             return throttle_do_compute_wait(bkt->max, extra);
    131         }
    132     }
    133 
    134     return 0;
    135 }
    136 
    137 /* This function compute the time that must be waited while this IO
    138  *
    139  * @is_write:   true if the current IO is a write, false if it's a read
    140  * @ret:        time to wait
    141  */
    142 static int64_t throttle_compute_wait_for(ThrottleState *ts,
    143                                          bool is_write)
    144 {
    145     BucketType to_check[2][4] = { {THROTTLE_BPS_TOTAL,
    146                                    THROTTLE_OPS_TOTAL,
    147                                    THROTTLE_BPS_READ,
    148                                    THROTTLE_OPS_READ},
    149                                   {THROTTLE_BPS_TOTAL,
    150                                    THROTTLE_OPS_TOTAL,
    151                                    THROTTLE_BPS_WRITE,
    152                                    THROTTLE_OPS_WRITE}, };
    153     int64_t wait, max_wait = 0;
    154     int i;
    155 
    156     for (i = 0; i < 4; i++) {
    157         BucketType index = to_check[is_write][i];
    158         wait = throttle_compute_wait(&ts->cfg.buckets[index]);
    159         if (wait > max_wait) {
    160             max_wait = wait;
    161         }
    162     }
    163 
    164     return max_wait;
    165 }
    166 
    167 /* compute the timer for this type of operation
    168  *
    169  * @is_write:   the type of operation
    170  * @now:        the current clock timestamp
    171  * @next_timestamp: the resulting timer
    172  * @ret:        true if a timer must be set
    173  */
    174 static bool throttle_compute_timer(ThrottleState *ts,
    175                                    bool is_write,
    176                                    int64_t now,
    177                                    int64_t *next_timestamp)
    178 {
    179     int64_t wait;
    180 
    181     /* leak proportionally to the time elapsed */
    182     throttle_do_leak(ts, now);
    183 
    184     /* compute the wait time if any */
    185     wait = throttle_compute_wait_for(ts, is_write);
    186 
    187     /* if the code must wait compute when the next timer should fire */
    188     if (wait) {
    189         *next_timestamp = now + wait;
    190         return true;
    191     }
    192 
    193     /* else no need to wait at all */
    194     *next_timestamp = now;
    195     return false;
    196 }
    197 
    198 /* Add timers to event loop */
    199 void throttle_timers_attach_aio_context(ThrottleTimers *tt,
    200                                         AioContext *new_context)
    201 {
    202     tt->timers[0] = aio_timer_new(new_context, tt->clock_type, SCALE_NS,
    203                                   tt->read_timer_cb, tt->timer_opaque);
    204     tt->timers[1] = aio_timer_new(new_context, tt->clock_type, SCALE_NS,
    205                                   tt->write_timer_cb, tt->timer_opaque);
    206 }
    207 
    208 /*
    209  * Initialize the ThrottleConfig structure to a valid state
    210  * @cfg: the config to initialize
    211  */
    212 void throttle_config_init(ThrottleConfig *cfg)
    213 {
    214     unsigned i;
    215     memset(cfg, 0, sizeof(*cfg));
    216     for (i = 0; i < BUCKETS_COUNT; i++) {
    217         cfg->buckets[i].burst_length = 1;
    218     }
    219 }
    220 
    221 /* To be called first on the ThrottleState */
    222 void throttle_init(ThrottleState *ts)
    223 {
    224     memset(ts, 0, sizeof(ThrottleState));
    225     throttle_config_init(&ts->cfg);
    226 }
    227 
    228 /* To be called first on the ThrottleTimers */
    229 void throttle_timers_init(ThrottleTimers *tt,
    230                           AioContext *aio_context,
    231                           QEMUClockType clock_type,
    232                           QEMUTimerCB *read_timer_cb,
    233                           QEMUTimerCB *write_timer_cb,
    234                           void *timer_opaque)
    235 {
    236     memset(tt, 0, sizeof(ThrottleTimers));
    237 
    238     tt->clock_type = clock_type;
    239     tt->read_timer_cb = read_timer_cb;
    240     tt->write_timer_cb = write_timer_cb;
    241     tt->timer_opaque = timer_opaque;
    242     throttle_timers_attach_aio_context(tt, aio_context);
    243 }
    244 
    245 /* destroy a timer */
    246 static void throttle_timer_destroy(QEMUTimer **timer)
    247 {
    248     assert(*timer != NULL);
    249 
    250     timer_free(*timer);
    251     *timer = NULL;
    252 }
    253 
    254 /* Remove timers from event loop */
    255 void throttle_timers_detach_aio_context(ThrottleTimers *tt)
    256 {
    257     int i;
    258 
    259     for (i = 0; i < 2; i++) {
    260         throttle_timer_destroy(&tt->timers[i]);
    261     }
    262 }
    263 
    264 /* To be called last on the ThrottleTimers */
    265 void throttle_timers_destroy(ThrottleTimers *tt)
    266 {
    267     throttle_timers_detach_aio_context(tt);
    268 }
    269 
    270 /* is any throttling timer configured */
    271 bool throttle_timers_are_initialized(ThrottleTimers *tt)
    272 {
    273     if (tt->timers[0]) {
    274         return true;
    275     }
    276 
    277     return false;
    278 }
    279 
    280 /* Does any throttling must be done
    281  *
    282  * @cfg: the throttling configuration to inspect
    283  * @ret: true if throttling must be done else false
    284  */
    285 bool throttle_enabled(ThrottleConfig *cfg)
    286 {
    287     int i;
    288 
    289     for (i = 0; i < BUCKETS_COUNT; i++) {
    290         if (cfg->buckets[i].avg > 0) {
    291             return true;
    292         }
    293     }
    294 
    295     return false;
    296 }
    297 
    298 /* check if a throttling configuration is valid
    299  * @cfg: the throttling configuration to inspect
    300  * @ret: true if valid else false
    301  * @errp: error object
    302  */
    303 bool throttle_is_valid(ThrottleConfig *cfg, Error **errp)
    304 {
    305     int i;
    306     bool bps_flag, ops_flag;
    307     bool bps_max_flag, ops_max_flag;
    308 
    309     bps_flag = cfg->buckets[THROTTLE_BPS_TOTAL].avg &&
    310                (cfg->buckets[THROTTLE_BPS_READ].avg ||
    311                 cfg->buckets[THROTTLE_BPS_WRITE].avg);
    312 
    313     ops_flag = cfg->buckets[THROTTLE_OPS_TOTAL].avg &&
    314                (cfg->buckets[THROTTLE_OPS_READ].avg ||
    315                 cfg->buckets[THROTTLE_OPS_WRITE].avg);
    316 
    317     bps_max_flag = cfg->buckets[THROTTLE_BPS_TOTAL].max &&
    318                   (cfg->buckets[THROTTLE_BPS_READ].max  ||
    319                    cfg->buckets[THROTTLE_BPS_WRITE].max);
    320 
    321     ops_max_flag = cfg->buckets[THROTTLE_OPS_TOTAL].max &&
    322                    (cfg->buckets[THROTTLE_OPS_READ].max ||
    323                    cfg->buckets[THROTTLE_OPS_WRITE].max);
    324 
    325     if (bps_flag || ops_flag || bps_max_flag || ops_max_flag) {
    326         error_setg(errp, "bps/iops/max total values and read/write values"
    327                    " cannot be used at the same time");
    328         return false;
    329     }
    330 
    331     if (cfg->op_size &&
    332         !cfg->buckets[THROTTLE_OPS_TOTAL].avg &&
    333         !cfg->buckets[THROTTLE_OPS_READ].avg &&
    334         !cfg->buckets[THROTTLE_OPS_WRITE].avg) {
    335         error_setg(errp, "iops size requires an iops value to be set");
    336         return false;
    337     }
    338 
    339     for (i = 0; i < BUCKETS_COUNT; i++) {
    340         LeakyBucket *bkt = &cfg->buckets[i];
    341         if (bkt->avg > THROTTLE_VALUE_MAX || bkt->max > THROTTLE_VALUE_MAX) {
    342             error_setg(errp, "bps/iops/max values must be within [0, %lld]",
    343                        THROTTLE_VALUE_MAX);
    344             return false;
    345         }
    346 
    347         if (!bkt->burst_length) {
    348             error_setg(errp, "the burst length cannot be 0");
    349             return false;
    350         }
    351 
    352         if (bkt->burst_length > 1 && !bkt->max) {
    353             error_setg(errp, "burst length set without burst rate");
    354             return false;
    355         }
    356 
    357         if (bkt->max && bkt->burst_length > THROTTLE_VALUE_MAX / bkt->max) {
    358             error_setg(errp, "burst length too high for this burst rate");
    359             return false;
    360         }
    361 
    362         if (bkt->max && !bkt->avg) {
    363             error_setg(errp, "bps_max/iops_max require corresponding"
    364                        " bps/iops values");
    365             return false;
    366         }
    367 
    368         if (bkt->max && bkt->max < bkt->avg) {
    369             error_setg(errp, "bps_max/iops_max cannot be lower than bps/iops");
    370             return false;
    371         }
    372     }
    373 
    374     return true;
    375 }
    376 
    377 /* Used to configure the throttle
    378  *
    379  * @ts: the throttle state we are working on
    380  * @clock_type: the group's clock_type
    381  * @cfg: the config to set
    382  */
    383 void throttle_config(ThrottleState *ts,
    384                      QEMUClockType clock_type,
    385                      ThrottleConfig *cfg)
    386 {
    387     int i;
    388 
    389     ts->cfg = *cfg;
    390 
    391     /* Zero bucket level */
    392     for (i = 0; i < BUCKETS_COUNT; i++) {
    393         ts->cfg.buckets[i].level = 0;
    394         ts->cfg.buckets[i].burst_level = 0;
    395     }
    396 
    397     ts->previous_leak = qemu_clock_get_ns(clock_type);
    398 }
    399 
    400 /* used to get config
    401  *
    402  * @ts:  the throttle state we are working on
    403  * @cfg: the config to write
    404  */
    405 void throttle_get_config(ThrottleState *ts, ThrottleConfig *cfg)
    406 {
    407     *cfg = ts->cfg;
    408 }
    409 
    410 
    411 /* Schedule the read or write timer if needed
    412  *
    413  * NOTE: this function is not unit tested due to it's usage of timer_mod
    414  *
    415  * @tt:       the timers structure
    416  * @is_write: the type of operation (read/write)
    417  * @ret:      true if the timer has been scheduled else false
    418  */
    419 bool throttle_schedule_timer(ThrottleState *ts,
    420                              ThrottleTimers *tt,
    421                              bool is_write)
    422 {
    423     int64_t now = qemu_clock_get_ns(tt->clock_type);
    424     int64_t next_timestamp;
    425     bool must_wait;
    426 
    427     must_wait = throttle_compute_timer(ts,
    428                                        is_write,
    429                                        now,
    430                                        &next_timestamp);
    431 
    432     /* request not throttled */
    433     if (!must_wait) {
    434         return false;
    435     }
    436 
    437     /* request throttled and timer pending -> do nothing */
    438     if (timer_pending(tt->timers[is_write])) {
    439         return true;
    440     }
    441 
    442     /* request throttled and timer not pending -> arm timer */
    443     timer_mod(tt->timers[is_write], next_timestamp);
    444     return true;
    445 }
    446 
    447 /* do the accounting for this operation
    448  *
    449  * @is_write: the type of operation (read/write)
    450  * @size:     the size of the operation
    451  */
    452 void throttle_account(ThrottleState *ts, bool is_write, uint64_t size)
    453 {
    454     const BucketType bucket_types_size[2][2] = {
    455         { THROTTLE_BPS_TOTAL, THROTTLE_BPS_READ },
    456         { THROTTLE_BPS_TOTAL, THROTTLE_BPS_WRITE }
    457     };
    458     const BucketType bucket_types_units[2][2] = {
    459         { THROTTLE_OPS_TOTAL, THROTTLE_OPS_READ },
    460         { THROTTLE_OPS_TOTAL, THROTTLE_OPS_WRITE }
    461     };
    462     double units = 1.0;
    463     unsigned i;
    464 
    465     /* if cfg.op_size is defined and smaller than size we compute unit count */
    466     if (ts->cfg.op_size && size > ts->cfg.op_size) {
    467         units = (double) size / ts->cfg.op_size;
    468     }
    469 
    470     for (i = 0; i < 2; i++) {
    471         LeakyBucket *bkt;
    472 
    473         bkt = &ts->cfg.buckets[bucket_types_size[is_write][i]];
    474         bkt->level += size;
    475         if (bkt->burst_length > 1) {
    476             bkt->burst_level += size;
    477         }
    478 
    479         bkt = &ts->cfg.buckets[bucket_types_units[is_write][i]];
    480         bkt->level += units;
    481         if (bkt->burst_length > 1) {
    482             bkt->burst_level += units;
    483         }
    484     }
    485 }
    486 
    487 /* return a ThrottleConfig based on the options in a ThrottleLimits
    488  *
    489  * @arg:    the ThrottleLimits object to read from
    490  * @cfg:    the ThrottleConfig to edit
    491  * @errp:   error object
    492  */
    493 void throttle_limits_to_config(ThrottleLimits *arg, ThrottleConfig *cfg,
    494                                Error **errp)
    495 {
    496     if (arg->has_bps_total) {
    497         cfg->buckets[THROTTLE_BPS_TOTAL].avg = arg->bps_total;
    498     }
    499     if (arg->has_bps_read) {
    500         cfg->buckets[THROTTLE_BPS_READ].avg  = arg->bps_read;
    501     }
    502     if (arg->has_bps_write) {
    503         cfg->buckets[THROTTLE_BPS_WRITE].avg = arg->bps_write;
    504     }
    505 
    506     if (arg->has_iops_total) {
    507         cfg->buckets[THROTTLE_OPS_TOTAL].avg = arg->iops_total;
    508     }
    509     if (arg->has_iops_read) {
    510         cfg->buckets[THROTTLE_OPS_READ].avg  = arg->iops_read;
    511     }
    512     if (arg->has_iops_write) {
    513         cfg->buckets[THROTTLE_OPS_WRITE].avg = arg->iops_write;
    514     }
    515 
    516     if (arg->has_bps_total_max) {
    517         cfg->buckets[THROTTLE_BPS_TOTAL].max = arg->bps_total_max;
    518     }
    519     if (arg->has_bps_read_max) {
    520         cfg->buckets[THROTTLE_BPS_READ].max = arg->bps_read_max;
    521     }
    522     if (arg->has_bps_write_max) {
    523         cfg->buckets[THROTTLE_BPS_WRITE].max = arg->bps_write_max;
    524     }
    525     if (arg->has_iops_total_max) {
    526         cfg->buckets[THROTTLE_OPS_TOTAL].max = arg->iops_total_max;
    527     }
    528     if (arg->has_iops_read_max) {
    529         cfg->buckets[THROTTLE_OPS_READ].max = arg->iops_read_max;
    530     }
    531     if (arg->has_iops_write_max) {
    532         cfg->buckets[THROTTLE_OPS_WRITE].max = arg->iops_write_max;
    533     }
    534 
    535     if (arg->has_bps_total_max_length) {
    536         if (arg->bps_total_max_length > UINT_MAX) {
    537             error_setg(errp, "bps-total-max-length value must be in"
    538                              " the range [0, %u]", UINT_MAX);
    539             return;
    540         }
    541         cfg->buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_total_max_length;
    542     }
    543     if (arg->has_bps_read_max_length) {
    544         if (arg->bps_read_max_length > UINT_MAX) {
    545             error_setg(errp, "bps-read-max-length value must be in"
    546                              " the range [0, %u]", UINT_MAX);
    547             return;
    548         }
    549         cfg->buckets[THROTTLE_BPS_READ].burst_length = arg->bps_read_max_length;
    550     }
    551     if (arg->has_bps_write_max_length) {
    552         if (arg->bps_write_max_length > UINT_MAX) {
    553             error_setg(errp, "bps-write-max-length value must be in"
    554                              " the range [0, %u]", UINT_MAX);
    555             return;
    556         }
    557         cfg->buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_write_max_length;
    558     }
    559     if (arg->has_iops_total_max_length) {
    560         if (arg->iops_total_max_length > UINT_MAX) {
    561             error_setg(errp, "iops-total-max-length value must be in"
    562                              " the range [0, %u]", UINT_MAX);
    563             return;
    564         }
    565         cfg->buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_total_max_length;
    566     }
    567     if (arg->has_iops_read_max_length) {
    568         if (arg->iops_read_max_length > UINT_MAX) {
    569             error_setg(errp, "iops-read-max-length value must be in"
    570                              " the range [0, %u]", UINT_MAX);
    571             return;
    572         }
    573         cfg->buckets[THROTTLE_OPS_READ].burst_length = arg->iops_read_max_length;
    574     }
    575     if (arg->has_iops_write_max_length) {
    576         if (arg->iops_write_max_length > UINT_MAX) {
    577             error_setg(errp, "iops-write-max-length value must be in"
    578                              " the range [0, %u]", UINT_MAX);
    579             return;
    580         }
    581         cfg->buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_write_max_length;
    582     }
    583 
    584     if (arg->has_iops_size) {
    585         cfg->op_size = arg->iops_size;
    586     }
    587 
    588     throttle_is_valid(cfg, errp);
    589 }
    590 
    591 /* write the options of a ThrottleConfig to a ThrottleLimits
    592  *
    593  * @cfg:    the ThrottleConfig to read from
    594  * @var:    the ThrottleLimits to write to
    595  */
    596 void throttle_config_to_limits(ThrottleConfig *cfg, ThrottleLimits *var)
    597 {
    598     var->bps_total               = cfg->buckets[THROTTLE_BPS_TOTAL].avg;
    599     var->bps_read                = cfg->buckets[THROTTLE_BPS_READ].avg;
    600     var->bps_write               = cfg->buckets[THROTTLE_BPS_WRITE].avg;
    601     var->iops_total              = cfg->buckets[THROTTLE_OPS_TOTAL].avg;
    602     var->iops_read               = cfg->buckets[THROTTLE_OPS_READ].avg;
    603     var->iops_write              = cfg->buckets[THROTTLE_OPS_WRITE].avg;
    604     var->bps_total_max           = cfg->buckets[THROTTLE_BPS_TOTAL].max;
    605     var->bps_read_max            = cfg->buckets[THROTTLE_BPS_READ].max;
    606     var->bps_write_max           = cfg->buckets[THROTTLE_BPS_WRITE].max;
    607     var->iops_total_max          = cfg->buckets[THROTTLE_OPS_TOTAL].max;
    608     var->iops_read_max           = cfg->buckets[THROTTLE_OPS_READ].max;
    609     var->iops_write_max          = cfg->buckets[THROTTLE_OPS_WRITE].max;
    610     var->bps_total_max_length    = cfg->buckets[THROTTLE_BPS_TOTAL].burst_length;
    611     var->bps_read_max_length     = cfg->buckets[THROTTLE_BPS_READ].burst_length;
    612     var->bps_write_max_length    = cfg->buckets[THROTTLE_BPS_WRITE].burst_length;
    613     var->iops_total_max_length   = cfg->buckets[THROTTLE_OPS_TOTAL].burst_length;
    614     var->iops_read_max_length    = cfg->buckets[THROTTLE_OPS_READ].burst_length;
    615     var->iops_write_max_length   = cfg->buckets[THROTTLE_OPS_WRITE].burst_length;
    616     var->iops_size               = cfg->op_size;
    617 
    618     var->has_bps_total = true;
    619     var->has_bps_read = true;
    620     var->has_bps_write = true;
    621     var->has_iops_total = true;
    622     var->has_iops_read = true;
    623     var->has_iops_write = true;
    624     var->has_bps_total_max = true;
    625     var->has_bps_read_max = true;
    626     var->has_bps_write_max = true;
    627     var->has_iops_total_max = true;
    628     var->has_iops_read_max = true;
    629     var->has_iops_write_max = true;
    630     var->has_bps_read_max_length = true;
    631     var->has_bps_total_max_length = true;
    632     var->has_bps_write_max_length = true;
    633     var->has_iops_total_max_length = true;
    634     var->has_iops_read_max_length = true;
    635     var->has_iops_write_max_length = true;
    636     var->has_iops_size = true;
    637 }