aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/backup.c2
-rw-r--r--block/copy-on-read.c33
-rw-r--r--block/io.c11
-rw-r--r--block/mirror.c6
-rw-r--r--block/monitor/block-hmp-cmds.c31
-rw-r--r--block/rbd.c32
-rw-r--r--block/write-threshold.c91
7 files changed, 66 insertions, 140 deletions
diff --git a/block/backup.c b/block/backup.c
index 6cf2f974aa..bd3614ce70 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -331,7 +331,7 @@ static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
}
}
-static void backup_cancel(Job *job)
+static void backup_cancel(Job *job, bool force)
{
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 9cad9e1b8c..c428682272 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -29,7 +29,6 @@
typedef struct BDRVStateCOR {
- bool active;
BlockDriverState *bottom_bs;
bool chain_frozen;
} BDRVStateCOR;
@@ -89,7 +88,6 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
*/
bdrv_ref(bottom_bs);
}
- state->active = true;
state->bottom_bs = bottom_bs;
/*
@@ -112,17 +110,6 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
{
- BDRVStateCOR *s = bs->opaque;
-
- if (!s->active) {
- /*
- * While the filter is being removed
- */
- *nperm = 0;
- *nshared = BLK_PERM_ALL;
- return;
- }
-
*nperm = perm & PERM_PASSTHROUGH;
*nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
@@ -280,32 +267,14 @@ static BlockDriver bdrv_copy_on_read = {
void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
{
- BdrvChild *child;
- BlockDriverState *bs;
BDRVStateCOR *s = cor_filter_bs->opaque;
- child = bdrv_filter_child(cor_filter_bs);
- if (!child) {
- return;
- }
- bs = child->bs;
-
- /* Retain the BDS until we complete the graph change. */
- bdrv_ref(bs);
- /* Hold a guest back from writing while permissions are being reset. */
- bdrv_drained_begin(bs);
- /* Drop permissions before the graph change. */
- s->active = false;
/* unfreeze, as otherwise bdrv_replace_node() will fail */
if (s->chain_frozen) {
s->chain_frozen = false;
bdrv_unfreeze_backing_chain(cor_filter_bs, s->bottom_bs);
}
- bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort);
- bdrv_replace_node(cor_filter_bs, bs, &error_abort);
-
- bdrv_drained_end(bs);
- bdrv_unref(bs);
+ bdrv_drop_filter(cor_filter_bs, &error_abort);
bdrv_unref(cor_filter_bs);
}
diff --git a/block/io.c b/block/io.c
index 35b6c56efc..1e826ba9e8 100644
--- a/block/io.c
+++ b/block/io.c
@@ -30,6 +30,7 @@
#include "block/blockjob_int.h"
#include "block/block_int.h"
#include "block/coroutines.h"
+#include "block/write-threshold.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
@@ -2008,8 +2009,8 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
} else {
assert(child->perm & BLK_PERM_WRITE);
}
- return notifier_with_return_list_notify(&bs->before_write_notifiers,
- req);
+ bdrv_write_threshold_check_write(bs, offset, bytes);
+ return 0;
case BDRV_TRACKED_TRUNCATE:
assert(child->perm & BLK_PERM_RESIZE);
return 0;
@@ -3164,12 +3165,6 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
return true;
}
-void bdrv_add_before_write_notifier(BlockDriverState *bs,
- NotifierWithReturn *notifier)
-{
- notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
-}
-
void bdrv_io_plug(BlockDriverState *bs)
{
BdrvChild *child;
diff --git a/block/mirror.c b/block/mirror.c
index 840b8e8c15..019f6deaa5 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1178,12 +1178,14 @@ static bool mirror_drained_poll(BlockJob *job)
return !!s->in_flight;
}
-static void mirror_cancel(Job *job)
+static void mirror_cancel(Job *job, bool force)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
BlockDriverState *target = blk_bs(s->target);
- bdrv_cancel_in_flight(target);
+ if (force || !job_is_ready(job)) {
+ bdrv_cancel_in_flight(target);
+ }
}
static const BlockJobDriver mirror_job_driver = {
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index ebf1033f31..3e6670c963 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -557,8 +557,10 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
{
- BlockBackend *blk;
+ BlockBackend *blk = NULL;
+ BlockDriverState *bs = NULL;
BlockBackend *local_blk = NULL;
+ AioContext *ctx = NULL;
bool qdev = qdict_get_try_bool(qdict, "qdev", false);
const char *device = qdict_get_str(qdict, "device");
const char *command = qdict_get_str(qdict, "command");
@@ -573,20 +575,24 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
} else {
blk = blk_by_name(device);
if (!blk) {
- BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
- if (bs) {
- blk = local_blk = blk_new(bdrv_get_aio_context(bs),
- 0, BLK_PERM_ALL);
- ret = blk_insert_bs(blk, bs, &err);
- if (ret < 0) {
- goto fail;
- }
- } else {
+ bs = bdrv_lookup_bs(NULL, device, &err);
+ if (!bs) {
goto fail;
}
}
}
+ ctx = blk ? blk_get_aio_context(blk) : bdrv_get_aio_context(bs);
+ aio_context_acquire(ctx);
+
+ if (bs) {
+ blk = local_blk = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL);
+ ret = blk_insert_bs(blk, bs, &err);
+ if (ret < 0) {
+ goto fail;
+ }
+ }
+
/*
* Notably absent: Proper permission management. This is sad, but it seems
* almost impossible to achieve without changing the semantics and thereby
@@ -616,6 +622,11 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
fail:
blk_unref(local_blk);
+
+ if (ctx) {
+ aio_context_release(ctx);
+ }
+
hmp_handle_error(mon, err);
}
diff --git a/block/rbd.c b/block/rbd.c
index f098a89c7b..26f64cce7c 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -113,21 +113,31 @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
const char *keypairs, const char *secretid,
Error **errp);
+static char *qemu_rbd_strchr(char *src, char delim)
+{
+ char *p;
+
+ for (p = src; *p; ++p) {
+ if (*p == delim) {
+ return p;
+ }
+ if (*p == '\\' && p[1] != '\0') {
+ ++p;
+ }
+ }
+
+ return NULL;
+}
+
+
static char *qemu_rbd_next_tok(char *src, char delim, char **p)
{
char *end;
*p = NULL;
- for (end = src; *end; ++end) {
- if (*end == delim) {
- break;
- }
- if (*end == '\\' && end[1] != '\0') {
- end++;
- }
- }
- if (*end == delim) {
+ end = qemu_rbd_strchr(src, delim);
+ if (end) {
*p = end + 1;
*end = '\0';
}
@@ -171,7 +181,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
qemu_rbd_unescape(found_str);
qdict_put_str(options, "pool", found_str);
- if (strchr(p, '@')) {
+ if (qemu_rbd_strchr(p, '@')) {
image_name = qemu_rbd_next_tok(p, '@', &p);
found_str = qemu_rbd_next_tok(p, ':', &p);
@@ -181,7 +191,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
image_name = qemu_rbd_next_tok(p, ':', &p);
}
/* Check for namespace in the image_name */
- if (strchr(image_name, '/')) {
+ if (qemu_rbd_strchr(image_name, '/')) {
found_str = qemu_rbd_next_tok(image_name, '/', &image_name);
qemu_rbd_unescape(found_str);
qdict_put_str(options, "namespace", found_str);
diff --git a/block/write-threshold.c b/block/write-threshold.c
index 85b78dc2a9..35cafbc22d 100644
--- a/block/write-threshold.c
+++ b/block/write-threshold.c
@@ -12,9 +12,7 @@
#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"
@@ -24,82 +22,9 @@ 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);
-
- /* 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 */
- }
+ bs->write_threshold_offset = threshold_bytes;
}
void qmp_block_set_write_threshold(const char *node_name,
@@ -122,3 +47,17 @@ void qmp_block_set_write_threshold(const char *node_name,
aio_context_release(aio_context);
}
+
+void bdrv_write_threshold_check_write(BlockDriverState *bs, int64_t offset,
+ int64_t bytes)
+{
+ int64_t end = offset + bytes;
+ uint64_t wtr = bs->write_threshold_offset;
+
+ if (wtr > 0 && end > wtr) {
+ qapi_event_send_block_write_threshold(bs->node_name, end - wtr, wtr);
+
+ /* autodisable to avoid flooding the monitor */
+ bdrv_write_threshold_set(bs, 0);
+ }
+}