Commit 734003e6 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote branch 'kwolf/for-anthony' into staging

parents 02d0ba14 de189a1b
Loading
Loading
Loading
Loading
+103 −22
Original line number Diff line number Diff line
@@ -63,6 +63,9 @@ static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
static QLIST_HEAD(, BlockDriver) bdrv_drivers =
    QLIST_HEAD_INITIALIZER(bdrv_drivers);

/* The device to use for VM snapshots */
static BlockDriverState *bs_snapshots;

/* If non-zero, use only whitelisted block drivers */
static int use_bdrv_whitelist;

@@ -288,23 +291,30 @@ BlockDriver *bdrv_find_protocol(const char *filename)
    char protocol[128];
    int len;
    const char *p;
    int is_drive;

    /* TODO Drivers without bdrv_file_open must be specified explicitly */

    /*
     * XXX(hch): we really should not let host device detection
     * override an explicit protocol specification, but moving this
     * later breaks access to device names with colons in them.
     * Thanks to the brain-dead persistent naming schemes on udev-
     * based Linux systems those actually are quite common.
     */
    drv1 = find_hdev_driver(filename);
    if (drv1) {
        return drv1;
    }

#ifdef _WIN32
    is_drive = is_windows_drive(filename) ||
        is_windows_drive_prefix(filename);
#else
    is_drive = 0;
     if (is_windows_drive(filename) ||
         is_windows_drive_prefix(filename))
         return bdrv_find_format("file");
#endif

    p = strchr(filename, ':');
    if (!p || is_drive) {
        drv1 = find_hdev_driver(filename);
        if (!drv1) {
            drv1 = bdrv_find_format("file");
        }
        return drv1;
    if (!p) {
        return bdrv_find_format("file");
    }
    len = p - filename;
    if (len > sizeof(protocol) - 1)
@@ -393,7 +403,6 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,

    bs->file = NULL;
    bs->total_sectors = 0;
    bs->is_temporary = 0;
    bs->encrypted = 0;
    bs->valid_key = 0;
    bs->open_flags = flags;
@@ -623,6 +632,9 @@ unlink_and_fail:
void bdrv_close(BlockDriverState *bs)
{
    if (bs->drv) {
        if (bs == bs_snapshots) {
            bs_snapshots = NULL;
        }
        if (bs->backing_hd) {
            bdrv_delete(bs->backing_hd);
            bs->backing_hd = NULL;
@@ -659,6 +671,8 @@ void bdrv_close_all(void)

void bdrv_delete(BlockDriverState *bs)
{
    assert(!bs->peer);

    /* remove from list, if necessary */
    if (bs->device_name[0] != '\0') {
        QTAILQ_REMOVE(&bdrv_states, bs, list);
@@ -669,9 +683,30 @@ void bdrv_delete(BlockDriverState *bs)
        bdrv_delete(bs->file);
    }

    assert(bs != bs_snapshots);
    qemu_free(bs);
}

int bdrv_attach(BlockDriverState *bs, DeviceState *qdev)
{
    if (bs->peer) {
        return -EBUSY;
    }
    bs->peer = qdev;
    return 0;
}

void bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
{
    assert(bs->peer == qdev);
    bs->peer = NULL;
}

DeviceState *bdrv_get_attached(BlockDriverState *bs)
{
    return bs->peer;
}

/*
 * Run consistency checks on an image
 *
@@ -1264,6 +1299,14 @@ BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read)
    return is_read ? bs->on_read_error : bs->on_write_error;
}

void bdrv_set_removable(BlockDriverState *bs, int removable)
{
    bs->removable = removable;
    if (removable && bs == bs_snapshots) {
        bs_snapshots = NULL;
    }
}

int bdrv_is_removable(BlockDriverState *bs)
{
    return bs->removable;
@@ -1750,6 +1793,24 @@ int bdrv_can_snapshot(BlockDriverState *bs)
    return 1;
}

BlockDriverState *bdrv_snapshots(void)
{
    BlockDriverState *bs;

    if (bs_snapshots) {
        return bs_snapshots;
    }

    bs = NULL;
    while ((bs = bdrv_next(bs))) {
        if (bdrv_can_snapshot(bs)) {
            bs_snapshots = bs;
            return bs;
        }
    }
    return NULL;
}

int bdrv_snapshot_create(BlockDriverState *bs,
                         QEMUSnapshotInfo *sn_info)
{
@@ -1981,14 +2042,11 @@ static void multiwrite_cb(void *opaque, int ret)

    if (ret < 0 && !mcb->error) {
        mcb->error = ret;
        multiwrite_user_cb(mcb);
    }

    mcb->num_requests--;
    if (mcb->num_requests == 0) {
        if (mcb->error == 0) {
        multiwrite_user_cb(mcb);
        }
        qemu_free(mcb);
    }
}
@@ -2122,8 +2180,29 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
    // Check for mergable requests
    num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb);

    // Run the aio requests
    /*
     * Run the aio requests. As soon as one request can't be submitted
     * successfully, fail all requests that are not yet submitted (we must
     * return failure for all requests anyway)
     *
     * num_requests cannot be set to the right value immediately: If
     * bdrv_aio_writev fails for some request, num_requests would be too high
     * and therefore multiwrite_cb() would never recognize the multiwrite
     * request as completed. We also cannot use the loop variable i to set it
     * when the first request fails because the callback may already have been
     * called for previously submitted requests. Thus, num_requests must be
     * incremented for each request that is submitted.
     *
     * The problem that callbacks may be called early also means that we need
     * to take care that num_requests doesn't become 0 before all requests are
     * submitted - multiwrite_cb() would consider the multiwrite request
     * completed. A dummy request that is "completed" by a manual call to
     * multiwrite_cb() takes care of this.
     */
    mcb->num_requests = 1;

    for (i = 0; i < num_reqs; i++) {
        mcb->num_requests++;
        acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
            reqs[i].nb_sectors, multiwrite_cb, mcb);

@@ -2131,22 +2210,24 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
            // We can only fail the whole thing if no request has been
            // submitted yet. Otherwise we'll wait for the submitted AIOs to
            // complete and report the error in the callback.
            if (mcb->num_requests == 0) {
                reqs[i].error = -EIO;
            if (i == 0) {
                goto fail;
            } else {
                mcb->num_requests++;
                multiwrite_cb(mcb, -EIO);
                break;
            }
        } else {
            mcb->num_requests++;
        }
    }

    /* Complete the dummy request */
    multiwrite_cb(mcb, 0);

    return 0;

fail:
    for (i = 0; i < mcb->num_callbacks; i++) {
        reqs[i].error = -EIO;
    }
    qemu_free(mcb);
    return -1;
}
+5 −0
Original line number Diff line number Diff line
@@ -71,6 +71,9 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
              BlockDriver *drv);
void bdrv_close(BlockDriverState *bs);
int bdrv_attach(BlockDriverState *bs, DeviceState *qdev);
void bdrv_detach(BlockDriverState *bs, DeviceState *qdev);
DeviceState *bdrv_get_attached(BlockDriverState *bs);
int bdrv_check(BlockDriverState *bs);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
              uint8_t *buf, int nb_sectors);
@@ -159,6 +162,7 @@ int bdrv_get_translation_hint(BlockDriverState *bs);
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
                       BlockErrorAction on_write_error);
BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read);
void bdrv_set_removable(BlockDriverState *bs, int removable);
int bdrv_is_removable(BlockDriverState *bs);
int bdrv_is_read_only(BlockDriverState *bs);
int bdrv_is_sg(BlockDriverState *bs);
@@ -190,6 +194,7 @@ const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
void bdrv_get_backing_filename(BlockDriverState *bs,
                               char *filename, int filename_size);
int bdrv_can_snapshot(BlockDriverState *bs);
BlockDriverState *bdrv_snapshots(void);
int bdrv_snapshot_create(BlockDriverState *bs,
                         QEMUSnapshotInfo *sn_info);
int bdrv_snapshot_goto(BlockDriverState *bs,
+6 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ static QemuOptsList inject_error_opts = {

static QemuOptsList set_state_opts = {
    .name = "set-state",
    .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head),
    .head = QTAILQ_HEAD_INITIALIZER(set_state_opts.head),
    .desc = {
        {
            .name = "event",
@@ -267,6 +267,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename)

    ret = 0;
fail:
    qemu_opts_reset(&inject_error_opts);
    qemu_opts_reset(&set_state_opts);
    fclose(f);
    return ret;
}
@@ -299,6 +301,9 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
    }
    filename = c + 1;

    /* Set initial state */
    s->vars.state = 1;

    /* Open the backing file */
    ret = bdrv_file_open(&bs->file, filename, flags);
    if (ret < 0) {
+9 −6
Original line number Diff line number Diff line
@@ -805,14 +805,14 @@ static int preallocate(BlockDriverState *bs)
    while (nb_sectors) {
        num = MIN(nb_sectors, INT_MAX >> 9);
        ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, &meta);

        if (ret < 0) {
            return -1;
            return ret;
        }

        if (qcow2_alloc_cluster_link_l2(bs, &meta) < 0) {
        ret = qcow2_alloc_cluster_link_l2(bs, &meta);
        if (ret < 0) {
            qcow2_free_any_clusters(bs, meta.cluster_offset, meta.nb_clusters);
            return -1;
            return ret;
        }

        /* There are no dependent requests, but we need to remove our request
@@ -833,7 +833,10 @@ static int preallocate(BlockDriverState *bs)
    if (meta.cluster_offset != 0) {
        uint8_t buf[512];
        memset(buf, 0, 512);
        bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1);
        ret = bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1);
        if (ret < 0) {
            return ret;
        }
    }

    return 0;
@@ -1030,7 +1033,7 @@ exit:
        BlockDriver *drv = bdrv_find_format("qcow2");
        bs = bdrv_new("");
        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, drv);
        preallocate(bs);
        ret = preallocate(bs);
        bdrv_close(bs);
    }

+4 −4
Original line number Diff line number Diff line
@@ -148,6 +148,8 @@ struct BlockDriverState {
    BlockDriver *drv; /* NULL means no media */
    void *opaque;

    DeviceState *peer;

    char filename[1024];
    char backing_file[1024]; /* if non zero, the image is a diff of
                                this file image */
@@ -210,10 +212,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
int is_windows_drive(const char *filename);
#endif

struct DriveInfo;

typedef struct BlockConf {
    struct DriveInfo *dinfo;
    BlockDriverState *bs;
    uint16_t physical_block_size;
    uint16_t logical_block_size;
    uint16_t min_io_size;
@@ -234,7 +234,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
}

#define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
    DEFINE_PROP_DRIVE("drive", _state, _conf.dinfo),                    \
    DEFINE_PROP_DRIVE("drive", _state, _conf.bs),                       \
    DEFINE_PROP_UINT16("logical_block_size", _state,                    \
                       _conf.logical_block_size, 512),                  \
    DEFINE_PROP_UINT16("physical_block_size", _state,                   \
Loading