Commit fd2590bc authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging



# gpg: Signature made Mon 20 Jun 2016 15:05:24 BST
# gpg:                using RSA key 0x9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/block-pull-request:
  backup: follow AioContext change gracefully
  mirror: follow AioContext change gracefully
  blockjob: add AioContext attached callback
  block: use safe iteration over AioContext notifiers
  blockjob: add block_job_get_aio_context()
  blockjob: add pause points
  blockjob: rename block_job_is_paused()
  blockjob: move iostatus reset out of block_job_enter()
  block: process before_write_notifiers in bdrv_co_discard
  block: fix race in bdrv_co_discard with drive-mirror
  block: fixed BdrvTrackedRequest filling in bdrv_co_discard
  libqos: add qvirtqueue_cleanup()
  libqos: drop duplicated virtio_pci.h definitions
  libqos: drop duplicated virtio_scsi.h definitions
  libqos: drop duplicated virtio_blk.h definitions
  libqos: drop duplicated virtio_vring.h structs
  libqos: drop duplicated virtio_ring.h bit definitions
  libqos: drop duplicated virtio_config.h definitions
  libqos: drop duplicated PCI vendor ID definition
  libqos: use virtio_ids.h for device ID definitions

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 5edbd4e3 5ab4b69c
Loading
Loading
Loading
Loading
+36 −10
Original line number Diff line number Diff line
@@ -3609,18 +3609,34 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
    return bs->aio_context;
}

static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
{
    QLIST_REMOVE(ban, list);
    g_free(ban);
}

void bdrv_detach_aio_context(BlockDriverState *bs)
{
    BdrvAioNotifier *baf;
    BdrvAioNotifier *baf, *baf_tmp;
    BdrvChild *child;

    if (!bs->drv) {
        return;
    }

    QLIST_FOREACH(baf, &bs->aio_notifiers, list) {
    assert(!bs->walking_aio_notifiers);
    bs->walking_aio_notifiers = true;
    QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
        if (baf->deleted) {
            bdrv_do_remove_aio_context_notifier(baf);
        } else {
            baf->detach_aio_context(baf->opaque);
        }
    }
    /* Never mind iterating again to check for ->deleted.  bdrv_close() will
     * remove remaining aio notifiers if we aren't called again.
     */
    bs->walking_aio_notifiers = false;

    if (bs->drv->bdrv_detach_aio_context) {
        bs->drv->bdrv_detach_aio_context(bs);
@@ -3635,7 +3651,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
void bdrv_attach_aio_context(BlockDriverState *bs,
                             AioContext *new_context)
{
    BdrvAioNotifier *ban;
    BdrvAioNotifier *ban, *ban_tmp;
    BdrvChild *child;

    if (!bs->drv) {
@@ -3651,10 +3667,17 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
        bs->drv->bdrv_attach_aio_context(bs, new_context);
    }

    QLIST_FOREACH(ban, &bs->aio_notifiers, list) {
    assert(!bs->walking_aio_notifiers);
    bs->walking_aio_notifiers = true;
    QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_tmp) {
        if (ban->deleted) {
            bdrv_do_remove_aio_context_notifier(ban);
        } else {
            ban->attached_aio_context(new_context, ban->opaque);
        }
    }
    bs->walking_aio_notifiers = false;
}

void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
{
@@ -3695,11 +3718,14 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
    QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
        if (ban->attached_aio_context == attached_aio_context &&
            ban->detach_aio_context   == detach_aio_context   &&
            ban->opaque               == opaque)
            ban->opaque               == opaque               &&
            ban->deleted              == false)
        {
            QLIST_REMOVE(ban, list);
            g_free(ban);

            if (bs->walking_aio_notifiers) {
                ban->deleted = true;
            } else {
                bdrv_do_remove_aio_context_notifier(ban);
            }
            return;
        }
    }
+14 −8
Original line number Diff line number Diff line
@@ -246,12 +246,20 @@ static void backup_abort(BlockJob *job)
    }
}

static void backup_attached_aio_context(BlockJob *job, AioContext *aio_context)
{
    BackupBlockJob *s = container_of(job, BackupBlockJob, common);

    blk_set_aio_context(s->target, aio_context);
}

static const BlockJobDriver backup_job_driver = {
    .instance_size          = sizeof(BackupBlockJob),
    .job_type               = BLOCK_JOB_TYPE_BACKUP,
    .set_speed              = backup_set_speed,
    .commit                 = backup_commit,
    .abort                  = backup_abort,
    .attached_aio_context   = backup_attached_aio_context,
};

static BlockErrorAction backup_error_action(BackupBlockJob *job,
@@ -392,9 +400,7 @@ static void coroutine_fn backup_run(void *opaque)
        while (!block_job_is_cancelled(&job->common)) {
            /* Yield until the job is cancelled.  We just let our before_write
             * notify callback service CoW requests. */
            job->common.busy = false;
            qemu_coroutine_yield();
            job->common.busy = true;
            block_job_yield(&job->common);
        }
    } else if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
        ret = backup_run_incremental(job);
+9 −3
Original line number Diff line number Diff line
@@ -2347,9 +2347,13 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
        return 0;
    }

    tracked_request_begin(&req, bs, sector_num, nb_sectors,
                          BDRV_TRACKED_DISCARD);
    bdrv_set_dirty(bs, sector_num, nb_sectors);
    tracked_request_begin(&req, bs, sector_num << BDRV_SECTOR_BITS,
                          nb_sectors << BDRV_SECTOR_BITS, BDRV_TRACKED_DISCARD);

    ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
    if (ret < 0) {
        goto out;
    }

    max_discard = MIN_NON_ZERO(bs->bl.max_discard, BDRV_REQUEST_MAX_SECTORS);
    while (nb_sectors > 0) {
@@ -2398,6 +2402,8 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
    }
    ret = 0;
out:
    bdrv_set_dirty(bs, req.offset >> BDRV_SECTOR_BITS,
                   req.bytes >> BDRV_SECTOR_BITS);
    tracked_request_end(&req);
    return ret;
}
+35 −8
Original line number Diff line number Diff line
@@ -331,6 +331,8 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
        mirror_wait_for_io(s);
    }

    block_job_pause_point(&s->common);

    /* Find the number of consective dirty chunks following the first dirty
     * one, and wait for in flight requests in them. */
    while (nb_chunks * sectors_per_chunk < (s->buf_size >> BDRV_SECTOR_BITS)) {
@@ -582,6 +584,8 @@ static void coroutine_fn mirror_run(void *opaque)
            if (now - last_pause_ns > SLICE_TIME) {
                last_pause_ns = now;
                block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, 0);
            } else {
                block_job_pause_point(&s->common);
            }

            if (block_job_is_cancelled(&s->common)) {
@@ -613,6 +617,8 @@ static void coroutine_fn mirror_run(void *opaque)
            goto immediate_exit;
        }

        block_job_pause_point(&s->common);

        cnt = bdrv_get_dirty_count(s->dirty_bitmap);
        /* s->common.offset contains the number of bytes already processed so
         * far, cnt is the number of dirty sectors remaining and
@@ -795,11 +801,30 @@ static void mirror_complete(BlockJob *job, Error **errp)
    block_job_enter(&s->common);
}

/* There is no matching mirror_resume() because mirror_run() will begin
 * iterating again when the job is resumed.
 */
static void coroutine_fn mirror_pause(BlockJob *job)
{
    MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);

    mirror_drain(s);
}

static void mirror_attached_aio_context(BlockJob *job, AioContext *new_context)
{
    MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);

    blk_set_aio_context(s->target, new_context);
}

static const BlockJobDriver mirror_job_driver = {
    .instance_size          = sizeof(MirrorBlockJob),
    .job_type               = BLOCK_JOB_TYPE_MIRROR,
    .set_speed              = mirror_set_speed,
    .complete               = mirror_complete,
    .pause                  = mirror_pause,
    .attached_aio_context   = mirror_attached_aio_context,
};

static const BlockJobDriver commit_active_job_driver = {
@@ -807,6 +832,8 @@ static const BlockJobDriver commit_active_job_driver = {
    .job_type               = BLOCK_JOB_TYPE_COMMIT,
    .set_speed              = mirror_set_speed,
    .complete               = mirror_complete,
    .pause                  = mirror_pause,
    .attached_aio_context   = mirror_attached_aio_context,
};

static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
+1 −0
Original line number Diff line number Diff line
@@ -3811,6 +3811,7 @@ void qmp_block_job_resume(const char *device, Error **errp)

    job->user_paused = false;
    trace_qmp_block_job_resume(job);
    block_job_iostatus_reset(job);
    block_job_resume(job);
    aio_context_release(aio_context);
}
Loading