Skip to content
Snippets Groups Projects
  1. Dec 28, 2021
    • Vladimir Sementsov-Ogievskiy's avatar
      blockjob: drop BlockJob.blk field · 985cac8f
      Vladimir Sementsov-Ogievskiy authored
      
      It's unused now (except for permission handling)[*]. The only reasonable
      user of it was block-stream job, recently updated to use own blk. And
      other block jobs prefer to use own source node related objects.
      
      So, the arguments of dropping the field are:
      
       - block jobs prefer not to use it
       - block jobs usually has more then one node to operate on, and better
         to operate symmetrically (for example has both source and target
         blk's in specific block-job state structure)
      
      *: BlockJob.blk is used to keep some permissions. We simply move
      permissions to block-job child created in block_job_create() together
      with blk.
      
      In mirror, we just should not care anymore about restoring state of
      blk. Most probably this code could be dropped long ago, after dropping
      bs->job pointer. Now it finally goes away together with BlockJob.blk
      itself.
      
      iotest 141 output is updated, as "bdrv_has_blk(bs)" check in
      qmp_blockdev_del() doesn't fail (we don't have blk now). Still, new
      error message looks even better.
      
      In iotest 283 we need to add a job id, otherwise "Invalid job ID"
      happens now earlier than permission check (as permissions moved from
      blk to block-job node).
      
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Reviewed-by: default avatarNikita Lapshin <nikita.lapshin@virtuozzo.com>
      985cac8f
    • Vladimir Sementsov-Ogievskiy's avatar
      block/stream: add own blk · 048954e2
      Vladimir Sementsov-Ogievskiy authored
      
      block-stream is the only block-job, that reasonably use BlockJob.blk.
      We are going to drop BlockJob.blk soon. So, let block-stream have own
      blk.
      
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Reviewed-by: default avatarNikita Lapshin <nikita.lapshin@virtuozzo.com>
      048954e2
  2. Dec 21, 2021
  3. Dec 09, 2021
    • Stefan Hajnoczi's avatar
      block/nvme: fix infinite loop in nvme_free_req_queue_cb() · cf4fbc30
      Stefan Hajnoczi authored
      
      When the request free list is exhausted the coroutine waits on
      q->free_req_queue for the next free request. Whenever a request is
      completed a BH is scheduled to invoke nvme_free_req_queue_cb() and wake
      up waiting coroutines.
      
      1. nvme_get_free_req() waits for a free request:
      
          while (q->free_req_head == -1) {
              ...
                  trace_nvme_free_req_queue_wait(q->s, q->index);
                  qemu_co_queue_wait(&q->free_req_queue, &q->lock);
              ...
          }
      
      2. nvme_free_req_queue_cb() wakes up the coroutine:
      
          while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
             ^--- infinite loop when free_req_head == -1
          }
      
      nvme_free_req_queue_cb() and the coroutine form an infinite loop when
      q->free_req_head == -1. Fix this by checking q->free_req_head in
      nvme_free_req_queue_cb(). If the free request list is exhausted, don't
      wake waiting coroutines. Eventually an in-flight request will complete
      and the BH will be scheduled again, guaranteeing forward progress.
      
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      Reviewed-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
      Message-id: 20211208152246.244585-1-stefanha@redhat.com
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      cf4fbc30
  4. Nov 23, 2021
    • Daniella Lee's avatar
      block/vvfat.c fix leak when failure occurs · 22c36b75
      Daniella Lee authored
      
      Function vvfat_open called function enable_write_target and init_directories,
      and these functions malloc new memory for BDRVVVFATState::qcow_filename,
      BDRVVVFATState::used_clusters, and BDRVVVFATState::cluster_buff.
      
      When the specified folder does not exist ,it may contains memory leak.
      After init_directories function is executed, the vvfat_open return -EIO,
      and bdrv_open_driver goto label open_failed,
      the program use g_free(bs->opaque) to release BDRVVVFATState struct
      without members mentioned.
      
      command line:
      qemu-system-x86_64 -hdb <vdisk qcow file>  -usb -device usb-storage,drive=fat16
      -drive file=fat:rw:fat-type=16:"<path of a host folder does not exist>",
      id=fat16,format=raw,if=none
      
      enable_write_target called:
      (gdb) bt
          at ../block/vvfat.c:3114
          flags=155650, errp=0x7fffffffd780) at ../block/vvfat.c:1236
          node_name=0x0, options=0x555556fa45d0, open_flags=155650,
          errp=0x7fffffffd890) at ../block.c:1558
          errp=0x7fffffffd890) at ../block.c:1852
          reference=0x0, options=0x555556fa45d0, flags=40962, parent=0x555556f98cd0,
          child_class=0x555556b1d6a0 <child_of_bds>, child_role=19,
          errp=0x7fffffffda90) at ../block.c:3779
          options=0x555556f9cfc0, bdref_key=0x555556239bb8 "file",
          parent=0x555556f98cd0, child_class=0x555556b1d6a0 <child_of_bds>,
          child_role=19, allow_none=true, errp=0x7fffffffda90) at ../block.c:3419
          reference=0x0, options=0x555556f9cfc0, flags=8194, parent=0x0,
          child_class=0x0, child_role=0, errp=0x555556c98c40 <error_fatal>)
          at ../block.c:3726
          options=0x555556f757b0, flags=0, errp=0x555556c98c40 <error_fatal>)
          at ../block.c:3872
          options=0x555556f757b0, flags=0, errp=0x555556c98c40 <error_fatal>)
          at ../block/block-backend.c:436
          bs_opts=0x555556f757b0, errp=0x555556c98c40 <error_fatal>)
          at ../blockdev.c:608
          errp=0x555556c98c40 <error_fatal>) at ../blockdev.c:992
      ......
      
      Signed-off-by: default avatarDaniella Lee <daniellalee111@gmail.com>
      Message-Id: <20211119112553.352222-1-daniellalee111@gmail.com>
      [hreitz: Took commit message from v1]
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      22c36b75
  5. Nov 16, 2021
  6. Nov 02, 2021
  7. Oct 15, 2021
  8. Oct 14, 2021
  9. Oct 07, 2021
    • Hanna Reitz's avatar
      mirror: Do not clear .cancelled · a640fa0e
      Hanna Reitz authored
      
      Clearing .cancelled before leaving the main loop when the job has been
      soft-cancelled is no longer necessary since job_is_cancelled() only
      returns true for jobs that have been force-cancelled.
      
      Therefore, this only makes a differences in places that call
      job_cancel_requested().  In block/mirror.c, this is done only before
      .cancelled was cleared.
      
      In job.c, there are two callers:
      - job_completed_txn_abort() asserts that .cancelled is true, so keeping
        it true will not affect this place.
      
      - job_complete() refuses to let a job complete that has .cancelled set.
        It is correct to refuse to let the user invoke job-complete on mirror
        jobs that have already been soft-cancelled.
      
      With this change, there are no places that reset .cancelled to false and
      so we can be sure that .force_cancel can only be true if .cancelled is
      true as well.  Assert this in job_is_cancelled().
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20211006151940.214590-13-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      a640fa0e
    • Hanna Reitz's avatar
      mirror: Stop active mirroring after force-cancel · 9b230ef9
      Hanna Reitz authored
      
      Once the mirror job is force-cancelled (job_is_cancelled() is true), we
      should not generate new I/O requests.  This applies to active mirroring,
      too, so stop it once the job is cancelled.
      
      (We must still forward all I/O requests to the source, though, of
      course, but those are not really I/O requests generated by the job, so
      this is fine.)
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20211006151940.214590-12-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      9b230ef9
    • Hanna Reitz's avatar
      mirror: Check job_is_cancelled() earlier · 4feeec7e
      Hanna Reitz authored
      We must check whether the job is force-cancelled early in our main loop,
      most importantly before any `continue` statement.  For example, we used
      to have `continue`s before our current checking location that are
      triggered by `mirror_flush()` failing.  So, if `mirror_flush()` kept
      failing, force-cancelling the job would not terminate it.
      
      Jobs can be cancelled while they yield, and once they are
      (force-cancelled), they should not generate new I/O requests.
      Therefore, we should put the check after the last yield before
      mirror_iteration() is invoked.
      
      Buglink: https://gitlab.com/qemu-project/qemu/-/issues/462
      
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20211006151940.214590-11-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      4feeec7e
    • Hanna Reitz's avatar
      mirror: Use job_is_cancelled() · 20ad4d20
      Hanna Reitz authored
      
      mirror_drained_poll() returns true whenever the job is cancelled,
      because "we [can] be sure that it won't issue more requests".  However,
      this is only true for force-cancelled jobs, so use job_is_cancelled().
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20211006151940.214590-10-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      20ad4d20
    • Hanna Reitz's avatar
      job: Add job_cancel_requested() · 08b83bff
      Hanna Reitz authored
      Most callers of job_is_cancelled() actually want to know whether the job
      is on its way to immediate termination.  For example, we refuse to pause
      jobs that are cancelled; but this only makes sense for jobs that are
      really actually cancelled.
      
      A mirror job that is cancelled during READY with force=false should
      absolutely be allowed to pause.  This "cancellation" (which is actually
      a kind of completion) may take an indefinite amount of time, and so
      should behave like any job during normal operation.  For example, with
      on-target-error=stop, the job should stop on write errors.  (In
      contrast, force-cancelled jobs should not get write errors, as they
      should just terminate and not do further I/O.)
      
      Therefore, redefine job_is_cancelled() to only return true for jobs that
      are force-cancelled (which as of HEAD^ means any job that interprets the
      cancellation request as a request for immediate termination), and add
      job_cancel_requested() as the general variant, which returns true for
      any jobs which have been requested to be cancelled, whether it be
      immediately or after an arbitrarily long completion phase.
      
      Finally, here is a justification for how different job_is_cancelled()
      invocations are treated by this patch:
      
      - block/mirror.c (mirror_run()):
        - The first invocation is a while loop that should loop until the job
          has been cancelled or scheduled for completion.  What kind of cancel
          does not matter, only the fact that the job is supposed to end.
      
        - The second invocation wants to know whether the job has been
          soft-cancelled.  Calling job_cancel_requested() is a bit too broad,
          but if the job were force-cancelled, we should leave the main loop
          as soon as possible anyway, so this should not matter here.
      
        - The last two invocations already check force_cancel, so they should
          continue to use job_is_cancelled().
      
      - block/backup.c, block/commit.c, block/stream.c, anything in tests/:
        These jobs know only force-cancel, so there is no difference between
        job_is_cancelled() and job_cancel_requested().  We can continue using
        job_is_cancelled().
      
      - job.c:
        - job_pause_point(), job_yield(), job_sleep_ns(): Only force-cancelled
          jobs should be prevented from being paused.  Continue using job_is_cancelled().
      
        - job_update_rc(), job_finalize_single(), job_finish_sync(): These
          functions are all called after the job has left its main loop.  The
          mirror job (the only job that can be soft-cancelled) will clear
          .cancelled before leaving the main loop if it has been
          soft-cancelled.  Therefore, these functions will observe .cancelled
          to be true only if the job has been force-cancelled.  We can
          continue to use job_is_cancelled().
          (Furthermore, conceptually, a soft-cancelled mirror job should not
          report to have been cancelled.  It should report completion (see
          also the block-job-cancel QAPI documentation).  Therefore, it makes
          sense for these functions not to distinguish between a
          soft-cancelled mirror job and a job that has completed as normal.)
      
        - job_completed_txn_abort(): All jobs other than @job have been
          force-cancelled.  job_is_cancelled() must be true for them.
          Regarding @job itself: job_completed_txn_abort() is mostly called
          when the job's return value is not 0.  A soft-cancelled mirror has a
          return value of 0, and so will not end up here then.
          However, job_cancel() invokes job_completed_txn_abort() if the job
          has been deferred to the main loop, which is mostly the case for
          completed jobs (which skip the assertion), but not for sure.
          To be safe, use job_cancel_requested() in this assertion.
      
        - job_complete(): This is function eventually invoked by the user
          (through qmp_block_job_complete() or qmp_job_complete(), or
          job_complete_sync(), which comes from qemu-img).  The intention here
          is to prevent a user from invoking job-complete after the job has
          been cancelled.  This should also apply to soft cancelling: After a
          mirror job has been soft-cancelled, the user should not be able to
          decide otherwise and have it complete as normal (i.e. pivoting to
          the target).
      
        - job_cancel(): Both functions are equivalent (see comment there), but
          we want to use job_is_cancelled(), because this shows that we call
          job_completed_txn_abort() only for force-cancelled jobs.  (As
          explained for job_update_rc(), soft-cancelled jobs should be treated
          as if they have completed as normal.)
      
      Buglink: https://gitlab.com/qemu-project/qemu/-/issues/462
      
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20211006151940.214590-9-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      08b83bff
    • Hanna Reitz's avatar
      jobs: Give Job.force_cancel more meaning · 73895f38
      Hanna Reitz authored
      
      We largely have two cancel modes for jobs:
      
      First, there is actual cancelling.  The job is terminated as soon as
      possible, without trying to reach a consistent result.
      
      Second, we have mirror in the READY state.  Technically, the job is not
      really cancelled, but it just is a different completion mode.  The job
      can still run for an indefinite amount of time while it tries to reach a
      consistent result.
      
      We want to be able to clearly distinguish which cancel mode a job is in
      (when it has been cancelled).  We can use Job.force_cancel for this, but
      right now it only reflects cancel requests from the user with
      force=true, but clearly, jobs that do not even distinguish between
      force=false and force=true are effectively always force-cancelled.
      
      So this patch has Job.force_cancel signify whether the job will
      terminate as soon as possible (force_cancel=true) or whether it will
      effectively remain running despite being "cancelled"
      (force_cancel=false).
      
      To this end, we let jobs that provide JobDriver.cancel() tell the
      generic job code whether they will terminate as soon as possible or not,
      and for jobs that do not provide that method we assume they will.
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Reviewed-by: default avatarKevin Wolf <kwolf@redhat.com>
      Message-Id: <20211006151940.214590-7-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      73895f38
    • Hanna Reitz's avatar
      job: @force parameter for job_cancel_sync() · 4cfb3f05
      Hanna Reitz authored
      Callers should be able to specify whether they want job_cancel_sync() to
      force-cancel the job or not.
      
      In fact, almost all invocations do not care about consistency of the
      result and just want the job to terminate as soon as possible, so they
      should pass force=true.  The replication block driver is the exception,
      specifically the active commit job it runs.
      
      As for job_cancel_sync_all(), all callers want it to force-cancel all
      jobs, because that is the point of it: To cancel all remaining jobs as
      quickly as possible (generally on process termination).  So make it
      invoke job_cancel_sync() with force=true.
      
      This changes some iotest outputs, because quitting qemu while a mirror
      job is active will now lead to it being cancelled instead of completed,
      which is what we want.  (Cancelling a READY mirror job with force=false
      may take an indefinite amount of time, which we do not want when
      quitting.  If users want consistent results, they must have all jobs be
      done before they quit qemu.)
      
      Buglink: https://gitlab.com/qemu-project/qemu/-/issues/462
      
      
      Signed-off-by: default avatarHanna Reitz <hreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      Message-Id: <20211006151940.214590-6-hreitz@redhat.com>
      Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
      4cfb3f05
Loading