Commit f563a5d7 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge remote-tracking branch 'origin/master' into threadpool

parents a2736526 aee0bf7d
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -8,6 +8,17 @@ ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
all:
include config-host.mak

# Check that we're not trying to do an out-of-tree build from
# a tree that's been used for an in-tree build.
ifneq ($(realpath $(SRC_PATH)),$(realpath .))
ifneq ($(wildcard $(SRC_PATH)/config-host.mak),)
$(error This is an out of tree build but your source tree ($(SRC_PATH)) \
seems to have been used for an in-tree build. You can fix this by running \
"make distclean && rm -rf *-linux-user *-softmmu" in your source tree)
endif
endif

include $(SRC_PATH)/rules.mak
config-host.mak: $(SRC_PATH)/configure
	@echo $@ is out-of-date, running configure
+18 −0
Original line number Diff line number Diff line
@@ -118,6 +118,24 @@ Example:
              "action": "stop" },
    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }

BLOCK_JOB_READY
---------------

Emitted when a block job is ready to complete.

Data:

- "device": device name (json-string)

Example:

{ "event": "BLOCK_JOB_READY",
    "data": { "device": "ide0-hd1" },
    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }

Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
event.

DEVICE_TRAY_MOVED
-----------------

+21 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ class QEMUMonitorProtocol:
        @raise QMPCapabilitiesError if fails to negotiate capabilities
        """
        self.__sock, _ = self.__sock.accept()
        self.__sockfile = self.__sock.makefile()
        return self.__negotiate_capabilities()

    def cmd_obj(self, qmp_cmd):
@@ -135,6 +136,26 @@ class QEMUMonitorProtocol:
            raise Exception(ret['error']['desc'])
        return ret['return']

    def pull_event(self, wait=False):
        """
        Get and delete the first available QMP event.

        @param wait: block until an event is available (bool)
        """
        self.__sock.setblocking(0)
        try:
            self.__json_read()
        except socket.error, err:
            if err[0] == errno.EAGAIN:
                # No data available
                pass
        self.__sock.setblocking(1)
        if not self.__events and wait:
            self.__json_read(only_event=True)
        event = self.__events[0]
        del self.__events[0]
        return event

    def get_events(self, wait=False):
        """
        Get a list of available QMP events.
+210 −97
Original line number Diff line number Diff line
@@ -387,7 +387,8 @@ int bdrv_create(BlockDriver *drv, const char* filename,
    };

    if (!drv->bdrv_create) {
        return -ENOTSUP;
        ret = -ENOTSUP;
        goto out;
    }

    if (qemu_in_coroutine()) {
@@ -402,8 +403,9 @@ int bdrv_create(BlockDriver *drv, const char* filename,
    }

    ret = cco.ret;
    g_free(cco.filename);

out:
    g_free(cco.filename);
    return ret;
}

@@ -742,6 +744,42 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
    return 0;
}

int bdrv_open_backing_file(BlockDriverState *bs)
{
    char backing_filename[PATH_MAX];
    int back_flags, ret;
    BlockDriver *back_drv = NULL;

    if (bs->backing_hd != NULL) {
        return 0;
    }

    bs->open_flags &= ~BDRV_O_NO_BACKING;
    if (bs->backing_file[0] == '\0') {
        return 0;
    }

    bs->backing_hd = bdrv_new("");
    bdrv_get_full_backing_filename(bs, backing_filename,
                                   sizeof(backing_filename));

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

    /* backing files always opened read-only */
    back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT);

    ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
    if (ret < 0) {
        bdrv_delete(bs->backing_hd);
        bs->backing_hd = NULL;
        bs->open_flags |= BDRV_O_NO_BACKING;
        return ret;
    }
    return 0;
}

/*
 * Opens a disk image (raw, qcow2, vmdk, ...)
 */
@@ -829,24 +867,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
    }

    /* If there is a backing file, use it */
    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
        char backing_filename[PATH_MAX];
        int back_flags;
        BlockDriver *back_drv = NULL;

        bs->backing_hd = bdrv_new("");
        bdrv_get_full_backing_filename(bs, backing_filename,
                                       sizeof(backing_filename));

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

        /* backing files always opened read-only */
        back_flags =
            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);

        ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
    if ((flags & BDRV_O_NO_BACKING) == 0) {
        ret = bdrv_open_backing_file(bs);
        if (ret < 0) {
            bdrv_close(bs);
            return ret;
@@ -2378,7 +2400,7 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
    }

    if (bs->dirty_bitmap) {
        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
        bdrv_set_dirty(bs, sector_num, nb_sectors);
    }

    if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
@@ -2806,76 +2828,82 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
    return 0;
}

BlockInfoList *qmp_query_block(Error **errp)
BlockInfo *bdrv_query_info(BlockDriverState *bs)
{
    BlockInfoList *head = NULL, *cur_item = NULL;
    BlockDriverState *bs;

    QTAILQ_FOREACH(bs, &bdrv_states, list) {
        BlockInfoList *info = g_malloc0(sizeof(*info));

        info->value = g_malloc0(sizeof(*info->value));
        info->value->device = g_strdup(bs->device_name);
        info->value->type = g_strdup("unknown");
        info->value->locked = bdrv_dev_is_medium_locked(bs);
        info->value->removable = bdrv_dev_has_removable_media(bs);
    BlockInfo *info = g_malloc0(sizeof(*info));
    info->device = g_strdup(bs->device_name);
    info->type = g_strdup("unknown");
    info->locked = bdrv_dev_is_medium_locked(bs);
    info->removable = bdrv_dev_has_removable_media(bs);

    if (bdrv_dev_has_removable_media(bs)) {
            info->value->has_tray_open = true;
            info->value->tray_open = bdrv_dev_is_tray_open(bs);
        info->has_tray_open = true;
        info->tray_open = bdrv_dev_is_tray_open(bs);
    }

    if (bdrv_iostatus_is_enabled(bs)) {
            info->value->has_io_status = true;
            info->value->io_status = bs->iostatus;
        info->has_io_status = true;
        info->io_status = bs->iostatus;
    }

    if (bs->dirty_bitmap) {
        info->has_dirty = true;
        info->dirty = g_malloc0(sizeof(*info->dirty));
        info->dirty->count = bdrv_get_dirty_count(bs) *
            BDRV_SECTORS_PER_DIRTY_CHUNK * BDRV_SECTOR_SIZE;
    }

    if (bs->drv) {
            info->value->has_inserted = true;
            info->value->inserted = g_malloc0(sizeof(*info->value->inserted));
            info->value->inserted->file = g_strdup(bs->filename);
            info->value->inserted->ro = bs->read_only;
            info->value->inserted->drv = g_strdup(bs->drv->format_name);
            info->value->inserted->encrypted = bs->encrypted;
            info->value->inserted->encryption_key_missing = bdrv_key_required(bs);
        info->has_inserted = true;
        info->inserted = g_malloc0(sizeof(*info->inserted));
        info->inserted->file = g_strdup(bs->filename);
        info->inserted->ro = bs->read_only;
        info->inserted->drv = g_strdup(bs->drv->format_name);
        info->inserted->encrypted = bs->encrypted;
        info->inserted->encryption_key_missing = bdrv_key_required(bs);

        if (bs->backing_file[0]) {
                info->value->inserted->has_backing_file = true;
                info->value->inserted->backing_file = g_strdup(bs->backing_file);
            info->inserted->has_backing_file = true;
            info->inserted->backing_file = g_strdup(bs->backing_file);
        }

            info->value->inserted->backing_file_depth =
                bdrv_get_backing_file_depth(bs);
        info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs);

        if (bs->io_limits_enabled) {
                info->value->inserted->bps =
            info->inserted->bps =
                           bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
                info->value->inserted->bps_rd =
            info->inserted->bps_rd =
                           bs->io_limits.bps[BLOCK_IO_LIMIT_READ];
                info->value->inserted->bps_wr =
            info->inserted->bps_wr =
                           bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE];
                info->value->inserted->iops =
            info->inserted->iops =
                           bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
                info->value->inserted->iops_rd =
            info->inserted->iops_rd =
                           bs->io_limits.iops[BLOCK_IO_LIMIT_READ];
                info->value->inserted->iops_wr =
            info->inserted->iops_wr =
                           bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
        }
    }

        /* XXX: waiting for the qapi to support GSList */
        if (!cur_item) {
            head = cur_item = info;
        } else {
            cur_item->next = info;
            cur_item = info;
    return info;
}

BlockInfoList *qmp_query_block(Error **errp)
{
    BlockInfoList *head = NULL, **p_next = &head;
    BlockDriverState *bs;

    QTAILQ_FOREACH(bs, &bdrv_states, list) {
        BlockInfoList *info = g_malloc0(sizeof(*info));
        info->value = bdrv_query_info(bs);

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

    return head;
}

/* Consider exposing this as a full fledged QMP command */
static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp)
BlockStats *bdrv_query_stats(const BlockDriverState *bs)
{
    BlockStats *s;

@@ -2899,7 +2927,7 @@ static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp)

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

    return s;
@@ -2907,20 +2935,15 @@ static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp)

BlockStatsList *qmp_query_blockstats(Error **errp)
{
    BlockStatsList *head = NULL, *cur_item = NULL;
    BlockStatsList *head = NULL, **p_next = &head;
    BlockDriverState *bs;

    QTAILQ_FOREACH(bs, &bdrv_states, list) {
        BlockStatsList *info = g_malloc0(sizeof(*info));
        info->value = qmp_query_blockstat(bs, NULL);
        info->value = bdrv_query_stats(bs);

        /* XXX: waiting for the qapi to support GSList */
        if (!cur_item) {
            head = cur_item = info;
        } else {
            cur_item->next = info;
            cur_item = info;
        }
        *p_next = info;
        p_next = &info->next;
    }

    return head;
@@ -2953,9 +2976,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
    if (bdrv_check_request(bs, sector_num, nb_sectors))
        return -EIO;

    if (bs->dirty_bitmap) {
        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
    }
    assert(!bs->dirty_bitmap);

    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
@@ -3132,22 +3153,70 @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
    return -ENOTSUP;
}

/* backing_file can either be relative, or absolute, or a protocol.  If it is
 * relative, it must be relative to the chain.  So, passing in bs->filename
 * from a BDS as backing_file should not be done, as that may be relative to
 * the CWD rather than the chain. */
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
        const char *backing_file)
{
    if (!bs->drv) {
    char *filename_full = NULL;
    char *backing_file_full = NULL;
    char *filename_tmp = NULL;
    int is_protocol = 0;
    BlockDriverState *curr_bs = NULL;
    BlockDriverState *retval = NULL;

    if (!bs || !bs->drv || !backing_file) {
        return NULL;
    }

    if (bs->backing_hd) {
        if (strcmp(bs->backing_file, backing_file) == 0) {
            return bs->backing_hd;
    filename_full     = g_malloc(PATH_MAX);
    backing_file_full = g_malloc(PATH_MAX);
    filename_tmp      = g_malloc(PATH_MAX);

    is_protocol = path_has_protocol(backing_file);

    for (curr_bs = bs; curr_bs->backing_hd; curr_bs = curr_bs->backing_hd) {

        /* If either of the filename paths is actually a protocol, then
         * compare unmodified paths; otherwise make paths relative */
        if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
            if (strcmp(backing_file, curr_bs->backing_file) == 0) {
                retval = curr_bs->backing_hd;
                break;
            }
        } else {
            return bdrv_find_backing_image(bs->backing_hd, backing_file);
            /* If not an absolute filename path, make it relative to the current
             * image's filename path */
            path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
                         backing_file);

            /* We are going to compare absolute pathnames */
            if (!realpath(filename_tmp, filename_full)) {
                continue;
            }

            /* We need to make sure the backing filename we are comparing against
             * is relative to the current image filename (or absolute) */
            path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
                         curr_bs->backing_file);

            if (!realpath(filename_tmp, backing_file_full)) {
                continue;
            }

    return NULL;
            if (strcmp(backing_file_full, filename_full) == 0) {
                retval = curr_bs->backing_hd;
                break;
            }
        }
    }

    g_free(filename_full);
    g_free(backing_file_full);
    g_free(filename_tmp);
    return retval;
}

int bdrv_get_backing_file_depth(BlockDriverState *bs)
@@ -4214,13 +4283,54 @@ int bdrv_get_dirty(BlockDriverState *bs, int64_t sector)

    if (bs->dirty_bitmap &&
        (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) {
        return !!(bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] &
            (1UL << (chunk % (sizeof(unsigned long) * 8))));
        return !!(bs->dirty_bitmap[chunk / BITS_PER_LONG] &
            (1UL << (chunk % BITS_PER_LONG)));
    } else {
        return 0;
    }
}

int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector)
{
    int64_t chunk;
    int bit, elem;

    /* Avoid an infinite loop.  */
    assert(bs->dirty_count > 0);

    sector = (sector | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1;
    chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;

    QEMU_BUILD_BUG_ON(sizeof(bs->dirty_bitmap[0]) * 8 != BITS_PER_LONG);
    elem = chunk / BITS_PER_LONG;
    bit = chunk % BITS_PER_LONG;
    for (;;) {
        if (sector >= bs->total_sectors) {
            sector = 0;
            bit = elem = 0;
        }
        if (bit == 0 && bs->dirty_bitmap[elem] == 0) {
            sector += BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG;
            elem++;
        } else {
            if (bs->dirty_bitmap[elem] & (1UL << bit)) {
                return sector;
            }
            sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
            if (++bit == BITS_PER_LONG) {
                bit = 0;
                elem++;
            }
        }
    }
}

void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
                    int nr_sectors)
{
    set_dirty_bitmap(bs, cur_sector, nr_sectors, 1);
}

void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
                      int nr_sectors)
{
@@ -4268,6 +4378,9 @@ void bdrv_iostatus_reset(BlockDriverState *bs)
{
    if (bdrv_iostatus_is_enabled(bs)) {
        bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
        if (bs->job) {
            block_job_iostatus_reset(bs->job);
        }
    }
}

+6 −2
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
void bdrv_delete(BlockDriverState *bs);
int bdrv_parse_cache_flags(const char *mode, int *flags);
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
int bdrv_open_backing_file(BlockDriverState *bs);
int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
              BlockDriver *drv);
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
@@ -314,6 +315,8 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
                               char *filename, int filename_size);
void bdrv_get_full_backing_filename(BlockDriverState *bs,
                                    char *dest, size_t sz);
BlockInfo *bdrv_query_info(BlockDriverState *s);
BlockStats *bdrv_query_stats(const BlockDriverState *bs);
int bdrv_can_snapshot(BlockDriverState *bs);
int bdrv_is_snapshot(BlockDriverState *bs);
BlockDriverState *bdrv_snapshots(void);
@@ -351,8 +354,9 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);

void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable);
int bdrv_get_dirty(BlockDriverState *bs, int64_t sector);
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
                      int nr_sectors);
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector);
int64_t bdrv_get_dirty_count(BlockDriverState *bs);

void bdrv_enable_copy_on_read(BlockDriverState *bs);
Loading