Skip to content
Snippets Groups Projects
  1. Feb 03, 2021
    • Vladimir Sementsov-Ogievskiy's avatar
      block/throttle-groups: throttle_group_co_io_limits_intercept(): 64bit bytes · 801625e6
      Vladimir Sementsov-Ogievskiy authored
      
      The function is called from 64bit io handlers, and bytes is just passed
      to throttle_account() which is 64bit too (unsigned though). So, let's
      convert intermediate argument to 64bit too.
      
      This patch is a first in the 64-bit-blocklayer series, so we are
      generally moving to int64_t for both offset and bytes parameters on all
      io paths. Main motivation is realization of 64-bit write_zeroes
      operation for fast zeroing large disk chunks, up to the whole disk.
      
      We chose signed type, to be consistent with off_t (which is signed) and
      with possibility for signed return type (where negative value means
      error).
      
      Patch-correctness audit by Eric Blake:
      
        Caller has 32-bit, this patch now causes widening which is safe:
        block/block-backend.c: blk_do_preadv() passes 'unsigned int'
        block/block-backend.c: blk_do_pwritev_part() passes 'unsigned int'
        block/throttle.c: throttle_co_pwrite_zeroes() passes 'int'
        block/throttle.c: throttle_co_pdiscard() passes 'int'
      
        Caller has 64-bit, this patch fixes potential bug where pre-patch
        could narrow, except it's easy enough to trace that callers are still
        capped at 2G actions:
        block/throttle.c: throttle_co_preadv() passes 'uint64_t'
        block/throttle.c: throttle_co_pwritev() passes 'uint64_t'
      
        Implementation in question: block/throttle-groups.c
        throttle_group_co_io_limits_intercept() takes 'unsigned int bytes'
        and uses it: argument to util/throttle.c throttle_account(uint64_t)
      
        All safe: it patches a latent bug, and does not introduce any 64-bit
        gotchas once throttle_co_p{read,write}v are relaxed, and assuming
        throttle_account() is not buggy.
      
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
      Message-Id: <20201211183934.169161-7-vsementsov@virtuozzo.com>
      Signed-off-by: default avatarEric Blake <eblake@redhat.com>
      801625e6
  2. Dec 11, 2020
  3. Sep 23, 2020
    • Stefan Hajnoczi's avatar
      qemu/atomic.h: rename atomic_ to qatomic_ · d73415a3
      Stefan Hajnoczi authored
      
      clang's C11 atomic_fetch_*() functions only take a C11 atomic type
      pointer argument. QEMU uses direct types (int, etc) and this causes a
      compiler error when a QEMU code calls these functions in a source file
      that also included <stdatomic.h> via a system header file:
      
        $ CC=clang CXX=clang++ ./configure ... && make
        ../util/async.c:79:17: error: address argument to atomic operation must be a pointer to _Atomic type ('unsigned int *' invalid)
      
      Avoid using atomic_*() names in QEMU's atomic.h since that namespace is
      used by <stdatomic.h>. Prefix QEMU's APIs with 'q' so that atomic.h
      and <stdatomic.h> can co-exist. I checked /usr/include on my machine and
      searched GitHub for existing "qatomic_" users but there seem to be none.
      
      This patch was generated using:
      
        $ git grep -h -o '\<atomic\(64\)\?_[a-z0-9_]\+' include/qemu/atomic.h | \
          sort -u >/tmp/changed_identifiers
        $ for identifier in $(</tmp/changed_identifiers); do
              sed -i "s%\<$identifier\>%q$identifier%g" \
                  $(git grep -I -l "\<$identifier\>")
          done
      
      I manually fixed line-wrap issues and misaligned rST tables.
      
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      Reviewed-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
      Acked-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
      Message-Id: <20200923105646.47864-1-stefanha@redhat.com>
      d73415a3
  4. Aug 27, 2020
  5. Jul 21, 2020
  6. Jul 10, 2020
    • Markus Armbruster's avatar
      error: Eliminate error_propagate() with Coccinelle, part 1 · 668f62ec
      Markus Armbruster authored
      
      When all we do with an Error we receive into a local variable is
      propagating to somewhere else, we can just as well receive it there
      right away.  Convert
      
          if (!foo(..., &err)) {
              ...
              error_propagate(errp, err);
              ...
              return ...
          }
      
      to
      
          if (!foo(..., errp)) {
              ...
              ...
              return ...
          }
      
      where nothing else needs @err.  Coccinelle script:
      
          @rule1 forall@
          identifier fun, err, errp, lbl;
          expression list args, args2;
          binary operator op;
          constant c1, c2;
          symbol false;
          @@
               if (
          (
          -        fun(args, &err, args2)
          +        fun(args, errp, args2)
          |
          -        !fun(args, &err, args2)
          +        !fun(args, errp, args2)
          |
          -        fun(args, &err, args2) op c1
          +        fun(args, errp, args2) op c1
          )
                  )
               {
                   ... when != err
                       when != lbl:
                       when strict
          -        error_propagate(errp, err);
                   ... when != err
          (
                   return;
          |
                   return c2;
          |
                   return false;
          )
               }
      
          @rule2 forall@
          identifier fun, err, errp, lbl;
          expression list args, args2;
          expression var;
          binary operator op;
          constant c1, c2;
          symbol false;
          @@
          -    var = fun(args, &err, args2);
          +    var = fun(args, errp, args2);
               ... when != err
               if (
          (
                   var
          |
                   !var
          |
                   var op c1
          )
                  )
               {
                   ... when != err
                       when != lbl:
                       when strict
          -        error_propagate(errp, err);
                   ... when != err
          (
                   return;
          |
                   return c2;
          |
                   return false;
          |
                   return var;
          )
               }
      
          @depends on rule1 || rule2@
          identifier err;
          @@
          -    Error *err = NULL;
               ... when != err
      
      Not exactly elegant, I'm afraid.
      
      The "when != lbl:" is necessary to avoid transforming
      
               if (fun(args, &err)) {
                   goto out
               }
               ...
           out:
               error_propagate(errp, err);
      
      even though other paths to label out still need the error_propagate().
      For an actual example, see sclp_realize().
      
      Without the "when strict", Coccinelle transforms vfio_msix_setup(),
      incorrectly.  I don't know what exactly "when strict" does, only that
      it helps here.
      
      The match of return is narrower than what I want, but I can't figure
      out how to express "return where the operand doesn't use @err".  For
      an example where it's too narrow, see vfio_intx_enable().
      
      Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
      confused by ARMSSE being used both as typedef and function-like macro
      there.  Converted manually.
      
      Line breaks tidied up manually.  One nested declaration of @local_err
      deleted manually.  Preexisting unwanted blank line dropped in
      hw/riscv/sifive_e.c.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Message-Id: <20200707160613.848843-35-armbru@redhat.com>
      668f62ec
    • Markus Armbruster's avatar
      error: Avoid unnecessary error_propagate() after error_setg() · dcfe4805
      Markus Armbruster authored
      
      Replace
      
          error_setg(&err, ...);
          error_propagate(errp, err);
      
      by
      
          error_setg(errp, ...);
      
      Related pattern:
      
          if (...) {
              error_setg(&err, ...);
              goto out;
          }
          ...
       out:
          error_propagate(errp, err);
          return;
      
      When all paths to label out are that way, replace by
      
          if (...) {
              error_setg(errp, ...);
              return;
          }
      
      and delete the label along with the error_propagate().
      
      When we have at most one other path that actually needs to propagate,
      and maybe one at the end that where propagation is unnecessary, e.g.
      
          foo(..., &err);
          if (err) {
              goto out;
          }
          ...
          bar(..., &err);
       out:
          error_propagate(errp, err);
          return;
      
      move the error_propagate() to where it's needed, like
      
          if (...) {
              foo(..., &err);
              error_propagate(errp, err);
              return;
          }
          ...
          bar(..., errp);
          return;
      
      and transform the error_setg() as above.
      
      In some places, the transformation results in obviously unnecessary
      error_propagate().  The next few commits will eliminate them.
      
      Bonus: the elimination of gotos will make later patches in this series
      easier to review.
      
      Candidates for conversion tracked down with this Coccinelle script:
      
          @@
          identifier err, errp;
          expression list args;
          @@
          -    error_setg(&err, args);
          +    error_setg(errp, args);
               ... when != err
               error_propagate(errp, err);
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Message-Id: <20200707160613.848843-34-armbru@redhat.com>
      dcfe4805
    • Markus Armbruster's avatar
      qapi: Use returned bool to check for failure, manual part · 14217038
      Markus Armbruster authored
      
      The previous commit used Coccinelle to convert from checking the Error
      object to checking the return value.  Convert a few more manually.
      Also tweak control flow in places to conform to the conventional "if
      error bail out" pattern.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20200707160613.848843-20-armbru@redhat.com>
      14217038
    • Markus Armbruster's avatar
      qapi: Use returned bool to check for failure, Coccinelle part · 62a35aaa
      Markus Armbruster authored
      
      The previous commit enables conversion of
      
          visit_foo(..., &err);
          if (err) {
              ...
          }
      
      to
      
          if (!visit_foo(..., errp)) {
              ...
          }
      
      for visitor functions that now return true / false on success / error.
      Coccinelle script:
      
          @@
          identifier fun =~ "check_list|input_type_enum|lv_start_struct|lv_type_bool|lv_type_int64|lv_type_str|lv_type_uint64|output_type_enum|parse_type_bool|parse_type_int64|parse_type_null|parse_type_number|parse_type_size|parse_type_str|parse_type_uint64|print_type_bool|print_type_int64|print_type_null|print_type_number|print_type_size|print_type_str|print_type_uint64|qapi_clone_start_alternate|qapi_clone_start_list|qapi_clone_start_struct|qapi_clone_type_bool|qapi_clone_type_int64|qapi_clone_type_null|qapi_clone_type_number|qapi_clone_type_str|qapi_clone_type_uint64|qapi_dealloc_start_list|qapi_dealloc_start_struct|qapi_dealloc_type_anything|qapi_dealloc_type_bool|qapi_dealloc_type_int64|qapi_dealloc_type_null|qapi_dealloc_type_number|qapi_dealloc_type_str|qapi_dealloc_type_uint64|qobject_input_check_list|qobject_input_check_struct|qobject_input_start_alternate|qobject_input_start_list|qobject_input_start_struct|qobject_input_type_any|qobject_input_type_bool|qobject_input_type_bool_keyval|qobject_input_type_int64|qobject_input_type_int64_keyval|qobject_input_type_null|qobject_input_type_number|qobject_input_type_number_keyval|qobject_input_type_size_keyval|qobject_input_type_str|qobject_input_type_str_keyval|qobject_input_type_uint64|qobject_input_type_uint64_keyval|qobject_output_start_list|qobject_output_start_struct|qobject_output_type_any|qobject_output_type_bool|qobject_output_type_int64|qobject_output_type_null|qobject_output_type_number|qobject_output_type_str|qobject_output_type_uint64|start_list|visit_check_list|visit_check_struct|visit_start_alternate|visit_start_list|visit_start_struct|visit_type_.*";
          expression list args;
          typedef Error;
          Error *err;
          @@
          -    fun(args, &err);
          -    if (err)
          +    if (!fun(args, &err))
               {
                   ...
               }
      
      A few line breaks tidied up manually.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20200707160613.848843-19-armbru@redhat.com>
      62a35aaa
  7. May 15, 2020
    • Markus Armbruster's avatar
      qom: Drop parameter @errp of object_property_add() & friends · d2623129
      Markus Armbruster authored
      
      The only way object_property_add() can fail is when a property with
      the same name already exists.  Since our property names are all
      hardcoded, failure is a programming error, and the appropriate way to
      handle it is passing &error_abort.
      
      Same for its variants, except for object_property_add_child(), which
      additionally fails when the child already has a parent.  Parentage is
      also under program control, so this is a programming error, too.
      
      We have a bit over 500 callers.  Almost half of them pass
      &error_abort, slightly fewer ignore errors, one test case handles
      errors, and the remaining few callers pass them to their own callers.
      
      The previous few commits demonstrated once again that ignoring
      programming errors is a bad idea.
      
      Of the few ones that pass on errors, several violate the Error API.
      The Error ** argument must be NULL, &error_abort, &error_fatal, or a
      pointer to a variable containing NULL.  Passing an argument of the
      latter kind twice without clearing it in between is wrong: if the
      first call sets an error, it no longer points to NULL for the second
      call.  ich9_pm_add_properties(), sparc32_ledma_realize(),
      sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
      are wrong that way.
      
      When the one appropriate choice of argument is &error_abort, letting
      users pick the argument is a bad idea.
      
      Drop parameter @errp and assert the preconditions instead.
      
      There's one exception to "duplicate property name is a programming
      error": the way object_property_add() implements the magic (and
      undocumented) "automatic arrayification".  Don't drop @errp there.
      Instead, rename object_property_add() to object_property_try_add(),
      and add the obvious wrapper object_property_add().
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
      Message-Id: <20200505152926.18877-15-armbru@redhat.com>
      [Two semantic rebase conflicts resolved]
      d2623129
  8. Jan 06, 2020
    • Pan Nengyuan's avatar
      throttle-groups: fix memory leak in throttle_group_set_limit: · 88be15a9
      Pan Nengyuan authored
      
      This avoid a memory leak when qom-set is called to set throttle_group
      limits, here is an easy way to reproduce:
      
      1. run qemu-iotests as follow and check the result with asan:
             ./check -qcow2 184
      
      Following is the asan output backtrack:
      Direct leak of 912 byte(s) in 3 object(s) allocated from:
          #0 0xffff8d7ab3c3 in __interceptor_calloc   (/lib64/libasan.so.4+0xd33c3)
          #1 0xffff8d4c31cb in g_malloc0   (/lib64/libglib-2.0.so.0+0x571cb)
          #2 0x190c857 in qobject_input_start_struct  /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qapi/qobject-input-visitor.c:295
          #3 0x19070df in visit_start_struct   /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qapi/qapi-visit-core.c:49
          #4 0x1948b87 in visit_type_ThrottleLimits   qapi/qapi-visit-block-core.c:3759
          #5 0x17e4aa3 in throttle_group_set_limits   /mnt/sdc/qemu-master/qemu-4.2.0-rc0/block/throttle-groups.c:900
          #6 0x1650eff in object_property_set     /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/object.c:1272
          #7 0x1658517 in object_property_set_qobject   /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/qom-qobject.c:26
          #8 0x15880bb in qmp_qom_set  /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/qom-qmp-cmds.c:74
          #9 0x157e3e3 in qmp_marshal_qom_set  qapi/qapi-commands-qom.c:154
      
      Reported-by: default avatarEuler Robot <euler.robot@huawei.com>
      Signed-off-by: default avatarPanNengyuan <pannengyuan@huawei.com>
      Message-id: 1574835614-42028-1-git-send-email-pannengyuan@huawei.com
      Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
      88be15a9
  9. Aug 16, 2019
  10. Jan 24, 2019
    • Stefan Hajnoczi's avatar
      throttle-groups: fix restart coroutine iothread race · bc19a0a6
      Stefan Hajnoczi authored
      
      The following QMP command leads to a crash when iothreads are used:
      
        { 'execute': 'device_del', 'arguments': {'id': 'data'} }
      
      The backtrace involves the queue restart coroutine where
      tgm->throttle_state is a NULL pointer because
      throttle_group_unregister_tgm() has already been called:
      
        (gdb) bt full
        #0  0x00005585a7a3b378 in qemu_mutex_lock_impl (mutex=0xffffffffffffffd0, file=0x5585a7bb3d54 "block/throttle-groups.c", line=412) at util/qemu-thread-posix.c:64
              err = <optimized out>
              __PRETTY_FUNCTION__ = "qemu_mutex_lock_impl"
              __func__ = "qemu_mutex_lock_impl"
        #1  0x00005585a79be074 in throttle_group_restart_queue_entry (opaque=0x5585a9de4eb0) at block/throttle-groups.c:412
              _f = <optimized out>
              data = 0x5585a9de4eb0
              tgm = 0x5585a9079440
              ts = 0x0
              tg = 0xffffffffffffff98
              is_write = false
              empty_queue = 255
      
      This coroutine should not execute in the iothread after the throttle
      group member has been unregistered!
      
      The root cause is that the device_del code path schedules the restart
      coroutine in the iothread while holding the AioContext lock.  Therefore
      the iothread cannot execute the coroutine until after device_del
      releases the lock - by this time it's too late.
      
      This patch adds a reference count to ThrottleGroupMember so we can
      synchronously wait for restart coroutines to complete.  Once they are
      done it is safe to unregister the ThrottleGroupMember.
      
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
      Message-id: 20190114133257.30299-2-stefanha@redhat.com
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      bc19a0a6
  11. Aug 15, 2018
    • Alberto Garcia's avatar
      throttle-groups: Don't allow timers without throttled requests · 25b8e4db
      Alberto Garcia authored
      
      Commit 6fccbb47 fixed a bug caused by
      QEMU attempting to remove a throttle group member with no pending
      requests but an active timer set. This was the result of a previous
      bdrv_drained_begin() call processing the throttled requests but
      leaving the timer untouched.
      
      Although the commit does solve the problem, the situation shouldn't
      happen in the first place. If we try to drain a throttle group member
      which has a timer set, we should cancel the timer instead of ignoring
      it.
      
      Signed-off-by: default avatarAlberto Garcia <berto@igalia.com>
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      25b8e4db
    • Alberto Garcia's avatar
      throttle-groups: Skip the round-robin if a member is being drained · 5d8e4ca0
      Alberto Garcia authored
      
      In the throttling code after an I/O request has been completed the
      next one is selected from a different member using a round-robin
      algorithm. This ensures that all members get a chance to finish their
      pending I/O requests.
      
      However, if a group member has its I/O limits disabled (because it's
      being drained) then we should always give it priority in order to have
      all its pending requests finished as soon as possible.
      
      If we don't do this we could have a member in the process of being
      drained waiting for the throttled requests of other members, for which
      the I/O limits still apply.
      
      This can have additional consequences: if we're running in qtest mode
      (with QEMU_CLOCK_VIRTUAL) then timers can only fire if we advance the
      clock manually, so attempting to drain a block device can hang QEMU in
      the BDRV_POLL_WHILE() loop at the end of bdrv_do_drained_begin().
      
      Signed-off-by: default avatarAlberto Garcia <berto@igalia.com>
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      5d8e4ca0
  12. Jul 19, 2018
    • Stefan Hajnoczi's avatar
      throttle-groups: fix hang when group member leaves · 6fccbb47
      Stefan Hajnoczi authored
      
      Throttle groups consist of members sharing one throttling state
      (including bps/iops limits).  Round-robin scheduling is used to ensure
      fairness.  If a group member already has a timer pending then other
      groups members do not schedule their own timers.  The next group member
      will have its turn when the existing timer expires.
      
      A hang may occur when a group member leaves while it had a timer
      scheduled.  Although the code carefully removes the group member from
      the round-robin list, it does not schedule the next member.  Therefore
      remaining members continue to wait for the removed member's timer to
      expire.
      
      This patch schedules the next request if a timer is pending.
      Unfortunately the actual bug is a race condition that I've been unable
      to capture in a test case.
      
      Sometimes drive2 hangs when drive1 is removed from the throttling group:
      
        $ qemu ... -drive if=none,id=drive1,cache=none,format=qcow2,file=data1.qcow2,iops=100,group=foo \
                   -device virtio-blk-pci,id=virtio-blk-pci0,drive=drive1 \
                   -drive if=none,id=drive2,cache=none,format=qcow2,file=data2.qcow2,iops=10,group=foo \
                   -device virtio-blk-pci,id=virtio-blk-pci1,drive=drive2
        (guest-console1)# fio -filename /dev/vda 4k-seq-read.job
        (guest-console2)# fio -filename /dev/vdb 4k-seq-read.job
        (qmp) {"execute": "block_set_io_throttle", "arguments": {"device": "drive1","bps": 0,"bps_rd": 0,"bps_wr": 0,"iops": 0,"iops_rd": 0,"iops_wr": 0}}
      
      Reported-by: default avatarNini Gu <ngu@redhat.com>
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      Message-id: 20180704145410.794-1-stefanha@redhat.com
      RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1535914
      
      
      Cc: Alberto Garcia <berto@igalia.com>
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      6fccbb47
  13. Mar 02, 2018
  14. Nov 16, 2017
    • Stefan Hajnoczi's avatar
      throttle-groups: forget timer and schedule next TGM on detach · 341e0b56
      Stefan Hajnoczi authored
      
      tg->any_timer_armed[] must be cleared when detaching pending timers from
      the AioContext.  Failure to do so leads to hung I/O because it looks
      like there are still timers pending when in fact they have been removed.
      
      Other ThrottleGroupMembers might have requests pending too so it's
      necessary to schedule the next TGM so it can set a timer.
      
      This patch fixes hung I/O when QEMU is launched with drives that are in
      the same throttling group:
      
        (guest)$ dd if=/dev/zero of=/dev/vdb oflag=direct bs=512 &
        (guest)$ dd if=/dev/zero of=/dev/vdc oflag=direct bs=512 &
        (qemu) stop
        (qemu) cont
        ...I/O is stuck...
      
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      Message-id: 20171116112150.27607-1-stefanha@redhat.com
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      341e0b56
  15. Nov 13, 2017
  16. Sep 26, 2017
  17. Sep 06, 2017
  18. Sep 05, 2017
  19. Jul 18, 2017
  20. Jun 26, 2017
  21. Jun 15, 2017
  22. Feb 21, 2017
  23. Oct 24, 2016
  24. May 19, 2016
Loading