Commit 3ee933c9 authored by Peter Maydell's avatar Peter Maydell
Browse files

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



Block pull request

# gpg: Signature made Wed 28 May 2014 13:31:15 BST using RSA key ID 81AB73C8
# gpg: Can't check signature: public key not found

* remotes/stefanha/tags/block-pull-request: (33 commits)
  block/sheepdog: Don't use qerror_report()
  block/sheepdog: Fix silent sd_open(), sd_create() failures
  block/sheepdog: Propagate errors to open and create methods
  block/sheepdog: Propagate errors through find_vdi_name()
  block/sheepdog: Propagate errors through do_sd_create()
  block/sheepdog: Propagate errors through sd_prealloc()
  block/sheepdog: Propagate errors through get_sheep_fd()
  block/sheepdog: Propagate errors through connect_to_sdog()
  block/vvfat: Propagate errors through init_directories()
  block/vvfat: Propagate errors through enable_write_target()
  block/ssh: Propagate errors to open and create methods
  block/ssh: Propagate errors through connect_to_ssh()
  block/ssh: Propagate errors through authenticate()
  block/ssh: Propagate errors through check_host_key()
  block/ssh: Drop superfluous libssh2_session_last_errno() calls
  block/rbd: Propagate errors to open and create methods
  qemu-nbd: Don't use qerror_report()
  blockdev: Don't use qerror_report() in do_drive_del()
  blockdev: Don't use qerror_report_err() in drive_init()
  docs: Define refcount_bits value
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 052367ba fbab9ccb
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ typedef struct BlkMigDevState {
    unsigned long *aio_bitmap;
    int64_t completed_sectors;
    BdrvDirtyBitmap *dirty_bitmap;
    Error *blocker;
} BlkMigDevState;

typedef struct BlkMigBlock {
@@ -361,7 +362,8 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
        bmds->completed_sectors = 0;
        bmds->shared_base = block_mig_state.shared_base;
        alloc_aio_bitmap(bmds);
        bdrv_set_in_use(bs, 1);
        error_setg(&bmds->blocker, "block device is in use by migration");
        bdrv_op_block_all(bs, bmds->blocker);
        bdrv_ref(bs);

        block_mig_state.total_sector_sum += sectors;
@@ -599,7 +601,8 @@ static void blk_mig_cleanup(void)
    blk_mig_lock();
    while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
        bdrv_set_in_use(bmds->bs, 0);
        bdrv_op_unblock_all(bmds->bs, bmds->blocker);
        error_free(bmds->blocker);
        bdrv_unref(bmds->bs);
        g_free(bmds->aio_bitmap);
        g_free(bmds);
+119 −33
Original line number Diff line number Diff line
@@ -335,6 +335,7 @@ void bdrv_register(BlockDriver *bdrv)
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
{
    BlockDriverState *bs;
    int i;

    if (bdrv_find(device_name)) {
        error_setg(errp, "Device with id '%s' already exists",
@@ -353,6 +354,9 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
    if (device_name[0] != '\0') {
        QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
    }
    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);
@@ -1090,6 +1094,37 @@ fail:
    return ret;
}

void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
{

    if (bs->backing_hd) {
        assert(bs->backing_blocker);
        bdrv_op_unblock_all(bs->backing_hd, bs->backing_blocker);
    } else if (backing_hd) {
        error_setg(&bs->backing_blocker,
                   "device is used as backing hd of '%s'",
                   bs->device_name);
    }

    bs->backing_hd = backing_hd;
    if (!backing_hd) {
        error_free(bs->backing_blocker);
        bs->backing_blocker = NULL;
        goto out;
    }
    bs->open_flags &= ~BDRV_O_NO_BACKING;
    pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename);
    pstrcpy(bs->backing_format, sizeof(bs->backing_format),
            backing_hd->drv ? backing_hd->drv->format_name : "");

    bdrv_op_block_all(bs->backing_hd, bs->backing_blocker);
    /* Otherwise we won't be able to commit due to check in bdrv_commit */
    bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT,
                    bs->backing_blocker);
out:
    bdrv_refresh_limits(bs);
}

/*
 * Opens the backing file for a BlockDriverState if not yet open
 *
@@ -1103,6 +1138,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
    char *backing_filename = g_malloc0(PATH_MAX);
    int ret = 0;
    BlockDriver *back_drv = NULL;
    BlockDriverState *backing_hd;
    Error *local_err = NULL;

    if (bs->backing_hd != NULL) {
@@ -1125,30 +1161,26 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
        bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
    }

    backing_hd = bdrv_new("", errp);

    if (bs->backing_format[0] != '\0') {
        back_drv = bdrv_find_format(bs->backing_format);
    }

    assert(bs->backing_hd == NULL);
    ret = bdrv_open(&bs->backing_hd,
    ret = bdrv_open(&backing_hd,
                    *backing_filename ? backing_filename : NULL, NULL, options,
                    bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
    if (ret < 0) {
        bs->backing_hd = NULL;
        bdrv_unref(backing_hd);
        backing_hd = NULL;
        bs->open_flags |= BDRV_O_NO_BACKING;
        error_setg(errp, "Could not open backing file: %s",
                   error_get_pretty(local_err));
        error_free(local_err);
        goto free_exit;
    }

    if (bs->backing_hd->file) {
        pstrcpy(bs->backing_file, sizeof(bs->backing_file),
                bs->backing_hd->file->filename);
    }

    /* Recalculate the BlockLimits with the backing file */
    bdrv_refresh_limits(bs);
    bdrv_set_backing_hd(bs, backing_hd);

free_exit:
    g_free(backing_filename);
@@ -1784,8 +1816,9 @@ void bdrv_close(BlockDriverState *bs)

    if (bs->drv) {
        if (bs->backing_hd) {
            bdrv_unref(bs->backing_hd);
            bs->backing_hd = NULL;
            BlockDriverState *backing_hd = bs->backing_hd;
            bdrv_set_backing_hd(bs, NULL);
            bdrv_unref(backing_hd);
        }
        bs->drv->bdrv_close(bs);
        g_free(bs->opaque);
@@ -1945,13 +1978,14 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
    bs_dest->refcnt             = bs_src->refcnt;

    /* job */
    bs_dest->in_use             = bs_src->in_use;
    bs_dest->job                = bs_src->job;

    /* keep the same entry in bdrv_states */
    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
            bs_src->device_name);
    bs_dest->device_list = bs_src->device_list;
    memcpy(bs_dest->op_blockers, bs_src->op_blockers,
           sizeof(bs_dest->op_blockers));
}

/*
@@ -1986,7 +2020,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
    assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
    assert(bs_new->job == NULL);
    assert(bs_new->dev == NULL);
    assert(bs_new->in_use == 0);
    assert(bs_new->io_limits_enabled == false);
    assert(!throttle_have_timer(&bs_new->throttle_state));

@@ -2005,7 +2038,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
    /* Check a few fields that should remain attached to the device */
    assert(bs_new->dev == NULL);
    assert(bs_new->job == NULL);
    assert(bs_new->in_use == 0);
    assert(bs_new->io_limits_enabled == false);
    assert(!throttle_have_timer(&bs_new->throttle_state));

@@ -2038,19 +2070,14 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)

    /* The contents of 'tmp' will become bs_top, as we are
     * swapping bs_new and bs_top contents. */
    bs_top->backing_hd = bs_new;
    bs_top->open_flags &= ~BDRV_O_NO_BACKING;
    pstrcpy(bs_top->backing_file, sizeof(bs_top->backing_file),
            bs_new->filename);
    pstrcpy(bs_top->backing_format, sizeof(bs_top->backing_format),
            bs_new->drv ? bs_new->drv->format_name : "");
    bdrv_set_backing_hd(bs_top, bs_new);
}

static void bdrv_delete(BlockDriverState *bs)
{
    assert(!bs->dev);
    assert(!bs->job);
    assert(!bs->in_use);
    assert(bdrv_op_blocker_is_empty(bs));
    assert(!bs->refcnt);
    assert(QLIST_EMPTY(&bs->dirty_bitmaps));

@@ -2232,7 +2259,8 @@ int bdrv_commit(BlockDriverState *bs)
        return -ENOTSUP;
    }

    if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) {
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, NULL) ||
        bdrv_op_is_blocked(bs->backing_hd, BLOCK_OP_TYPE_COMMIT, NULL)) {
        return -EBUSY;
    }

@@ -2636,13 +2664,11 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
    if (ret) {
        goto exit;
    }
    new_top_bs->backing_hd = base_bs;

    bdrv_refresh_limits(new_top_bs);
    bdrv_set_backing_hd(new_top_bs, base_bs);

    QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
        /* so that bdrv_close() does not recursively close the chain */
        intermediate_state->bs->backing_hd = NULL;
        bdrv_set_backing_hd(intermediate_state->bs, NULL);
        bdrv_unref(intermediate_state->bs);
    }
    ret = 0;
@@ -3494,8 +3520,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
        return -ENOTSUP;
    if (bs->read_only)
        return -EACCES;
    if (bdrv_in_use(bs))
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
        return -EBUSY;
    }
    ret = drv->bdrv_truncate(bs, offset);
    if (ret == 0) {
        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
@@ -5325,15 +5352,74 @@ void bdrv_unref(BlockDriverState *bs)
    }
}

void bdrv_set_in_use(BlockDriverState *bs, int in_use)
struct BdrvOpBlocker {
    Error *reason;
    QLIST_ENTRY(BdrvOpBlocker) list;
};

bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
{
    assert(bs->in_use != in_use);
    bs->in_use = in_use;
    BdrvOpBlocker *blocker;
    assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
    if (!QLIST_EMPTY(&bs->op_blockers[op])) {
        blocker = QLIST_FIRST(&bs->op_blockers[op]);
        if (errp) {
            error_setg(errp, "Device '%s' is busy: %s",
                       bs->device_name, error_get_pretty(blocker->reason));
        }
        return true;
    }
    return false;
}

int bdrv_in_use(BlockDriverState *bs)
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason)
{
    return bs->in_use;
    BdrvOpBlocker *blocker;
    assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);

    blocker = g_malloc0(sizeof(BdrvOpBlocker));
    blocker->reason = reason;
    QLIST_INSERT_HEAD(&bs->op_blockers[op], blocker, list);
}

void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason)
{
    BdrvOpBlocker *blocker, *next;
    assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
    QLIST_FOREACH_SAFE(blocker, &bs->op_blockers[op], list, next) {
        if (blocker->reason == reason) {
            QLIST_REMOVE(blocker, list);
            g_free(blocker);
        }
    }
}

void bdrv_op_block_all(BlockDriverState *bs, Error *reason)
{
    int i;
    for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
        bdrv_op_block(bs, i, reason);
    }
}

void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason)
{
    int i;
    for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
        bdrv_op_unblock(bs, i, reason);
    }
}

bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
{
    int i;

    for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
        if (!QLIST_EMPTY(&bs->op_blockers[i])) {
            return false;
        }
    }
    return true;
}

void bdrv_iostatus_enable(BlockDriverState *bs)
+1 −1
Original line number Diff line number Diff line
@@ -498,7 +498,7 @@ immediate_exit:
            /* drop the bs loop chain formed by the swap: break the loop then
             * trigger the unref from the top one */
            BlockDriverState *p = s->base->backing_hd;
            s->base->backing_hd = NULL;
            bdrv_set_backing_hd(s->base, NULL);
            bdrv_unref(p);
        }
    }
+2 −1
Original line number Diff line number Diff line
@@ -379,7 +379,8 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
    BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);

    if (!bs->drv) {
        return -ENOMEDIUM;
        ret = -ENOMEDIUM;
        goto out;
    }

    /* Call .bdrv_co_readv() directly instead of using the public block-layer
+39 −32
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ typedef struct BDRVRBDState {
static int qemu_rbd_next_tok(char *dst, int dst_len,
                             char *src, char delim,
                             const char *name,
                             char **p)
                             char **p, Error **errp)
{
    int l;
    char *end;
@@ -128,10 +128,10 @@ static int qemu_rbd_next_tok(char *dst, int dst_len,
    }
    l = strlen(src);
    if (l >= dst_len) {
        error_report("%s too long", name);
        error_setg(errp, "%s too long", name);
        return -EINVAL;
    } else if (l == 0) {
        error_report("%s too short", name);
        error_setg(errp, "%s too short", name);
        return -EINVAL;
    }

@@ -157,13 +157,15 @@ static int qemu_rbd_parsename(const char *filename,
                              char *pool, int pool_len,
                              char *snap, int snap_len,
                              char *name, int name_len,
                              char *conf, int conf_len)
                              char *conf, int conf_len,
                              Error **errp)
{
    const char *start;
    char *p, *buf;
    int ret;

    if (!strstart(filename, "rbd:", &start)) {
        error_setg(errp, "File name must start with 'rbd:'");
        return -EINVAL;
    }

@@ -172,7 +174,8 @@ static int qemu_rbd_parsename(const char *filename,
    *snap = '\0';
    *conf = '\0';

    ret = qemu_rbd_next_tok(pool, pool_len, p, '/', "pool name", &p);
    ret = qemu_rbd_next_tok(pool, pool_len, p,
                            '/', "pool name", &p, errp);
    if (ret < 0 || !p) {
        ret = -EINVAL;
        goto done;
@@ -180,21 +183,25 @@ static int qemu_rbd_parsename(const char *filename,
    qemu_rbd_unescape(pool);

    if (strchr(p, '@')) {
        ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p);
        ret = qemu_rbd_next_tok(name, name_len, p,
                                '@', "object name", &p, errp);
        if (ret < 0) {
            goto done;
        }
        ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p);
        ret = qemu_rbd_next_tok(snap, snap_len, p,
                                ':', "snap name", &p, errp);
        qemu_rbd_unescape(snap);
    } else {
        ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p);
        ret = qemu_rbd_next_tok(name, name_len, p,
                                ':', "object name", &p, errp);
    }
    qemu_rbd_unescape(name);
    if (ret < 0 || !p) {
        goto done;
    }

    ret = qemu_rbd_next_tok(conf, conf_len, p, '\0', "configuration", &p);
    ret = qemu_rbd_next_tok(conf, conf_len, p,
                            '\0', "configuration", &p, errp);

done:
    g_free(buf);
@@ -229,7 +236,7 @@ static char *qemu_rbd_parse_clientname(const char *conf, char *clientname)
    return NULL;
}

static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
static int qemu_rbd_set_conf(rados_t cluster, const char *conf, Error **errp)
{
    char *p, *buf;
    char name[RBD_MAX_CONF_NAME_SIZE];
@@ -241,20 +248,20 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)

    while (p) {
        ret = qemu_rbd_next_tok(name, sizeof(name), p,
                                '=', "conf option name", &p);
                                '=', "conf option name", &p, errp);
        if (ret < 0) {
            break;
        }
        qemu_rbd_unescape(name);

        if (!p) {
            error_report("conf option %s has no value", name);
            error_setg(errp, "conf option %s has no value", name);
            ret = -EINVAL;
            break;
        }

        ret = qemu_rbd_next_tok(value, sizeof(value), p,
                                ':', "conf option value", &p);
                                ':', "conf option value", &p, errp);
        if (ret < 0) {
            break;
        }
@@ -263,7 +270,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
        if (strcmp(name, "conf") == 0) {
            ret = rados_conf_read_file(cluster, value);
            if (ret < 0) {
                error_report("error reading conf file %s", value);
                error_setg(errp, "error reading conf file %s", value);
                break;
            }
        } else if (strcmp(name, "id") == 0) {
@@ -271,7 +278,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
        } else {
            ret = rados_conf_set(cluster, name, value);
            if (ret < 0) {
                error_report("invalid conf option %s", name);
                error_setg(errp, "invalid conf option %s", name);
                ret = -EINVAL;
                break;
            }
@@ -285,6 +292,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
                           Error **errp)
{
    Error *local_err = NULL;
    int64_t bytes = 0;
    int64_t objsize;
    int obj_order = 0;
@@ -301,7 +309,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
    if (qemu_rbd_parsename(filename, pool, sizeof(pool),
                           snap_buf, sizeof(snap_buf),
                           name, sizeof(name),
                           conf, sizeof(conf)) < 0) {
                           conf, sizeof(conf), &local_err) < 0) {
        error_propagate(errp, local_err);
        return -EINVAL;
    }

@@ -313,11 +322,11 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
            if (options->value.n) {
                objsize = options->value.n;
                if ((objsize - 1) & objsize) {    /* not a power of 2? */
                    error_report("obj size needs to be power of 2");
                    error_setg(errp, "obj size needs to be power of 2");
                    return -EINVAL;
                }
                if (objsize < 4096) {
                    error_report("obj size too small");
                    error_setg(errp, "obj size too small");
                    return -EINVAL;
                }
                obj_order = ffs(objsize) - 1;
@@ -328,7 +337,7 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,

    clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
    if (rados_create(&cluster, clientname) < 0) {
        error_report("error initializing");
        error_setg(errp, "error initializing");
        return -EIO;
    }

@@ -338,20 +347,20 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
    }

    if (conf[0] != '\0' &&
        qemu_rbd_set_conf(cluster, conf) < 0) {
        error_report("error setting config options");
        qemu_rbd_set_conf(cluster, conf, &local_err) < 0) {
        rados_shutdown(cluster);
        error_propagate(errp, local_err);
        return -EIO;
    }

    if (rados_connect(cluster) < 0) {
        error_report("error connecting");
        error_setg(errp, "error connecting");
        rados_shutdown(cluster);
        return -EIO;
    }

    if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) {
        error_report("error opening pool %s", pool);
        error_setg(errp, "error opening pool %s", pool);
        rados_shutdown(cluster);
        return -EIO;
    }
@@ -441,8 +450,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (local_err) {
        qerror_report_err(local_err);
        error_free(local_err);
        error_propagate(errp, local_err);
        qemu_opts_del(opts);
        return -EINVAL;
    }
@@ -452,7 +460,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
    if (qemu_rbd_parsename(filename, pool, sizeof(pool),
                           snap_buf, sizeof(snap_buf),
                           s->name, sizeof(s->name),
                           conf, sizeof(conf)) < 0) {
                           conf, sizeof(conf), errp) < 0) {
        r = -EINVAL;
        goto failed_opts;
    }
@@ -460,7 +468,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
    clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
    r = rados_create(&s->cluster, clientname);
    if (r < 0) {
        error_report("error initializing");
        error_setg(&local_err, "error initializing");
        goto failed_opts;
    }

@@ -488,28 +496,27 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
    }

    if (conf[0] != '\0') {
        r = qemu_rbd_set_conf(s->cluster, conf);
        r = qemu_rbd_set_conf(s->cluster, conf, errp);
        if (r < 0) {
            error_report("error setting config options");
            goto failed_shutdown;
        }
    }

    r = rados_connect(s->cluster);
    if (r < 0) {
        error_report("error connecting");
        error_setg(&local_err, "error connecting");
        goto failed_shutdown;
    }

    r = rados_ioctx_create(s->cluster, pool, &s->io_ctx);
    if (r < 0) {
        error_report("error opening pool %s", pool);
        error_setg(&local_err, "error opening pool %s", pool);
        goto failed_shutdown;
    }

    r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
    if (r < 0) {
        error_report("error reading header from %s", s->name);
        error_setg(&local_err, "error reading header from %s", s->name);
        goto failed_open;
    }

Loading