xemu/block/write-threshold.c
Markus Armbruster 9af2398977 Include less of the generated modular QAPI headers
In my "build everything" tree, a change to the types in
qapi-schema.json triggers a recompile of about 4800 out of 5100
objects.

The previous commit split up qmp-commands.h, qmp-event.h, qmp-visit.h,
qapi-types.h.  Each of these headers still includes all its shards.
Reduce compile time by including just the shards we actually need.

To illustrate the benefits: adding a type to qapi/migration.json now
recompiles some 2300 instead of 4800 objects.  The next commit will
improve it further.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180211093607.27351-24-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[eblake: rebase to master]
Signed-off-by: Eric Blake <eblake@redhat.com>
2018-03-02 13:45:50 -06:00

126 lines
3.5 KiB
C

/*
* QEMU System Emulator block write threshold notification
*
* Copyright Red Hat, Inc. 2014
*
* Authors:
* Francesco Romani <fromani@redhat.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
* See the COPYING.LIB file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "block/block_int.h"
#include "qemu/coroutine.h"
#include "block/write-threshold.h"
#include "qemu/notify.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-block-core.h"
#include "qapi/qapi-events-block-core.h"
uint64_t bdrv_write_threshold_get(const BlockDriverState *bs)
{
return bs->write_threshold_offset;
}
bool bdrv_write_threshold_is_set(const BlockDriverState *bs)
{
return bs->write_threshold_offset > 0;
}
static void write_threshold_disable(BlockDriverState *bs)
{
if (bdrv_write_threshold_is_set(bs)) {
notifier_with_return_remove(&bs->write_threshold_notifier);
bs->write_threshold_offset = 0;
}
}
uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs,
const BdrvTrackedRequest *req)
{
if (bdrv_write_threshold_is_set(bs)) {
if (req->offset > bs->write_threshold_offset) {
return (req->offset - bs->write_threshold_offset) + req->bytes;
}
if ((req->offset + req->bytes) > bs->write_threshold_offset) {
return (req->offset + req->bytes) - bs->write_threshold_offset;
}
}
return 0;
}
static int coroutine_fn before_write_notify(NotifierWithReturn *notifier,
void *opaque)
{
BdrvTrackedRequest *req = opaque;
BlockDriverState *bs = req->bs;
uint64_t amount = 0;
amount = bdrv_write_threshold_exceeded(bs, req);
if (amount > 0) {
qapi_event_send_block_write_threshold(
bs->node_name,
amount,
bs->write_threshold_offset,
&error_abort);
/* autodisable to avoid flooding the monitor */
write_threshold_disable(bs);
}
return 0; /* should always let other notifiers run */
}
static void write_threshold_register_notifier(BlockDriverState *bs)
{
bs->write_threshold_notifier.notify = before_write_notify;
bdrv_add_before_write_notifier(bs, &bs->write_threshold_notifier);
}
static void write_threshold_update(BlockDriverState *bs,
int64_t threshold_bytes)
{
bs->write_threshold_offset = threshold_bytes;
}
void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes)
{
if (bdrv_write_threshold_is_set(bs)) {
if (threshold_bytes > 0) {
write_threshold_update(bs, threshold_bytes);
} else {
write_threshold_disable(bs);
}
} else {
if (threshold_bytes > 0) {
/* avoid multiple registration */
write_threshold_register_notifier(bs);
write_threshold_update(bs, threshold_bytes);
}
/* discard bogus disable request */
}
}
void qmp_block_set_write_threshold(const char *node_name,
uint64_t threshold_bytes,
Error **errp)
{
BlockDriverState *bs;
AioContext *aio_context;
bs = bdrv_find_node(node_name);
if (!bs) {
error_setg(errp, "Device '%s' not found", node_name);
return;
}
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
bdrv_write_threshold_set(bs, threshold_bytes);
aio_context_release(aio_context);
}