Commit 4d07c720 authored by Kevin Wolf's avatar Kevin Wolf
Browse files

Merge remote-tracking branch 'mreitz/tags/pull-block-for-kevin-2015-11-11' into queue-block



Block patches from 2015-10-26 until 2015-11-11.

# gpg: Signature made Wed Nov 11 17:00:50 2015 CET using RSA key ID E838ACAD
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"

* mreitz/tags/pull-block-for-kevin-2015-11-11:
  iotests: Check for quorum support in test 139
  qcow2: Fix qcow2_get_cluster_offset() for zero clusters
  iotests: Add tests for the x-blockdev-del command
  block: Add 'x-blockdev-del' QMP command
  block: Add blk_get_refcnt()
  mirror: block all operations on the target image during the job
  qemu-iotests: fix -valgrind option for check
  qemu-iotests: fix cleanup of background processes

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parents a9ecfa00 92e68987
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -189,6 +189,11 @@ static void drive_info_del(DriveInfo *dinfo)
    g_free(dinfo);
}

int blk_get_refcnt(BlockBackend *blk)
{
    return blk ? blk->refcnt : 0;
}

/*
 * Increment @blk's reference count.
 * @blk must not be null.
+4 −0
Original line number Diff line number Diff line
@@ -384,6 +384,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
        aio_context_release(replace_aio_context);
    }
    g_free(s->replaces);
    bdrv_op_unblock_all(s->target, s->common.blocker);
    bdrv_unref(s->target);
    block_job_completed(&s->common, data->ret);
    g_free(data);
@@ -744,6 +745,9 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
        block_job_release(bs);
        return;
    }

    bdrv_op_block_all(s->target, s->common.blocker);

    bdrv_set_enable_write_cache(s->target, true);
    if (s->target->blk) {
        blk_set_on_error(s->target->blk, on_target_error, on_target_error);
+9 −6
Original line number Diff line number Diff line
@@ -312,7 +312,7 @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
    if (!offset)
        return 0;

    assert(qcow2_get_cluster_type(first_entry) != QCOW2_CLUSTER_COMPRESSED);
    assert(qcow2_get_cluster_type(first_entry) == QCOW2_CLUSTER_NORMAL);

    for (i = 0; i < nb_clusters; i++) {
        uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
@@ -324,14 +324,16 @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
	return i;
}

static int count_contiguous_free_clusters(int nb_clusters, uint64_t *l2_table)
static int count_contiguous_clusters_by_type(int nb_clusters,
                                             uint64_t *l2_table,
                                             int wanted_type)
{
    int i;

    for (i = 0; i < nb_clusters; i++) {
        int type = qcow2_get_cluster_type(be64_to_cpu(l2_table[i]));

        if (type != QCOW2_CLUSTER_UNALLOCATED) {
        if (type != wanted_type) {
            break;
        }
    }
@@ -554,13 +556,14 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
            ret = -EIO;
            goto fail;
        }
        c = count_contiguous_clusters(nb_clusters, s->cluster_size,
                &l2_table[l2_index], QCOW_OFLAG_ZERO);
        c = count_contiguous_clusters_by_type(nb_clusters, &l2_table[l2_index],
                                              QCOW2_CLUSTER_ZERO);
        *cluster_offset = 0;
        break;
    case QCOW2_CLUSTER_UNALLOCATED:
        /* how many empty clusters ? */
        c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
        c = count_contiguous_clusters_by_type(nb_clusters, &l2_table[l2_index],
                                              QCOW2_CLUSTER_UNALLOCATED);
        *cluster_offset = 0;
        break;
    case QCOW2_CLUSTER_NORMAL:
+66 −0
Original line number Diff line number Diff line
@@ -3479,6 +3479,72 @@ fail:
    qmp_output_visitor_cleanup(ov);
}

void qmp_x_blockdev_del(bool has_id, const char *id,
                        bool has_node_name, const char *node_name, Error **errp)
{
    AioContext *aio_context;
    BlockBackend *blk;
    BlockDriverState *bs;

    if (has_id && has_node_name) {
        error_setg(errp, "Only one of id and node-name must be specified");
        return;
    } else if (!has_id && !has_node_name) {
        error_setg(errp, "No block device specified");
        return;
    }

    if (has_id) {
        blk = blk_by_name(id);
        if (!blk) {
            error_setg(errp, "Cannot find block backend %s", id);
            return;
        }
        if (blk_get_refcnt(blk) > 1) {
            error_setg(errp, "Block backend %s is in use", id);
            return;
        }
        bs = blk_bs(blk);
        aio_context = blk_get_aio_context(blk);
    } else {
        bs = bdrv_find_node(node_name);
        if (!bs) {
            error_setg(errp, "Cannot find node %s", node_name);
            return;
        }
        blk = bs->blk;
        if (blk) {
            error_setg(errp, "Node %s is in use by %s",
                       node_name, blk_name(blk));
            return;
        }
        aio_context = bdrv_get_aio_context(bs);
    }

    aio_context_acquire(aio_context);

    if (bs) {
        if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, errp)) {
            goto out;
        }

        if (bs->refcnt > 1 || !QLIST_EMPTY(&bs->parents)) {
            error_setg(errp, "Block device %s is in use",
                       bdrv_get_device_or_node_name(bs));
            goto out;
        }
    }

    if (blk) {
        blk_unref(blk);
    } else {
        bdrv_unref(bs);
    }

out:
    aio_context_release(aio_context);
}

BlockJobInfoList *qmp_query_block_jobs(Error **errp)
{
    BlockJobInfoList *head = NULL, **p_next = &head;
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp);
BlockBackend *blk_new_open(const char *name, const char *filename,
                           const char *reference, QDict *options, int flags,
                           Error **errp);
int blk_get_refcnt(BlockBackend *blk);
void blk_ref(BlockBackend *blk);
void blk_unref(BlockBackend *blk);
const char *blk_name(BlockBackend *blk);
Loading