Commit 863d2ed5 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-02-06' into staging



Block patches:
- Drop BDRV_SECTOR_SIZE from qcow2
- Allow Python iotests to be added to the auto group
  (and add some)
- Fix for the backup job
- Fix memleak in bdrv_refresh_filename()
- Use GStrings in two places for greater efficiency (than manually
  handling string allocation)

# gpg: Signature made Thu 06 Feb 2020 12:50:14 GMT
# gpg:                using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40
# gpg:                issuer "mreitz@redhat.com"
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full]
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2020-02-06:
  iotests: add test for backup-top failure on permission activation
  block/backup-top: fix failure path
  qcow2: Use BDRV_SECTOR_SIZE instead of the hardcoded value
  qcow2: Don't require aligned offsets in qcow2_co_copy_range_from()
  qcow2: Use bs->bl.request_alignment when updating an L1 entry
  qcow2: Tighten cluster_offset alignment assertions
  qcow2: Don't round the L1 table allocation up to the sector size
  iotests: Enable more tests in the 'auto' group to improve test coverage
  iotests: Skip Python-based tests if QEMU does not support virtio-blk
  iotests: Check for the availability of the required devices in 267 and 127
  iotests: Test 183 does not work on macOS and OpenBSD
  iotests: Test 041 only works on certain systems
  iotests: remove 'linux' from default supported platforms
  qcow2: Use a GString in report_unsupported_feature()
  block: fix memleaks in bdrv_refresh_filename
  block: Use a GString in bdrv_perm_names()
  qcow2: Assert that host cluster offsets fit in L2 table entries

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2021b7c9 a541fcc2
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -1998,18 +1998,19 @@ char *bdrv_perm_names(uint64_t perm)
        { 0, NULL }
    };

    char *result = g_strdup("");
    GString *result = g_string_sized_new(30);
    struct perm_name *p;

    for (p = permissions; p->name; p++) {
        if (perm & p->perm) {
            char *old = result;
            result = g_strdup_printf("%s%s%s", old, *old ? ", " : "", p->name);
            g_free(old);
            if (result->len > 0) {
                g_string_append(result, ", ");
            }
            g_string_append(result, p->name);
        }
    }

    return result;
    return g_string_free(result, FALSE);
}

/*
@@ -6441,6 +6442,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
                child->bs->exact_filename);
        pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);

        qobject_unref(bs->full_open_options);
        bs->full_open_options = qobject_ref(child->bs->full_open_options);

        return;
+12 −9
Original line number Diff line number Diff line
@@ -190,6 +190,7 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
    BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter,
                                                 filter_node_name,
                                                 BDRV_O_RDWR, errp);
    bool appended = false;

    if (!top) {
        return NULL;
@@ -212,8 +213,9 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
    bdrv_append(top, source, &local_err);
    if (local_err) {
        error_prepend(&local_err, "Cannot append backup-top filter: ");
        goto append_failed;
        goto fail;
    }
    appended = true;

    /*
     * bdrv_append() finished successfully, now we can require permissions
@@ -224,14 +226,14 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
    if (local_err) {
        error_prepend(&local_err,
                      "Cannot set permissions for backup-top filter: ");
        goto failed_after_append;
        goto fail;
    }

    state->bcs = block_copy_state_new(top->backing, state->target,
                                      cluster_size, write_flags, &local_err);
    if (local_err) {
        error_prepend(&local_err, "Cannot create block-copy-state: ");
        goto failed_after_append;
        goto fail;
    }
    *bcs = state->bcs;

@@ -239,14 +241,15 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,

    return top;

failed_after_append:
fail:
    if (appended) {
        state->active = false;
        bdrv_backup_top_drop(top);
    } else {
        bdrv_unref(top);
    }

append_failed:
    bdrv_drained_end(source);
    bdrv_unref_child(top, state->target);
    bdrv_unref(top);
    error_propagate(errp, local_err);

    return NULL;
+29 −15
Original line number Diff line number Diff line
@@ -124,12 +124,11 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
#endif

    new_l1_size2 = sizeof(uint64_t) * new_l1_size;
    new_l1_table = qemu_try_blockalign(bs->file->bs,
                                       ROUND_UP(new_l1_size2, 512));
    new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_size2);
    if (new_l1_table == NULL) {
        return -ENOMEM;
    }
    memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512));
    memset(new_l1_table, 0, new_l1_size2);

    if (s->l1_size) {
        memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
@@ -217,26 +216,31 @@ static int l2_load(BlockDriverState *bs, uint64_t offset,
}

/*
 * Writes one sector of the L1 table to the disk (can't update single entries
 * and we really don't want bdrv_pread to perform a read-modify-write)
 * Writes an L1 entry to disk (note that depending on the alignment
 * requirements this function may write more that just one entry in
 * order to prevent bdrv_pwrite from performing a read-modify-write)
 */
#define L1_ENTRIES_PER_SECTOR (512 / 8)
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
{
    BDRVQcow2State *s = bs->opaque;
    uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 };
    int l1_start_index;
    int i, ret;
    int bufsize = MAX(sizeof(uint64_t),
                      MIN(bs->file->bs->bl.request_alignment, s->cluster_size));
    int nentries = bufsize / sizeof(uint64_t);
    g_autofree uint64_t *buf = g_try_new0(uint64_t, nentries);

    l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
    for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size;
         i++)
    {
    if (buf == NULL) {
        return -ENOMEM;
    }

    l1_start_index = QEMU_ALIGN_DOWN(l1_index, nentries);
    for (i = 0; i < MIN(nentries, s->l1_size - l1_start_index); i++) {
        buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
    }

    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
            s->l1_table_offset + 8 * l1_start_index, sizeof(buf), false);
            s->l1_table_offset + 8 * l1_start_index, bufsize, false);
    if (ret < 0) {
        return ret;
    }
@@ -244,7 +248,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
    BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
    ret = bdrv_pwrite_sync(bs->file,
                           s->l1_table_offset + 8 * l1_start_index,
                           buf, sizeof(buf));
                           buf, bufsize);
    if (ret < 0) {
        return ret;
    }
@@ -777,6 +781,10 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
        (cluster_offset + compressed_size - 1) / QCOW2_COMPRESSED_SECTOR_SIZE -
        (cluster_offset / QCOW2_COMPRESSED_SECTOR_SIZE);

    /* The offset and size must fit in their fields of the L2 table entry */
    assert((cluster_offset & s->cluster_offset_mask) == cluster_offset);
    assert((nb_csectors & s->csize_mask) == nb_csectors);

    cluster_offset |= QCOW_OFLAG_COMPRESSED |
                      ((uint64_t)nb_csectors << s->csize_shift);

@@ -972,6 +980,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)

    assert(l2_index + m->nb_clusters <= s->l2_slice_size);
    for (i = 0; i < m->nb_clusters; i++) {
        uint64_t offset = cluster_offset + (i << s->cluster_bits);
        /* if two concurrent writes happen to the same unallocated cluster
         * each write allocates separate cluster and writes data concurrently.
         * The first one to complete updates l2 table with pointer to its
@@ -982,8 +991,10 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
            old_cluster[j++] = l2_slice[l2_index + i];
        }

        l2_slice[l2_index + i] = cpu_to_be64((cluster_offset +
                    (i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
        /* The offset must fit in the offset field of the L2 table entry */
        assert((offset & L2E_OFFSET_MASK) == offset);

        l2_slice[l2_index + i] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
     }


@@ -1913,6 +1924,9 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
                        goto fail;
                    }

                    /* The offset must fit in the offset field */
                    assert((offset & L2E_OFFSET_MASK) == offset);

                    if (l2_refcount > 1) {
                        /* For shared L2 tables, set the refcount accordingly
                         * (it is already 1 and needs to be l2_refcount) */
+1 −1
Original line number Diff line number Diff line
@@ -1262,7 +1262,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     * l1_table_offset when it is the current s->l1_table_offset! Be careful
     * when changing this! */
    if (l1_table_offset != s->l1_table_offset) {
        l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512));
        l1_table = g_try_malloc0(l1_size2);
        if (l1_size2 && l1_table == NULL) {
            ret = -ENOMEM;
            goto fail;
+1 −2
Original line number Diff line number Diff line
@@ -1024,8 +1024,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
        return ret;
    }
    new_l1_bytes = sn->l1_size * sizeof(uint64_t);
    new_l1_table = qemu_try_blockalign(bs->file->bs,
                                       ROUND_UP(new_l1_bytes, 512));
    new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes);
    if (new_l1_table == NULL) {
        return -ENOMEM;
    }
Loading