Commit 96b3d73f authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'qmp/queue/qmp' into staging

Conflicts:
	ui/spice-core.c
parents 549f808b f795e743
Loading
Loading
Loading
Loading
+14 −58
Original line number Diff line number Diff line
@@ -25,12 +25,11 @@
 */

#include "monitor.h"
#include "qjson.h"
#include "qint.h"
#include "cpu-common.h"
#include "kvm.h"
#include "balloon.h"
#include "trace.h"
#include "qmp-commands.h"

static QEMUBalloonEvent *balloon_event_fn;
static QEMUBalloonStatus *balloon_stat_fn;
@@ -72,76 +71,33 @@ static int qemu_balloon(ram_addr_t target)
    return 1;
}

static int qemu_balloon_status(MonitorCompletion cb, void *opaque)
static int qemu_balloon_status(BalloonInfo *info)
{
    if (!balloon_stat_fn) {
        return 0;
    }
    balloon_stat_fn(balloon_opaque, cb, opaque);
    balloon_stat_fn(balloon_opaque, info);
    return 1;
}

static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
BalloonInfo *qmp_query_balloon(Error **errp)
{
    Monitor *mon = opaque;

    if (strcmp(key, "actual")) {
        monitor_printf(mon, ",%s=%" PRId64, key,
                       qint_get_int(qobject_to_qint(obj)));
    }
}

void monitor_print_balloon(Monitor *mon, const QObject *data)
{
    QDict *qdict;

    qdict = qobject_to_qdict(data);
    if (!qdict_haskey(qdict, "actual")) {
        return;
    }
    monitor_printf(mon, "balloon: actual=%" PRId64,
                   qdict_get_int(qdict, "actual") >> 20);
    qdict_iter(qdict, print_balloon_stat, mon);
    monitor_printf(mon, "\n");
}

/**
 * do_info_balloon(): Balloon information
 *
 * Make an asynchronous request for balloon info.  When the request completes
 * a QDict will be returned according to the following specification:
 *
 * - "actual": current balloon value in bytes
 * The following fields may or may not be present:
 * - "mem_swapped_in": Amount of memory swapped in (bytes)
 * - "mem_swapped_out": Amount of memory swapped out (bytes)
 * - "major_page_faults": Number of major faults
 * - "minor_page_faults": Number of minor faults
 * - "free_mem": Total amount of free and unused memory (bytes)
 * - "total_mem": Total amount of available memory (bytes)
 *
 * Example:
 *
 * { "actual": 1073741824, "mem_swapped_in": 0, "mem_swapped_out": 0,
 *   "major_page_faults": 142, "minor_page_faults": 239245,
 *   "free_mem": 1014185984, "total_mem": 1044668416 }
 */
int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
{
    int ret;
    BalloonInfo *info;

    if (kvm_enabled() && !kvm_has_sync_mmu()) {
        qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
        return -1;
        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
        return NULL;
    }

    ret = qemu_balloon_status(cb, opaque);
    if (!ret) {
        qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
        return -1;
    info = g_malloc0(sizeof(*info));

    if (qemu_balloon_status(info) == 0) {
        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
        qapi_free_BalloonInfo(info);
        return NULL;
    }

    return 0;
    return info;
}

/**
+2 −4
Original line number Diff line number Diff line
@@ -15,17 +15,15 @@
#define _QEMU_BALLOON_H

#include "monitor.h"
#include "qapi-types.h"

typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target);
typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb,
                                 void *cb_data);
typedef void (QEMUBalloonStatus)(void *opaque, BalloonInfo *info);

int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
			     QEMUBalloonStatus *stat_func, void *opaque);
void qemu_remove_balloon_handler(void *opaque);

void monitor_print_balloon(Monitor *mon, const QObject *data);
int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque);
int do_balloon(Monitor *mon, const QDict *params,
               MonitorCompletion cb, void *opaque);

+74 −160
Original line number Diff line number Diff line
@@ -27,8 +27,9 @@
#include "monitor.h"
#include "block_int.h"
#include "module.h"
#include "qemu-objects.h"
#include "qjson.h"
#include "qemu-coroutine.h"
#include "qmp-commands.h"

#ifdef CONFIG_BSD
#include <sys/types.h>
@@ -1824,195 +1825,105 @@ void bdrv_mon_event(const BlockDriverState *bdrv,
    qobject_decref(data);
}

static void bdrv_print_dict(QObject *obj, void *opaque)
BlockInfoList *qmp_query_block(Error **errp)
{
    QDict *bs_dict;
    Monitor *mon = opaque;

    bs_dict = qobject_to_qdict(obj);

    monitor_printf(mon, "%s: removable=%d",
                        qdict_get_str(bs_dict, "device"),
                        qdict_get_bool(bs_dict, "removable"));

    if (qdict_get_bool(bs_dict, "removable")) {
        monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked"));
        monitor_printf(mon, " tray-open=%d",
                       qdict_get_bool(bs_dict, "tray-open"));
    }

    if (qdict_haskey(bs_dict, "io-status")) {
        monitor_printf(mon, " io-status=%s", qdict_get_str(bs_dict, "io-status"));
    }

    if (qdict_haskey(bs_dict, "inserted")) {
        QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted"));

        monitor_printf(mon, " file=");
        monitor_print_filename(mon, qdict_get_str(qdict, "file"));
        if (qdict_haskey(qdict, "backing_file")) {
            monitor_printf(mon, " backing_file=");
            monitor_print_filename(mon, qdict_get_str(qdict, "backing_file"));
        }
        monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
                            qdict_get_bool(qdict, "ro"),
                            qdict_get_str(qdict, "drv"),
                            qdict_get_bool(qdict, "encrypted"));
    } else {
        monitor_printf(mon, " [not inserted]");
    }

    monitor_printf(mon, "\n");
}

void bdrv_info_print(Monitor *mon, const QObject *data)
{
    qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
}

static const char *const io_status_name[BDRV_IOS_MAX] = {
    [BDRV_IOS_OK] = "ok",
    [BDRV_IOS_FAILED] = "failed",
    [BDRV_IOS_ENOSPC] = "nospace",
};

void bdrv_info(Monitor *mon, QObject **ret_data)
{
    QList *bs_list;
    BlockInfoList *head = NULL, *cur_item = NULL;
    BlockDriverState *bs;

    bs_list = qlist_new();

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

        bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', "
                                    "'removable': %i, 'locked': %i }",
                                    bs->device_name,
                                    bdrv_dev_has_removable_media(bs),
                                    bdrv_dev_is_medium_locked(bs));
        bs_dict = qobject_to_qdict(bs_obj);
        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);

        if (bdrv_dev_has_removable_media(bs)) {
            qdict_put(bs_dict, "tray-open",
                      qbool_from_int(bdrv_dev_is_tray_open(bs)));
            info->value->has_tray_open = true;
            info->value->tray_open = bdrv_dev_is_tray_open(bs);
        }

        if (bdrv_iostatus_is_enabled(bs)) {
            qdict_put(bs_dict, "io-status",
                      qstring_from_str(io_status_name[bs->iostatus]));
            info->value->has_io_status = true;
            info->value->io_status = bs->iostatus;
        }

        if (bs->drv) {
            QObject *obj;

            obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, "
                                     "'encrypted': %i }",
                                     bs->filename, bs->read_only,
                                     bs->drv->format_name,
                                     bdrv_is_encrypted(bs));
            if (bs->backing_file[0] != '\0') {
                QDict *qdict = qobject_to_qdict(obj);
                qdict_put(qdict, "backing_file",
                          qstring_from_str(bs->backing_file));
            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;
            if (bs->backing_file[0]) {
                info->value->inserted->has_backing_file = true;
                info->value->inserted->backing_file = g_strdup(bs->backing_file);
            }

            qdict_put_obj(bs_dict, "inserted", obj);
        }
        qlist_append_obj(bs_list, bs_obj);
        }

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

static void bdrv_stats_iter(QObject *data, void *opaque)
{
    QDict *qdict;
    Monitor *mon = opaque;

    qdict = qobject_to_qdict(data);
    monitor_printf(mon, "%s:", qdict_get_str(qdict, "device"));

    qdict = qobject_to_qdict(qdict_get(qdict, "stats"));
    monitor_printf(mon, " rd_bytes=%" PRId64
                        " wr_bytes=%" PRId64
                        " rd_operations=%" PRId64
                        " wr_operations=%" PRId64
                        " flush_operations=%" PRId64
                        " wr_total_time_ns=%" PRId64
                        " rd_total_time_ns=%" PRId64
                        " flush_total_time_ns=%" PRId64
                        "\n",
                        qdict_get_int(qdict, "rd_bytes"),
                        qdict_get_int(qdict, "wr_bytes"),
                        qdict_get_int(qdict, "rd_operations"),
                        qdict_get_int(qdict, "wr_operations"),
                        qdict_get_int(qdict, "flush_operations"),
                        qdict_get_int(qdict, "wr_total_time_ns"),
                        qdict_get_int(qdict, "rd_total_time_ns"),
                        qdict_get_int(qdict, "flush_total_time_ns"));
    }

void bdrv_stats_print(Monitor *mon, const QObject *data)
{
    qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
    return head;
}

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

    res = qobject_from_jsonf("{ 'stats': {"
                             "'rd_bytes': %" PRId64 ","
                             "'wr_bytes': %" PRId64 ","
                             "'rd_operations': %" PRId64 ","
                             "'wr_operations': %" PRId64 ","
                             "'wr_highest_offset': %" PRId64 ","
                             "'flush_operations': %" PRId64 ","
                             "'wr_total_time_ns': %" PRId64 ","
                             "'rd_total_time_ns': %" PRId64 ","
                             "'flush_total_time_ns': %" PRId64
                             "} }",
                             bs->nr_bytes[BDRV_ACCT_READ],
                             bs->nr_bytes[BDRV_ACCT_WRITE],
                             bs->nr_ops[BDRV_ACCT_READ],
                             bs->nr_ops[BDRV_ACCT_WRITE],
                             bs->wr_highest_sector *
                             (uint64_t)BDRV_SECTOR_SIZE,
                             bs->nr_ops[BDRV_ACCT_FLUSH],
                             bs->total_time_ns[BDRV_ACCT_WRITE],
                             bs->total_time_ns[BDRV_ACCT_READ],
                             bs->total_time_ns[BDRV_ACCT_FLUSH]);
    dict  = qobject_to_qdict(res);
    s = g_malloc0(sizeof(*s));

    if (*bs->device_name) {
        qdict_put(dict, "device", qstring_from_str(bs->device_name));
    if (bs->device_name[0]) {
        s->has_device = true;
        s->device = g_strdup(bs->device_name);
    }

    s->stats = g_malloc0(sizeof(*s->stats));
    s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ];
    s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE];
    s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ];
    s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE];
    s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
    s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH];
    s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE];
    s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ];
    s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH];

    if (bs->file) {
        QObject *parent = bdrv_info_stats_bs(bs->file);
        qdict_put_obj(dict, "parent", parent);
        s->has_parent = true;
        s->parent = qmp_query_blockstat(bs->file, NULL);
    }

    return res;
    return s;
}

void bdrv_info_stats(Monitor *mon, QObject **ret_data)
BlockStatsList *qmp_query_blockstats(Error **errp)
{
    QObject *obj;
    QList *devices;
    BlockStatsList *head = NULL, *cur_item = NULL;
    BlockDriverState *bs;

    devices = qlist_new();

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

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

    *ret_data = QOBJECT(devices);
    return head;
}

const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
@@ -3139,14 +3050,15 @@ int bdrv_in_use(BlockDriverState *bs)

void bdrv_iostatus_enable(BlockDriverState *bs)
{
    bs->iostatus = BDRV_IOS_OK;
    bs->iostatus_enabled = true;
    bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
}

/* The I/O status is only enabled if the drive explicitly
 * enables it _and_ the VM is configured to stop on errors */
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
{
    return (bs->iostatus != BDRV_IOS_INVAL &&
    return (bs->iostatus_enabled &&
           (bs->on_write_error == BLOCK_ERR_STOP_ENOSPC ||
            bs->on_write_error == BLOCK_ERR_STOP_ANY    ||
            bs->on_read_error == BLOCK_ERR_STOP_ANY));
@@ -3154,13 +3066,13 @@ bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)

void bdrv_iostatus_disable(BlockDriverState *bs)
{
    bs->iostatus = BDRV_IOS_INVAL;
    bs->iostatus_enabled = false;
}

void bdrv_iostatus_reset(BlockDriverState *bs)
{
    if (bdrv_iostatus_is_enabled(bs)) {
        bs->iostatus = BDRV_IOS_OK;
        bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
    }
}

@@ -3169,9 +3081,11 @@ void bdrv_iostatus_reset(BlockDriverState *bs)
   possible to implement this without device models being involved */
void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
{
    if (bdrv_iostatus_is_enabled(bs) && bs->iostatus == BDRV_IOS_OK) {
    if (bdrv_iostatus_is_enabled(bs) &&
        bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
        assert(error >= 0);
        bs->iostatus = error == ENOSPC ? BDRV_IOS_ENOSPC : BDRV_IOS_FAILED;
        bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
                                         BLOCK_DEVICE_IO_STATUS_FAILED;
    }
}

+0 −5
Original line number Diff line number Diff line
@@ -77,11 +77,6 @@ typedef enum {
    BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
} BlockMonEventAction;

typedef enum {
    BDRV_IOS_INVAL, BDRV_IOS_OK, BDRV_IOS_FAILED, BDRV_IOS_ENOSPC,
    BDRV_IOS_MAX
} BlockIOStatus;

void bdrv_iostatus_enable(BlockDriverState *bs);
void bdrv_iostatus_reset(BlockDriverState *bs);
void bdrv_iostatus_disable(BlockDriverState *bs);
+3 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "qemu-queue.h"
#include "qemu-coroutine.h"
#include "qemu-timer.h"
#include "qapi-types.h"

#define BLOCK_FLAG_ENCRYPT	1
#define BLOCK_FLAG_COMPAT6	4
@@ -202,7 +203,8 @@ struct BlockDriverState {
       drivers. They are not used by the block driver */
    int cyls, heads, secs, translation;
    BlockErrorAction on_read_error, on_write_error;
    BlockIOStatus iostatus;
    bool iostatus_enabled;
    BlockDeviceIoStatus iostatus;
    char device_name[32];
    unsigned long *dirty_bitmap;
    int64_t dirty_count;
Loading