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

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging



Block layer patches

# gpg: Signature made Fri 23 Oct 2015 17:59:56 BST using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream: (37 commits)
  tests: Add test case for aio_disable_external
  block: Add "drained begin/end" for internal snapshot
  block: Add "drained begin/end" for transactional blockdev-backup
  block: Add "drained begin/end" for transactional backup
  block: Add "drained begin/end" for transactional external snapshot
  block: Introduce "drained begin/end" API
  aio: introduce aio_{disable,enable}_external
  dataplane: Mark host notifiers' client type as "external"
  nbd: Mark fd handlers client type as "external"
  aio: Add "is_external" flag for event handlers
  throttle: Remove throttle_group_lock/unlock()
  blockdev: Allow more options for BB-less BDS tree
  blockdev: Pull out blockdev option extraction
  blockdev: Do not create BDS for empty drive
  block: Prepare for NULL BDS
  block: Add blk_insert_bs()
  block: Prepare remaining BB functions for NULL BDS
  block: Fail requests to empty BlockBackend
  block: Make some BB functions fall back to BBRS
  block: Add BlockBackendRootState
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents bc79082e c07bc2c1
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ struct AioHandler
    IOHandler *io_write;
    int deleted;
    void *opaque;
    bool is_external;
    QLIST_ENTRY(AioHandler) node;
};

@@ -43,6 +44,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd)

void aio_set_fd_handler(AioContext *ctx,
                        int fd,
                        bool is_external,
                        IOHandler *io_read,
                        IOHandler *io_write,
                        void *opaque)
@@ -82,6 +84,7 @@ void aio_set_fd_handler(AioContext *ctx,
        node->io_read = io_read;
        node->io_write = io_write;
        node->opaque = opaque;
        node->is_external = is_external;

        node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0);
        node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0);
@@ -92,10 +95,11 @@ void aio_set_fd_handler(AioContext *ctx,

void aio_set_event_notifier(AioContext *ctx,
                            EventNotifier *notifier,
                            bool is_external,
                            EventNotifierHandler *io_read)
{
    aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
                       (IOHandler *)io_read, NULL, notifier);
                       is_external, (IOHandler *)io_read, NULL, notifier);
}

bool aio_prepare(AioContext *ctx)
@@ -257,7 +261,8 @@ bool aio_poll(AioContext *ctx, bool blocking)

    /* fill pollfds */
    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
        if (!node->deleted && node->pfd.events) {
        if (!node->deleted && node->pfd.events
            && aio_node_check(ctx, node->is_external)) {
            add_pollfd(node);
        }
    }
+7 −1
Original line number Diff line number Diff line
@@ -28,11 +28,13 @@ struct AioHandler {
    GPollFD pfd;
    int deleted;
    void *opaque;
    bool is_external;
    QLIST_ENTRY(AioHandler) node;
};

void aio_set_fd_handler(AioContext *ctx,
                        int fd,
                        bool is_external,
                        IOHandler *io_read,
                        IOHandler *io_write,
                        void *opaque)
@@ -86,6 +88,7 @@ void aio_set_fd_handler(AioContext *ctx,
        node->opaque = opaque;
        node->io_read = io_read;
        node->io_write = io_write;
        node->is_external = is_external;

        event = event_notifier_get_handle(&ctx->notifier);
        WSAEventSelect(node->pfd.fd, event,
@@ -98,6 +101,7 @@ void aio_set_fd_handler(AioContext *ctx,

void aio_set_event_notifier(AioContext *ctx,
                            EventNotifier *e,
                            bool is_external,
                            EventNotifierHandler *io_notify)
{
    AioHandler *node;
@@ -133,6 +137,7 @@ void aio_set_event_notifier(AioContext *ctx,
            node->e = e;
            node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
            node->pfd.events = G_IO_IN;
            node->is_external = is_external;
            QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);

            g_source_add_poll(&ctx->source, &node->pfd);
@@ -304,7 +309,8 @@ bool aio_poll(AioContext *ctx, bool blocking)
    /* fill fd sets */
    count = 0;
    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
        if (!node->deleted && node->io_notify) {
        if (!node->deleted && node->io_notify
            && aio_node_check(ctx, node->is_external)) {
            events[count++] = event_notifier_get_handle(node->e);
        }
    }
+2 −1
Original line number Diff line number Diff line
@@ -247,7 +247,7 @@ aio_ctx_finalize(GSource *source)
    }
    qemu_mutex_unlock(&ctx->bh_lock);

    aio_set_event_notifier(ctx, &ctx->notifier, NULL);
    aio_set_event_notifier(ctx, &ctx->notifier, false, NULL);
    event_notifier_cleanup(&ctx->notifier);
    rfifolock_destroy(&ctx->lock);
    qemu_mutex_destroy(&ctx->bh_lock);
@@ -329,6 +329,7 @@ AioContext *aio_context_new(Error **errp)
    }
    g_source_set_can_recurse(&ctx->source, true);
    aio_set_event_notifier(ctx, &ctx->notifier,
                           false,
                           (EventNotifierHandler *)
                           event_notifier_dummy_cb);
    ctx->thread_pool = NULL;
+27 −153
Original line number Diff line number Diff line
@@ -257,7 +257,6 @@ BlockDriverState *bdrv_new(void)
    for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
        QLIST_INIT(&bs->op_blockers[i]);
    }
    bdrv_iostatus_disable(bs);
    notifier_list_init(&bs->close_notifiers);
    notifier_with_return_list_init(&bs->before_write_notifiers);
    qemu_co_queue_init(&bs->throttled_reqs[0]);
@@ -857,7 +856,6 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
        goto fail_opts;
    }

    bs->guest_block_size = 512;
    bs->request_alignment = 512;
    bs->zero_beyond_eof = true;
    open_flags = bdrv_open_flags(bs, flags);
@@ -1081,6 +1079,10 @@ static int bdrv_fill_options(QDict **options, const char **pfilename,
        }
    }

    if (runstate_check(RUN_STATE_INMIGRATE)) {
        *flags |= BDRV_O_INCOMING;
    }

    return 0;
}

@@ -1908,6 +1910,10 @@ void bdrv_close(BlockDriverState *bs)
    bdrv_drain(bs); /* in case flush left pending I/O */
    notifier_list_notify(&bs->close_notifiers, bs);

    if (bs->blk) {
        blk_dev_change_media_cb(bs->blk, false);
    }

    if (bs->drv) {
        BdrvChild *child, *next;

@@ -1946,10 +1952,6 @@ void bdrv_close(BlockDriverState *bs)
        bs->full_open_options = NULL;
    }

    if (bs->blk) {
        blk_dev_change_media_cb(bs->blk, false);
    }

    QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
        g_free(ban);
    }
@@ -1998,19 +2000,10 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
    /* move some fields that need to stay attached to the device */

    /* dev info */
    bs_dest->guest_block_size   = bs_src->guest_block_size;
    bs_dest->copy_on_read       = bs_src->copy_on_read;

    bs_dest->enable_write_cache = bs_src->enable_write_cache;

    /* r/w error */
    bs_dest->on_read_error      = bs_src->on_read_error;
    bs_dest->on_write_error     = bs_src->on_write_error;

    /* i/o status */
    bs_dest->iostatus_enabled   = bs_src->iostatus_enabled;
    bs_dest->iostatus           = bs_src->iostatus;

    /* dirty bitmap */
    bs_dest->dirty_bitmaps      = bs_src->dirty_bitmaps;
}
@@ -2497,82 +2490,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
    *nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
}

void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
                       BlockdevOnError on_write_error)
{
    bs->on_read_error = on_read_error;
    bs->on_write_error = on_write_error;
}

BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read)
{
    return is_read ? bs->on_read_error : bs->on_write_error;
}

BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error)
{
    BlockdevOnError on_err = is_read ? bs->on_read_error : bs->on_write_error;

    switch (on_err) {
    case BLOCKDEV_ON_ERROR_ENOSPC:
        return (error == ENOSPC) ?
               BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
    case BLOCKDEV_ON_ERROR_STOP:
        return BLOCK_ERROR_ACTION_STOP;
    case BLOCKDEV_ON_ERROR_REPORT:
        return BLOCK_ERROR_ACTION_REPORT;
    case BLOCKDEV_ON_ERROR_IGNORE:
        return BLOCK_ERROR_ACTION_IGNORE;
    default:
        abort();
    }
}

static void send_qmp_error_event(BlockDriverState *bs,
                                 BlockErrorAction action,
                                 bool is_read, int error)
{
    IoOperationType optype;

    optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
    qapi_event_send_block_io_error(bdrv_get_device_name(bs), optype, action,
                                   bdrv_iostatus_is_enabled(bs),
                                   error == ENOSPC, strerror(error),
                                   &error_abort);
}

/* This is done by device models because, while the block layer knows
 * about the error, it does not know whether an operation comes from
 * the device or the block layer (from a job, for example).
 */
void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
                       bool is_read, int error)
{
    assert(error >= 0);

    if (action == BLOCK_ERROR_ACTION_STOP) {
        /* First set the iostatus, so that "info block" returns an iostatus
         * that matches the events raised so far (an additional error iostatus
         * is fine, but not a lost one).
         */
        bdrv_iostatus_set_err(bs, error);

        /* Then raise the request to stop the VM and the event.
         * qemu_system_vmstop_request_prepare has two effects.  First,
         * it ensures that the STOP event always comes after the
         * BLOCK_IO_ERROR event.  Second, it ensures that even if management
         * can observe the STOP event and do a "cont" before the STOP
         * event is issued, the VM will not stop.  In this case, vm_start()
         * also ensures that the STOP/RESUME pair of events is emitted.
         */
        qemu_system_vmstop_request_prepare();
        send_qmp_error_event(bs, action, is_read, error);
        qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
    } else {
        send_qmp_error_event(bs, action, is_read, error);
    }
}

int bdrv_is_read_only(BlockDriverState *bs)
{
    return bs->read_only;
@@ -2766,6 +2683,11 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
        blk = blk_by_name(device);

        if (blk) {
            if (!blk_bs(blk)) {
                error_setg(errp, "Device '%s' has no medium", device);
                return NULL;
            }

            return blk_bs(blk);
        }
    }
@@ -3136,16 +3058,24 @@ void bdrv_invalidate_cache_all(Error **errp)
/**
 * Return TRUE if the media is present
 */
int bdrv_is_inserted(BlockDriverState *bs)
bool bdrv_is_inserted(BlockDriverState *bs)
{
    BlockDriver *drv = bs->drv;
    BdrvChild *child;

    if (!drv)
        return 0;
    if (!drv->bdrv_is_inserted)
        return 1;
    if (!drv) {
        return false;
    }
    if (drv->bdrv_is_inserted) {
        return drv->bdrv_is_inserted(bs);
    }
    QLIST_FOREACH(child, &bs->children, next) {
        if (!bdrv_is_inserted(child->bs)) {
            return false;
        }
    }
    return true;
}

/**
 * Return whether the media changed since the last call to this
@@ -3195,11 +3125,6 @@ void bdrv_lock_medium(BlockDriverState *bs, bool locked)
    }
}

void bdrv_set_guest_block_size(BlockDriverState *bs, int align)
{
    bs->guest_block_size = align;
}

BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
{
    BdrvDirtyBitmap *bm;
@@ -3597,46 +3522,6 @@ bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
    return true;
}

void bdrv_iostatus_enable(BlockDriverState *bs)
{
    bs->iostatus_enabled = true;
    bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
}

/* The I/O status is only enabled if the drive explicitly
 * enables it _and_ the VM is configured to stop on errors */
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
{
    return (bs->iostatus_enabled &&
           (bs->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
            bs->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
            bs->on_read_error == BLOCKDEV_ON_ERROR_STOP));
}

void bdrv_iostatus_disable(BlockDriverState *bs)
{
    bs->iostatus_enabled = false;
}

void bdrv_iostatus_reset(BlockDriverState *bs)
{
    if (bdrv_iostatus_is_enabled(bs)) {
        bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
        if (bs->job) {
            block_job_iostatus_reset(bs->job);
        }
    }
}

void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
{
    assert(bdrv_iostatus_is_enabled(bs));
    if (bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
        bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
                                         BLOCK_DEVICE_IO_STATUS_FAILED;
    }
}

void bdrv_img_create(const char *filename, const char *fmt,
                     const char *base_filename, const char *base_fmt,
                     char *options, uint64_t img_size, int flags,
@@ -4148,14 +4033,3 @@ void bdrv_refresh_filename(BlockDriverState *bs)
        QDECREF(json);
    }
}

/* This accessor function purpose is to allow the device models to access the
 * BlockAcctStats structure embedded inside a BlockDriverState without being
 * aware of the BlockDriverState structure layout.
 * It will go away when the BlockAcctStats structure will be moved inside
 * the device models.
 */
BlockAcctStats *bdrv_get_stats(BlockDriverState *bs)
{
    return &bs->stats;
}
+0 −8
Original line number Diff line number Diff line
@@ -47,14 +47,6 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie)
}


void block_acct_highest_sector(BlockAcctStats *stats, int64_t sector_num,
                               unsigned int nb_sectors)
{
    if (stats->wr_highest_sector < sector_num + nb_sectors - 1) {
        stats->wr_highest_sector = sector_num + nb_sectors - 1;
    }
}

void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
                      int num_requests)
{
Loading