Commit 40eeb397 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 Tue 07 Jun 2016 15:26:09 BST
# gpg:                using RSA key 0x9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/block-pull-request:
  throttle: refuse iops-size without iops-total/read/write
  block: Drop bdrv_ioctl_bh_cb
  block: Move BlockRequest type to io.c
  block/io: optimize bdrv_co_pwritev for small requests
  iostatus: fix comments for block_job_iostatus_reset
  block/io: Remove unused bdrv_aio_write_zeroes()
  virtio: drop duplicate virtio_queue_get_id() function
  virtio-scsi: Remove op blocker for dataplane
  virtio-blk: Remove op blocker for dataplane
  blockdev-backup: Don't move target AioContext if it's attached
  blockdev-backup: Use bdrv_lookup_bs on target
  tests: avoid coroutine pool test crash

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 79cecb35 8860eabd
Loading
Loading
Loading
Loading
+31 −29
Original line number Diff line number Diff line
@@ -1427,6 +1427,14 @@ int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs,

        bytes += offset & (align - 1);
        offset = offset & ~(align - 1);

        /* We have read the tail already if the request is smaller
         * than one aligned block.
         */
        if (bytes < align) {
            qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes);
            bytes = align;
        }
    }

    if ((offset + bytes) & (align - 1)) {
@@ -1865,17 +1873,6 @@ BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
                                 cb, opaque, true);
}

BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
        int64_t sector_num, int nb_sectors, BdrvRequestFlags flags,
        BlockCompletionFunc *cb, void *opaque)
{
    trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque);

    return bdrv_co_aio_rw_vector(bs, sector_num, NULL, nb_sectors,
                                 BDRV_REQ_ZERO_WRITE | flags,
                                 cb, opaque, true);
}

void bdrv_aio_cancel(BlockAIOCB *acb)
{
    qemu_aio_ref(acb);
@@ -1905,6 +1902,27 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb)
/**************************************************************/
/* async block device emulation */

typedef struct BlockRequest {
    union {
        /* Used during read, write, trim */
        struct {
            int64_t sector;
            int nb_sectors;
            int flags;
            QEMUIOVector *qiov;
        };
        /* Used during ioctl */
        struct {
            int req;
            void *buf;
        };
    };
    BlockCompletionFunc *cb;
    void *opaque;

    int error;
} BlockRequest;

typedef struct BlockAIOCBCoroutine {
    BlockAIOCB common;
    BlockRequest req;
@@ -2309,19 +2327,6 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
    return rwco.ret;
}

typedef struct {
    CoroutineIOCompletion *co;
    QEMUBH *bh;
} BdrvIoctlCompletionData;

static void bdrv_ioctl_bh_cb(void *opaque)
{
    BdrvIoctlCompletionData *data = opaque;

    bdrv_co_io_em_complete(data->co, -ENOTSUP);
    qemu_bh_delete(data->bh);
}

static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf)
{
    BlockDriver *drv = bs->drv;
@@ -2339,11 +2344,8 @@ static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf)

    acb = drv->bdrv_aio_ioctl(bs, req, buf, bdrv_co_io_em_complete, &co);
    if (!acb) {
        BdrvIoctlCompletionData *data = g_new(BdrvIoctlCompletionData, 1);
        data->bh = aio_bh_new(bdrv_get_aio_context(bs),
                                bdrv_ioctl_bh_cb, data);
        data->co = &co;
        qemu_bh_schedule(data->bh);
        co.ret = -ENOTSUP;
        goto out;
    }
    qemu_coroutine_yield();
out:
+13 −10
Original line number Diff line number Diff line
@@ -3335,7 +3335,7 @@ void do_blockdev_backup(const char *device, const char *target,
                         BlockdevOnError on_target_error,
                         BlockJobTxn *txn, Error **errp)
{
    BlockBackend *blk, *target_blk;
    BlockBackend *blk;
    BlockDriverState *bs;
    BlockDriverState *target_bs;
    Error *local_err = NULL;
@@ -3366,19 +3366,22 @@ void do_blockdev_backup(const char *device, const char *target,
    }
    bs = blk_bs(blk);

    target_blk = blk_by_name(target);
    if (!target_blk) {
        error_setg(errp, "Device '%s' not found", target);
    target_bs = bdrv_lookup_bs(target, target, errp);
    if (!target_bs) {
        goto out;
    }

    if (!blk_is_available(target_blk)) {
        error_setg(errp, "Device '%s' has no medium", target);
    if (bdrv_get_aio_context(target_bs) != aio_context) {
        if (!bdrv_has_blk(target_bs)) {
            /* The target BDS is not attached, we can safely move it to another
             * AioContext. */
            bdrv_set_aio_context(target_bs, aio_context);
        } else {
            error_setg(errp, "Target is attached to a different thread from "
                             "source.");
            goto out;
        }
    target_bs = blk_bs(target_blk);

    bdrv_set_aio_context(target_bs, aio_context);
    }
    backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
                 on_target_error, block_job_cb, bs, txn, &local_err);
    if (local_err != NULL) {
+0 −63
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@ struct VirtIOBlockDataPlane {
    EventNotifier *guest_notifier;  /* irq */
    QEMUBH *bh;                     /* bh for guest notification */

    Notifier insert_notifier, remove_notifier;

    /* Note that these EventNotifiers are assigned by value.  This is
     * fine as long as you do not call event_notifier_cleanup on them
     * (because you don't own the file descriptor or handle; you just
@@ -46,9 +44,6 @@ struct VirtIOBlockDataPlane {
     */
    IOThread *iothread;
    AioContext *ctx;

    /* Operation blocker on BDS */
    Error *blocker;
};

/* Raise an interrupt to signal guest, if necessary */
@@ -68,54 +63,6 @@ static void notify_guest_bh(void *opaque)
    event_notifier_set(s->guest_notifier);
}

static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s)
{
    assert(!s->blocker);
    error_setg(&s->blocker, "block device is in use by data plane");
    blk_op_block_all(s->conf->conf.blk, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
                   s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT,
                   s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
                   s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_MIRROR_SOURCE, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker);
    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker);
}

static void data_plane_remove_op_blockers(VirtIOBlockDataPlane *s)
{
    if (s->blocker) {
        blk_op_unblock_all(s->conf->conf.blk, s->blocker);
        error_free(s->blocker);
        s->blocker = NULL;
    }
}

static void data_plane_blk_insert_notifier(Notifier *n, void *data)
{
    VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane,
                                           insert_notifier);
    assert(s->conf->conf.blk == data);
    data_plane_set_up_op_blockers(s);
}

static void data_plane_blk_remove_notifier(Notifier *n, void *data)
{
    VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane,
                                           remove_notifier);
    assert(s->conf->conf.blk == data);
    data_plane_remove_op_blockers(s);
}

/* Context: QEMU global mutex held */
void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
                                  VirtIOBlockDataPlane **dataplane,
@@ -158,13 +105,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
    s->ctx = iothread_get_aio_context(s->iothread);
    s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);

    s->insert_notifier.notify = data_plane_blk_insert_notifier;
    s->remove_notifier.notify = data_plane_blk_remove_notifier;
    blk_add_insert_bs_notifier(conf->conf.blk, &s->insert_notifier);
    blk_add_remove_bs_notifier(conf->conf.blk, &s->remove_notifier);

    data_plane_set_up_op_blockers(s);

    *dataplane = s;
}

@@ -176,9 +116,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
    }

    virtio_blk_data_plane_stop(s);
    data_plane_remove_op_blockers(s);
    notifier_remove(&s->insert_notifier);
    notifier_remove(&s->remove_notifier);
    qemu_bh_delete(s->bh);
    object_unref(OBJECT(s->iothread));
    g_free(s);
+1 −63
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
{
    VirtIOSCSIReq *req = sreq->hba_private;
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
    uint32_t n = virtio_queue_get_id(req->vq) - 2;
    uint32_t n = virtio_get_queue_index(req->vq) - 2;

    assert(n < vs->conf.num_queues);
    qemu_put_be32s(f, &n);
@@ -773,22 +773,6 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
    }
}

static void virtio_scsi_blk_insert_notifier(Notifier *n, void *data)
{
    VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
                                                n, n);
    assert(cn->sd->conf.blk == data);
    blk_op_block_all(cn->sd->conf.blk, cn->s->blocker);
}

static void virtio_scsi_blk_remove_notifier(Notifier *n, void *data)
{
    VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
                                                n, n);
    assert(cn->sd->conf.blk == data);
    blk_op_unblock_all(cn->sd->conf.blk, cn->s->blocker);
}

static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp)
{
@@ -797,29 +781,13 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
    SCSIDevice *sd = SCSI_DEVICE(dev);

    if (s->ctx && !s->dataplane_fenced) {
        VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;

        if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
            return;
        }
        blk_op_block_all(sd->conf.blk, s->blocker);
        aio_context_acquire(s->ctx);
        blk_set_aio_context(sd->conf.blk, s->ctx);
        aio_context_release(s->ctx);

        insert_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
        insert_notifier->n.notify = virtio_scsi_blk_insert_notifier;
        insert_notifier->s = s;
        insert_notifier->sd = sd;
        blk_add_insert_bs_notifier(sd->conf.blk, &insert_notifier->n);
        QTAILQ_INSERT_TAIL(&s->insert_notifiers, insert_notifier, next);

        remove_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
        remove_notifier->n.notify = virtio_scsi_blk_remove_notifier;
        remove_notifier->s = s;
        remove_notifier->sd = sd;
        blk_add_remove_bs_notifier(sd->conf.blk, &remove_notifier->n);
        QTAILQ_INSERT_TAIL(&s->remove_notifiers, remove_notifier, next);
    }

    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
@@ -835,7 +803,6 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
    VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
    SCSIDevice *sd = SCSI_DEVICE(dev);
    VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;

    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
        virtio_scsi_push_event(s, sd,
@@ -843,28 +810,6 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
                               VIRTIO_SCSI_EVT_RESET_REMOVED);
    }

    if (s->ctx) {
        blk_op_unblock_all(sd->conf.blk, s->blocker);
    }

    QTAILQ_FOREACH(insert_notifier, &s->insert_notifiers, next) {
        if (insert_notifier->sd == sd) {
            notifier_remove(&insert_notifier->n);
            QTAILQ_REMOVE(&s->insert_notifiers, insert_notifier, next);
            g_free(insert_notifier);
            break;
        }
    }

    QTAILQ_FOREACH(remove_notifier, &s->remove_notifiers, next) {
        if (remove_notifier->sd == sd) {
            notifier_remove(&remove_notifier->n);
            QTAILQ_REMOVE(&s->remove_notifiers, remove_notifier, next);
            g_free(remove_notifier);
            break;
        }
    }

    qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
}

@@ -950,11 +895,6 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)

    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
                    virtio_scsi_save, virtio_scsi_load, s);

    error_setg(&s->blocker, "block device is in use by data plane");

    QTAILQ_INIT(&s->insert_notifiers);
    QTAILQ_INIT(&s->remove_notifiers);
}

static void virtio_scsi_instance_init(Object *obj)
@@ -980,8 +920,6 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
{
    VirtIOSCSI *s = VIRTIO_SCSI(dev);

    error_free(s->blocker);

    unregister_savevm(dev, "virtio-scsi", s);
    virtio_scsi_common_unrealize(dev, errp);
}
+0 −7
Original line number Diff line number Diff line
@@ -1062,13 +1062,6 @@ int virtio_get_num_queues(VirtIODevice *vdev)
    return i;
}

int virtio_queue_get_id(VirtQueue *vq)
{
    VirtIODevice *vdev = vq->vdev;
    assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_QUEUE_MAX]);
    return vq - &vdev->vq[0];
}

void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
{
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
Loading