Commit e4ae62b8 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 Fri 09 Mar 2018 13:19:02 GMT
# gpg:                using RSA key 9CA4ABB381AB73C8
# 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:
  vl: introduce vm_shutdown()
  virtio-scsi: fix race between .ioeventfd_stop() and vq handler
  virtio-blk: fix race between .ioeventfd_stop() and vq handler
  block: add aio_wait_bh_oneshot()
  virtio-blk: dataplane: Don't batch notifications if EVENT_IDX is present
  README: Fix typo 'git-publish'
  block: Fix qemu crash when using scsi-block

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents b39b61e4 4486e89c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ The QEMU website is also maintained under source control.
  git clone git://git.qemu.org/qemu-web.git
  https://www.qemu.org/2017/02/04/the-new-qemu-website-is-up/

A 'git-profile' utility was created to make above process less
A 'git-publish' utility was created to make above process less
cumbersome, and is highly recommended for making regular contributions,
or even just for sending consecutive patch series revisions. It also
requires a working 'git send-email' setup, and by default doesn't
+25 −26
Original line number Diff line number Diff line
@@ -1150,7 +1150,7 @@ int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
typedef struct BlkRwCo {
    BlockBackend *blk;
    int64_t offset;
    QEMUIOVector *qiov;
    void *iobuf;
    int ret;
    BdrvRequestFlags flags;
} BlkRwCo;
@@ -1158,17 +1158,19 @@ typedef struct BlkRwCo {
static void blk_read_entry(void *opaque)
{
    BlkRwCo *rwco = opaque;
    QEMUIOVector *qiov = rwco->iobuf;

    rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, rwco->qiov->size,
                              rwco->qiov, rwco->flags);
    rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, qiov->size,
                              qiov, rwco->flags);
}

static void blk_write_entry(void *opaque)
{
    BlkRwCo *rwco = opaque;
    QEMUIOVector *qiov = rwco->iobuf;

    rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, rwco->qiov->size,
                               rwco->qiov, rwco->flags);
    rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, qiov->size,
                               qiov, rwco->flags);
}

static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
@@ -1188,7 +1190,7 @@ static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
    rwco = (BlkRwCo) {
        .blk    = blk,
        .offset = offset,
        .qiov   = &qiov,
        .iobuf  = &qiov,
        .flags  = flags,
        .ret    = NOT_DONE,
    };
@@ -1296,7 +1298,7 @@ static void blk_aio_complete_bh(void *opaque)
}

static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
                                QEMUIOVector *qiov, CoroutineEntry co_entry,
                                void *iobuf, CoroutineEntry co_entry,
                                BdrvRequestFlags flags,
                                BlockCompletionFunc *cb, void *opaque)
{
@@ -1308,7 +1310,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
    acb->rwco = (BlkRwCo) {
        .blk    = blk,
        .offset = offset,
        .qiov   = qiov,
        .iobuf  = iobuf,
        .flags  = flags,
        .ret    = NOT_DONE,
    };
@@ -1331,10 +1333,11 @@ static void blk_aio_read_entry(void *opaque)
{
    BlkAioEmAIOCB *acb = opaque;
    BlkRwCo *rwco = &acb->rwco;
    QEMUIOVector *qiov = rwco->iobuf;

    assert(rwco->qiov->size == acb->bytes);
    assert(qiov->size == acb->bytes);
    rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, acb->bytes,
                              rwco->qiov, rwco->flags);
                              qiov, rwco->flags);
    blk_aio_complete(acb);
}

@@ -1342,10 +1345,11 @@ static void blk_aio_write_entry(void *opaque)
{
    BlkAioEmAIOCB *acb = opaque;
    BlkRwCo *rwco = &acb->rwco;
    QEMUIOVector *qiov = rwco->iobuf;

    assert(!rwco->qiov || rwco->qiov->size == acb->bytes);
    assert(!qiov || qiov->size == acb->bytes);
    rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, acb->bytes,
                               rwco->qiov, rwco->flags);
                               qiov, rwco->flags);
    blk_aio_complete(acb);
}

@@ -1474,8 +1478,10 @@ int blk_co_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
static void blk_ioctl_entry(void *opaque)
{
    BlkRwCo *rwco = opaque;
    QEMUIOVector *qiov = rwco->iobuf;

    rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
                             rwco->qiov->iov[0].iov_base);
                             qiov->iov[0].iov_base);
}

int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
@@ -1488,24 +1494,15 @@ static void blk_aio_ioctl_entry(void *opaque)
    BlkAioEmAIOCB *acb = opaque;
    BlkRwCo *rwco = &acb->rwco;

    rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
                             rwco->qiov->iov[0].iov_base);
    rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset, rwco->iobuf);

    blk_aio_complete(acb);
}

BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
                          BlockCompletionFunc *cb, void *opaque)
{
    QEMUIOVector qiov;
    struct iovec iov;

    iov = (struct iovec) {
        .iov_base = buf,
        .iov_len = 0,
    };
    qemu_iovec_init_external(&qiov, &iov, 1);

    return blk_aio_prwv(blk, req, 0, &qiov, blk_aio_ioctl_entry, 0, cb, opaque);
    return blk_aio_prwv(blk, req, 0, buf, blk_aio_ioctl_entry, 0, cb, opaque);
}

int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
@@ -1949,7 +1946,9 @@ int blk_truncate(BlockBackend *blk, int64_t offset, PreallocMode prealloc,
static void blk_pdiscard_entry(void *opaque)
{
    BlkRwCo *rwco = opaque;
    rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, rwco->qiov->size);
    QEMUIOVector *qiov = rwco->iobuf;

    rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, qiov->size);
}

int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
+13 −3
Original line number Diff line number Diff line
@@ -993,7 +993,7 @@ void cpu_synchronize_all_pre_loadvm(void)
    }
}

static int do_vm_stop(RunState state)
static int do_vm_stop(RunState state, bool send_stop)
{
    int ret = 0;

@@ -1002,8 +1002,10 @@ static int do_vm_stop(RunState state)
        pause_all_vcpus();
        runstate_set(state);
        vm_state_notify(0, state);
        if (send_stop) {
            qapi_event_send_stop(&error_abort);
        }
    }

    bdrv_drain_all();
    replay_disable_events();
@@ -1012,6 +1014,14 @@ static int do_vm_stop(RunState state)
    return ret;
}

/* Special vm_stop() variant for terminating the process.  Historically clients
 * did not expect a QMP STOP event and so we need to retain compatibility.
 */
int vm_shutdown(void)
{
    return do_vm_stop(RUN_STATE_SHUTDOWN, false);
}

static bool cpu_can_run(CPUState *cpu)
{
    if (cpu->stop) {
@@ -1994,7 +2004,7 @@ int vm_stop(RunState state)
        return 0;
    }

    return do_vm_stop(state);
    return do_vm_stop(state, true);
}

/**
+30 −9
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ struct VirtIOBlockDataPlane {
    VirtIODevice *vdev;
    QEMUBH *bh;                     /* bh for guest notification */
    unsigned long *batch_notify_vqs;
    bool batch_notifications;

    /* Note that these EventNotifiers are assigned by value.  This is
     * fine as long as you do not call event_notifier_cleanup on them
@@ -47,8 +48,12 @@ struct VirtIOBlockDataPlane {
/* Raise an interrupt to signal guest, if necessary */
void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq)
{
    if (s->batch_notifications) {
        set_bit(virtio_get_queue_index(vq), s->batch_notify_vqs);
        qemu_bh_schedule(s->bh);
    } else {
        virtio_notify_irqfd(s->vdev, vq);
    }
}

static void notify_guest_bh(void *opaque)
@@ -177,6 +182,12 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)

    s->starting = true;

    if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
        s->batch_notifications = true;
    } else {
        s->batch_notifications = false;
    }

    /* Set up guest notifier (irq) */
    r = k->set_guest_notifiers(qbus->parent, nvqs, true);
    if (r != 0) {
@@ -229,6 +240,22 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
    return -ENOSYS;
}

/* Stop notifications for new requests from guest.
 *
 * Context: BH in IOThread
 */
static void virtio_blk_data_plane_stop_bh(void *opaque)
{
    VirtIOBlockDataPlane *s = opaque;
    unsigned i;

    for (i = 0; i < s->conf->num_queues; i++) {
        VirtQueue *vq = virtio_get_queue(s->vdev, i);

        virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL);
    }
}

/* Context: QEMU global mutex held */
void virtio_blk_data_plane_stop(VirtIODevice *vdev)
{
@@ -253,13 +280,7 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
    trace_virtio_blk_data_plane_stop(s);

    aio_context_acquire(s->ctx);

    /* Stop notifications for new requests from guest */
    for (i = 0; i < nvqs; i++) {
        VirtQueue *vq = virtio_get_queue(s->vdev, i);

        virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL);
    }
    aio_wait_bh_oneshot(s->ctx, virtio_blk_data_plane_stop_bh, s);

    /* Drain and switch bs back to the QEMU main loop */
    blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context());
+5 −4
Original line number Diff line number Diff line
@@ -107,9 +107,10 @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n,
    return 0;
}

/* assumes s->ctx held */
static void virtio_scsi_clear_aio(VirtIOSCSI *s)
/* Context: BH in IOThread */
static void virtio_scsi_dataplane_stop_bh(void *opaque)
{
    VirtIOSCSI *s = opaque;
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
    int i;

@@ -171,7 +172,7 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
    return 0;

fail_vrings:
    virtio_scsi_clear_aio(s);
    aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
    aio_context_release(s->ctx);
    for (i = 0; i < vs->conf.num_queues + 2; i++) {
        virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
@@ -207,7 +208,7 @@ void virtio_scsi_dataplane_stop(VirtIODevice *vdev)
    s->dataplane_stopping = true;

    aio_context_acquire(s->ctx);
    virtio_scsi_clear_aio(s);
    aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
    aio_context_release(s->ctx);

    blk_drain_all(); /* ensure there are no in-flight requests */
Loading