Commit 0b4384d0 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2017-02-12' into staging



Block patches

# gpg: Signature made Sun 12 Feb 2017 01:26:20 GMT
# gpg:                using RSA key 0xF407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2017-02-12: (21 commits)
  qemu-img: Avoid setting ret to unused value in img_convert()
  qemu-img: Use qemu_strtoul() rather than raw strtoul()
  qemu-io: don't allow I/O operations larger than BDRV_REQUEST_MAX_BYTES
  qcow2: Optimize the refcount-block overlap check
  qemu-io: Add failure regression tests
  qemu-iotests: Add _unsupported_fmt helper
  qemu-io: Return non-zero exit code on failure
  block/nfs: fix naming of runtime opts
  block/nfs: fix NULL pointer dereference in URI parsing
  block: bdrv_invalidate_cache: invalidate children first
  block/qapi: reduce the execution time of qmp_query_blockstats
  block/qapi: reduce the coupling between the bdrv_query_stats and bdrv_query_bds_stats
  qemu-iotest: test to lookup protocol-based image with relative backing
  qemu-iotests: Don't create fifos / pidfiles with protocol paths
  block: check full backing filename when searching protocol filenames
  block/vmdk: Fix the endian problem of buf_len and lba
  iotests: record separate timings per format,protocol pair
  iotests: Fix reference output for 059
  qapi: Tweak error message of bdrv_query_image_info
  qemu-img: Improve commit invalid base message
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ed3d90df 10d6eda1
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -3145,6 +3145,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
    int is_protocol = 0;
    BlockDriverState *curr_bs = NULL;
    BlockDriverState *retval = NULL;
    Error *local_error = NULL;

    if (!bs || !bs->drv || !backing_file) {
        return NULL;
@@ -3165,6 +3166,18 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
                retval = curr_bs->backing->bs;
                break;
            }
            /* Also check against the full backing filename for the image */
            bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
                                           &local_error);
            if (local_error == NULL) {
                if (strcmp(backing_file, backing_file_full) == 0) {
                    retval = curr_bs->backing->bs;
                    break;
                }
            } else {
                error_free(local_error);
                local_error = NULL;
            }
        } else {
            /* If not an absolute filename path, make it relative to the current
             * image's filename path */
@@ -3235,19 +3248,18 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
    if (!(bs->open_flags & BDRV_O_INACTIVE)) {
        return;
    }
    bs->open_flags &= ~BDRV_O_INACTIVE;

    if (bs->drv->bdrv_invalidate_cache) {
        bs->drv->bdrv_invalidate_cache(bs, &local_err);
    QLIST_FOREACH(child, &bs->children, next) {
        bdrv_invalidate_cache(child->bs, &local_err);
        if (local_err) {
            bs->open_flags |= BDRV_O_INACTIVE;
            error_propagate(errp, local_err);
            return;
        }
    }

    QLIST_FOREACH(child, &bs->children, next) {
        bdrv_invalidate_cache(child->bs, &local_err);
    bs->open_flags &= ~BDRV_O_INACTIVE;
    if (bs->drv->bdrv_invalidate_cache) {
        bs->drv->bdrv_invalidate_cache(bs, &local_err);
        if (local_err) {
            bs->open_flags |= BDRV_O_INACTIVE;
            error_propagate(errp, local_err);
+25 −24
Original line number Diff line number Diff line
@@ -108,12 +108,13 @@ static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
    qdict_put(options, "path", qstring_from_str(uri->path));

    for (i = 0; i < qp->n; i++) {
        unsigned long long val;
        if (!qp->p[i].value) {
            error_setg(errp, "Value for NFS parameter expected: %s",
                       qp->p[i].name);
            goto out;
        }
        if (parse_uint_full(qp->p[i].value, NULL, 0)) {
        if (parse_uint_full(qp->p[i].value, &val, 0)) {
            error_setg(errp, "Illegal value for NFS parameter: %s",
                       qp->p[i].name);
            goto out;
@@ -358,27 +359,27 @@ static QemuOptsList runtime_opts = {
            .help = "Path of the image on the host",
        },
        {
            .name = "uid",
            .name = "user",
            .type = QEMU_OPT_NUMBER,
            .help = "UID value to use when talking to the server",
        },
        {
            .name = "gid",
            .name = "group",
            .type = QEMU_OPT_NUMBER,
            .help = "GID value to use when talking to the server",
        },
        {
            .name = "tcp-syncnt",
            .name = "tcp-syn-count",
            .type = QEMU_OPT_NUMBER,
            .help = "Number of SYNs to send during the session establish",
        },
        {
            .name = "readahead",
            .name = "readahead-size",
            .type = QEMU_OPT_NUMBER,
            .help = "Set the readahead size in bytes",
        },
        {
            .name = "pagecache",
            .name = "page-cache-size",
            .type = QEMU_OPT_NUMBER,
            .help = "Set the pagecache size in bytes",
        },
@@ -507,29 +508,29 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
        goto fail;
    }

    if (qemu_opt_get(opts, "uid")) {
        client->uid = qemu_opt_get_number(opts, "uid", 0);
    if (qemu_opt_get(opts, "user")) {
        client->uid = qemu_opt_get_number(opts, "user", 0);
        nfs_set_uid(client->context, client->uid);
    }

    if (qemu_opt_get(opts, "gid")) {
        client->gid = qemu_opt_get_number(opts, "gid", 0);
    if (qemu_opt_get(opts, "group")) {
        client->gid = qemu_opt_get_number(opts, "group", 0);
        nfs_set_gid(client->context, client->gid);
    }

    if (qemu_opt_get(opts, "tcp-syncnt")) {
        client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syncnt", 0);
    if (qemu_opt_get(opts, "tcp-syn-count")) {
        client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syn-count", 0);
        nfs_set_tcp_syncnt(client->context, client->tcp_syncnt);
    }

#ifdef LIBNFS_FEATURE_READAHEAD
    if (qemu_opt_get(opts, "readahead")) {
    if (qemu_opt_get(opts, "readahead-size")) {
        if (open_flags & BDRV_O_NOCACHE) {
            error_setg(errp, "Cannot enable NFS readahead "
                             "if cache.direct = on");
            goto fail;
        }
        client->readahead = qemu_opt_get_number(opts, "readahead", 0);
        client->readahead = qemu_opt_get_number(opts, "readahead-size", 0);
        if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) {
            error_report("NFS Warning: Truncating NFS readahead "
                         "size to %d", QEMU_NFS_MAX_READAHEAD_SIZE);
@@ -544,13 +545,13 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
#endif

#ifdef LIBNFS_FEATURE_PAGECACHE
    if (qemu_opt_get(opts, "pagecache")) {
    if (qemu_opt_get(opts, "page-cache-size")) {
        if (open_flags & BDRV_O_NOCACHE) {
            error_setg(errp, "Cannot enable NFS pagecache "
                             "if cache.direct = on");
            goto fail;
        }
        client->pagecache = qemu_opt_get_number(opts, "pagecache", 0);
        client->pagecache = qemu_opt_get_number(opts, "page-cache-size", 0);
        if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) {
            error_report("NFS Warning: Truncating NFS pagecache "
                         "size to %d pages", QEMU_NFS_MAX_PAGECACHE_SIZE);
@@ -803,21 +804,21 @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
    qdict_put(opts, "path", qstring_from_str(client->path));

    if (client->uid) {
        qdict_put(opts, "uid", qint_from_int(client->uid));
        qdict_put(opts, "user", qint_from_int(client->uid));
    }
    if (client->gid) {
        qdict_put(opts, "gid", qint_from_int(client->gid));
        qdict_put(opts, "group", qint_from_int(client->gid));
    }
    if (client->tcp_syncnt) {
        qdict_put(opts, "tcp-syncnt",
        qdict_put(opts, "tcp-syn-cnt",
                  qint_from_int(client->tcp_syncnt));
    }
    if (client->readahead) {
        qdict_put(opts, "readahead",
        qdict_put(opts, "readahead-size",
                  qint_from_int(client->readahead));
    }
    if (client->pagecache) {
        qdict_put(opts, "pagecache",
        qdict_put(opts, "page-cache-size",
                  qint_from_int(client->pagecache));
    }
    if (client->debug) {
+43 −56
Original line number Diff line number Diff line
@@ -237,8 +237,8 @@ void bdrv_query_image_info(BlockDriverState *bs,

    size = bdrv_getlength(bs);
    if (size < 0) {
        error_setg_errno(errp, -size, "Can't get size of device '%s'",
                         bdrv_get_device_name(bs));
        error_setg_errno(errp, -size, "Can't get image size '%s'",
                         bs->exact_filename);
        goto out;
    }

@@ -357,10 +357,6 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
    qapi_free_BlockInfo(info);
}

static BlockStats *bdrv_query_stats(BlockBackend *blk,
                                    const BlockDriverState *bs,
                                    bool query_backing);

static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
{
    BlockAcctStats *stats = blk_get_stats(blk);
@@ -428,9 +424,18 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
    }
}

static void bdrv_query_bds_stats(BlockStats *s, const BlockDriverState *bs,
static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
                                 bool query_backing)
{
    BlockStats *s = NULL;

    s = g_malloc0(sizeof(*s));
    s->stats = g_malloc0(sizeof(*s->stats));

    if (!bs) {
        return s;
    }

    if (bdrv_get_node_name(bs)[0]) {
        s->has_node_name = true;
        s->node_name = g_strdup(bdrv_get_node_name(bs));
@@ -440,32 +445,12 @@ static void bdrv_query_bds_stats(BlockStats *s, const BlockDriverState *bs,

    if (bs->file) {
        s->has_parent = true;
        s->parent = bdrv_query_stats(NULL, bs->file->bs, query_backing);
        s->parent = bdrv_query_bds_stats(bs->file->bs, query_backing);
    }

    if (query_backing && bs->backing) {
        s->has_backing = true;
        s->backing = bdrv_query_stats(NULL, bs->backing->bs, query_backing);
    }

}

static BlockStats *bdrv_query_stats(BlockBackend *blk,
                                    const BlockDriverState *bs,
                                    bool query_backing)
{
    BlockStats *s;

    s = g_malloc0(sizeof(*s));
    s->stats = g_malloc0(sizeof(*s->stats));

    if (blk) {
        s->has_device = true;
        s->device = g_strdup(blk_name(blk));
        bdrv_query_blk_stats(s->stats, blk);
    }
    if (bs) {
        bdrv_query_bds_stats(s, bs, query_backing);
        s->backing = bdrv_query_bds_stats(bs->backing->bs, query_backing);
    }

    return s;
@@ -494,43 +479,45 @@ BlockInfoList *qmp_query_block(Error **errp)
    return head;
}

static bool next_query_bds(BlockBackend **blk, BlockDriverState **bs,
                           bool query_nodes)
{
    if (query_nodes) {
        *bs = bdrv_next_node(*bs);
        return !!*bs;
    }

    *blk = blk_next(*blk);
    *bs = *blk ? blk_bs(*blk) : NULL;

    return !!*blk;
}

BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
                                     bool query_nodes,
                                     Error **errp)
{
    BlockStatsList *head = NULL, **p_next = &head;
    BlockBackend *blk = NULL;
    BlockDriverState *bs = NULL;
    BlockBackend *blk;
    BlockDriverState *bs;

    /* Just to be safe if query_nodes is not always initialized */
    query_nodes = has_query_nodes && query_nodes;
    if (has_query_nodes && query_nodes) {
        for (bs = bdrv_next_node(NULL); bs; bs = bdrv_next_node(bs)) {
            BlockStatsList *info = g_malloc0(sizeof(*info));
            AioContext *ctx = bdrv_get_aio_context(bs);

            aio_context_acquire(ctx);
            info->value = bdrv_query_bds_stats(bs, false);
            aio_context_release(ctx);

    while (next_query_bds(&blk, &bs, query_nodes)) {
            *p_next = info;
            p_next = &info->next;
        }
    } else {
        for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
            BlockStatsList *info = g_malloc0(sizeof(*info));
        AioContext *ctx = blk ? blk_get_aio_context(blk)
                              : bdrv_get_aio_context(bs);
            AioContext *ctx = blk_get_aio_context(blk);
            BlockStats *s;

            aio_context_acquire(ctx);
        info->value = bdrv_query_stats(blk, bs, !query_nodes);
            s = bdrv_query_bds_stats(blk_bs(blk), true);
            s->has_device = true;
            s->device = g_strdup(blk_name(blk));
            bdrv_query_blk_stats(s->stats, blk);
            aio_context_release(ctx);

            info->value = s;
            *p_next = info;
            p_next = &info->next;
        }
    }

    return head;
}
+23 −1
Original line number Diff line number Diff line
@@ -83,6 +83,16 @@ static Qcow2SetRefcountFunc *const set_refcount_funcs[] = {
/*********************************************************/
/* refcount handling */

static void update_max_refcount_table_index(BDRVQcow2State *s)
{
    unsigned i = s->refcount_table_size - 1;
    while (i > 0 && (s->refcount_table[i] & REFT_OFFSET_MASK) == 0) {
        i--;
    }
    /* Set s->max_refcount_table_index to the index of the last used entry */
    s->max_refcount_table_index = i;
}

int qcow2_refcount_init(BlockDriverState *bs)
{
    BDRVQcow2State *s = bs->opaque;
@@ -111,6 +121,7 @@ int qcow2_refcount_init(BlockDriverState *bs)
        }
        for(i = 0; i < s->refcount_table_size; i++)
            be64_to_cpus(&s->refcount_table[i]);
        update_max_refcount_table_index(s);
    }
    return 0;
 fail:
@@ -439,6 +450,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
        }

        s->refcount_table[refcount_table_index] = new_block;
        /* If there's a hole in s->refcount_table then it can happen
         * that refcount_table_index < s->max_refcount_table_index */
        s->max_refcount_table_index =
            MAX(s->max_refcount_table_index, refcount_table_index);

        /* The new refcount block may be where the caller intended to put its
         * data, so let it restart the search. */
@@ -580,6 +595,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
    s->refcount_table = new_table;
    s->refcount_table_size = table_size;
    s->refcount_table_offset = table_offset;
    update_max_refcount_table_index(s);

    /* Free old table. */
    qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t),
@@ -2171,6 +2187,7 @@ write_refblocks:
    s->refcount_table = on_disk_reftable;
    s->refcount_table_offset = reftable_offset;
    s->refcount_table_size = reftable_size;
    update_max_refcount_table_index(s);

    return 0;

@@ -2383,7 +2400,11 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
    }

    if ((chk & QCOW2_OL_REFCOUNT_BLOCK) && s->refcount_table) {
        for (i = 0; i < s->refcount_table_size; i++) {
        unsigned last_entry = s->max_refcount_table_index;
        assert(last_entry < s->refcount_table_size);
        assert(last_entry + 1 == s->refcount_table_size ||
               (s->refcount_table[last_entry + 1] & REFT_OFFSET_MASK) == 0);
        for (i = 0; i <= last_entry; i++) {
            if ((s->refcount_table[i] & REFT_OFFSET_MASK) &&
                overlaps_with(s->refcount_table[i] & REFT_OFFSET_MASK,
                s->cluster_size)) {
@@ -2871,6 +2892,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
    /* Now update the rest of the in-memory information */
    old_reftable = s->refcount_table;
    s->refcount_table = new_reftable;
    update_max_refcount_table_index(s);

    s->refcount_bits = 1 << refcount_order;
    s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1);
+1 −0
Original line number Diff line number Diff line
@@ -2743,6 +2743,7 @@ static int make_completely_empty(BlockDriverState *bs)

    s->refcount_table_offset = s->cluster_size;
    s->refcount_table_size   = s->cluster_size / sizeof(uint64_t);
    s->max_refcount_table_index = 0;

    g_free(s->refcount_table);
    s->refcount_table = new_reftable;
Loading