get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/813570/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 813570,
    "url": "http://patchwork.ozlabs.org/api/patches/813570/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20170913181910.29688-11-mreitz@redhat.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20170913181910.29688-11-mreitz@redhat.com>",
    "list_archive_url": null,
    "date": "2017-09-13T18:19:02",
    "name": "[10/18] block/mirror: Make source the file child",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "dc999ba4c908e8365b4fa07b6efb1df6f3332fc9",
    "submitter": {
        "id": 36836,
        "url": "http://patchwork.ozlabs.org/api/people/36836/?format=api",
        "name": "Max Reitz",
        "email": "mreitz@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20170913181910.29688-11-mreitz@redhat.com/mbox/",
    "series": [
        {
            "id": 2960,
            "url": "http://patchwork.ozlabs.org/api/series/2960/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2960",
            "date": "2017-09-13T18:18:52",
            "name": "block/mirror: Add active-sync mirroring",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/2960/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/813570/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/813570/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)",
            "ext-mx07.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com",
            "ext-mx07.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=mreitz@redhat.com"
        ],
        "Received": [
            "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xsqzB4dRMz9rxl\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 04:32:54 +1000 (AEST)",
            "from localhost ([::1]:44063 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dsCSy-0002RA-Jd\n\tfor incoming@patchwork.ozlabs.org; Wed, 13 Sep 2017 14:32:52 -0400",
            "from eggs.gnu.org ([2001:4830:134:3::10]:37181)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <mreitz@redhat.com>) id 1dsCHV-0000LU-7D\n\tfor qemu-devel@nongnu.org; Wed, 13 Sep 2017 14:21:03 -0400",
            "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <mreitz@redhat.com>) id 1dsCHS-0005fV-W3\n\tfor qemu-devel@nongnu.org; Wed, 13 Sep 2017 14:21:01 -0400",
            "from mx1.redhat.com ([209.132.183.28]:51504)\n\tby eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <mreitz@redhat.com>)\n\tid 1dsCHM-0005YV-BH; Wed, 13 Sep 2017 14:20:52 -0400",
            "from smtp.corp.redhat.com\n\t(int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 6A118C047B88;\n\tWed, 13 Sep 2017 18:20:51 +0000 (UTC)",
            "from localhost (ovpn-204-23.brq.redhat.com [10.40.204.23])\n\tby smtp.corp.redhat.com (Postfix) with ESMTPS id 202205D763;\n\tWed, 13 Sep 2017 18:20:43 +0000 (UTC)"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.3.2 mx1.redhat.com 6A118C047B88",
        "From": "Max Reitz <mreitz@redhat.com>",
        "To": "qemu-block@nongnu.org",
        "Date": "Wed, 13 Sep 2017 20:19:02 +0200",
        "Message-Id": "<20170913181910.29688-11-mreitz@redhat.com>",
        "In-Reply-To": "<20170913181910.29688-1-mreitz@redhat.com>",
        "References": "<20170913181910.29688-1-mreitz@redhat.com>",
        "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.15",
        "X-Greylist": "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.31]);\n\tWed, 13 Sep 2017 18:20:51 +0000 (UTC)",
        "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]\n\t[fuzzy]",
        "X-Received-From": "209.132.183.28",
        "Subject": "[Qemu-devel] [PATCH 10/18] block/mirror: Make source the file child",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.21",
        "Precedence": "list",
        "List-Id": "<qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Cc": "Kevin Wolf <kwolf@redhat.com>, Fam Zheng <famz@redhat.com>,\n\tqemu-devel@nongnu.org, Max Reitz <mreitz@redhat.com>,\n\tStefan Hajnoczi <stefanha@redhat.com>, John Snow <jsnow@redhat.com>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"
    },
    "content": "Regarding the source BDS, the mirror BDS is arguably a filter node.\nTherefore, the source BDS should be its \"file\" child.\n\nSigned-off-by: Max Reitz <mreitz@redhat.com>\n---\n block/mirror.c             | 127 ++++++++++++++++++++++++++++++++++-----------\n block/qapi.c               |  25 ++++++---\n tests/qemu-iotests/141.out |   4 +-\n 3 files changed, 119 insertions(+), 37 deletions(-)",
    "diff": "diff --git a/block/mirror.c b/block/mirror.c\nindex 9df4157511..05410c94ca 100644\n--- a/block/mirror.c\n+++ b/block/mirror.c\n@@ -77,8 +77,16 @@ typedef struct MirrorBlockJob {\n     int target_cluster_size;\n     int max_iov;\n     bool initial_zeroing_ongoing;\n+\n+    /* Signals that we are no longer accessing source and target and the mirror\n+     * BDS should thus relinquish all permissions */\n+    bool exiting;\n } MirrorBlockJob;\n \n+typedef struct MirrorBDSOpaque {\n+    MirrorBlockJob *job;\n+} MirrorBDSOpaque;\n+\n struct MirrorOp {\n     MirrorBlockJob *s;\n     QEMUIOVector qiov;\n@@ -595,12 +603,15 @@ static void mirror_exit(BlockJob *job, void *opaque)\n {\n     MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);\n     MirrorExitData *data = opaque;\n+    MirrorBDSOpaque *bs_opaque = s->mirror_top_bs->opaque;\n     AioContext *replace_aio_context = NULL;\n     BlockDriverState *src = s->source->bs;\n     BlockDriverState *target_bs = blk_bs(s->target);\n     BlockDriverState *mirror_top_bs = s->mirror_top_bs;\n     Error *local_err = NULL;\n \n+    s->exiting = true;\n+\n     bdrv_release_dirty_bitmap(src, s->dirty_bitmap);\n \n     /* Make sure that the source BDS doesn't go away before we called\n@@ -622,7 +633,7 @@ static void mirror_exit(BlockJob *job, void *opaque)\n \n     /* We don't access the source any more. Dropping any WRITE/RESIZE is\n      * required before it could become a backing file of target_bs. */\n-    bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,\n+    bdrv_child_try_set_perm(mirror_top_bs->file, 0, BLK_PERM_ALL,\n                             &error_abort);\n     if (s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {\n         BlockDriverState *backing = s->is_none_mode ? src : s->base;\n@@ -673,12 +684,11 @@ static void mirror_exit(BlockJob *job, void *opaque)\n \n     /* Remove the mirror filter driver from the graph. Before this, get rid of\n      * the blockers on the intermediate nodes so that the resulting state is\n-     * valid. Also give up permissions on mirror_top_bs->backing, which might\n+     * valid. Also give up permissions on mirror_top_bs->file, which might\n      * block the removal. */\n     block_job_remove_all_bdrv(job);\n-    bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,\n-                            &error_abort);\n-    bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);\n+    bdrv_child_try_set_perm(mirror_top_bs->file, 0, BLK_PERM_ALL, &error_abort);\n+    bdrv_replace_node(mirror_top_bs, mirror_top_bs->file->bs, &error_abort);\n \n     /* We just changed the BDS the job BB refers to (with either or both of the\n      * bdrv_replace_node() calls), so switch the BB back so the cleanup does\n@@ -687,6 +697,7 @@ static void mirror_exit(BlockJob *job, void *opaque)\n     blk_set_perm(job->blk, 0, BLK_PERM_ALL, &error_abort);\n     blk_insert_bs(job->blk, mirror_top_bs, &error_abort);\n \n+    bs_opaque->job = NULL;\n     block_job_completed(&s->common, data->ret);\n \n     g_free(data);\n@@ -1102,7 +1113,7 @@ static void mirror_drain(BlockJob *job)\n {\n     MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);\n \n-    /* Need to keep a reference in case blk_drain triggers execution\n+    /* Need to keep a reference in case bdrv_drain triggers execution\n      * of mirror_complete...\n      */\n     if (s->target) {\n@@ -1135,44 +1146,88 @@ static const BlockJobDriver commit_active_job_driver = {\n     .drain                  = mirror_drain,\n };\n \n+static void source_child_inherit_fmt_options(int *child_flags,\n+                                             QDict *child_options,\n+                                             int parent_flags,\n+                                             QDict *parent_options)\n+{\n+    child_backing.inherit_options(child_flags, child_options,\n+                                  parent_flags, parent_options);\n+}\n+\n+static char *source_child_get_parent_desc(BdrvChild *c)\n+{\n+    return child_backing.get_parent_desc(c);\n+}\n+\n+static void source_child_cb_drained_begin(BdrvChild *c)\n+{\n+    BlockDriverState *bs = c->opaque;\n+    MirrorBDSOpaque *s = bs->opaque;\n+\n+    if (s && s->job) {\n+        block_job_drained_begin(&s->job->common);\n+    }\n+    bdrv_drained_begin(bs);\n+}\n+\n+static void source_child_cb_drained_end(BdrvChild *c)\n+{\n+    BlockDriverState *bs = c->opaque;\n+    MirrorBDSOpaque *s = bs->opaque;\n+\n+    if (s && s->job) {\n+        block_job_drained_end(&s->job->common);\n+    }\n+    bdrv_drained_end(bs);\n+}\n+\n+static BdrvChildRole source_child_role = {\n+    .inherit_options    = source_child_inherit_fmt_options,\n+    .get_parent_desc    = source_child_get_parent_desc,\n+    .drained_begin      = source_child_cb_drained_begin,\n+    .drained_end        = source_child_cb_drained_end,\n+};\n+\n static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,\n     uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)\n {\n-    return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);\n+    return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);\n }\n \n static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,\n     uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)\n {\n-    return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);\n+    return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);\n }\n \n static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)\n {\n-    return bdrv_co_flush(bs->backing->bs);\n+    return bdrv_co_flush(bs->file->bs);\n }\n \n static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,\n     int64_t offset, int bytes, BdrvRequestFlags flags)\n {\n-    return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);\n+    return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);\n }\n \n static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,\n     int64_t offset, int bytes)\n {\n-    return bdrv_co_pdiscard(bs->backing->bs, offset, bytes);\n+    return bdrv_co_pdiscard(bs->file->bs, offset, bytes);\n }\n \n static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)\n {\n-    bdrv_refresh_filename(bs->backing->bs);\n     pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),\n-            bs->backing->bs->filename);\n+            bs->file->bs->filename);\n }\n \n static void bdrv_mirror_top_close(BlockDriverState *bs)\n {\n+    bdrv_unref_child(bs, bs->file);\n+    bs->file = NULL;\n }\n \n static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,\n@@ -1180,6 +1235,14 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,\n                                        uint64_t perm, uint64_t shared,\n                                        uint64_t *nperm, uint64_t *nshared)\n {\n+    MirrorBDSOpaque *s = bs->opaque;\n+\n+    if (s->job && s->job->exiting) {\n+        *nperm = 0;\n+        *nshared = BLK_PERM_ALL;\n+        return;\n+    }\n+\n     /* Must be able to forward guest writes to the real image */\n     *nperm = 0;\n     if (perm & BLK_PERM_WRITE) {\n@@ -1190,7 +1253,7 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,\n }\n \n /* Dummy node that provides consistent read to its users without requiring it\n- * from its backing file and that allows writes on the backing file chain. */\n+ * from its source file and that allows writes on the source file. */\n static BlockDriver bdrv_mirror_top = {\n     .format_name                = \"mirror_top\",\n     .bdrv_co_preadv             = bdrv_mirror_top_preadv,\n@@ -1198,7 +1261,7 @@ static BlockDriver bdrv_mirror_top = {\n     .bdrv_co_pwrite_zeroes      = bdrv_mirror_top_pwrite_zeroes,\n     .bdrv_co_pdiscard           = bdrv_mirror_top_pdiscard,\n     .bdrv_co_flush              = bdrv_mirror_top_flush,\n-    .bdrv_co_get_block_status   = bdrv_co_get_block_status_from_backing,\n+    .bdrv_co_get_block_status   = bdrv_co_get_block_status_from_file,\n     .bdrv_refresh_filename      = bdrv_mirror_top_refresh_filename,\n     .bdrv_close                 = bdrv_mirror_top_close,\n     .bdrv_child_perm            = bdrv_mirror_top_child_perm,\n@@ -1221,6 +1284,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,\n                              Error **errp)\n {\n     MirrorBlockJob *s;\n+    MirrorBDSOpaque *bs_opaque;\n     BlockDriverState *mirror_top_bs;\n     bool target_graph_mod;\n     bool target_is_backing;\n@@ -1244,9 +1308,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,\n         buf_size = DEFAULT_MIRROR_BUF_SIZE;\n     }\n \n-    /* In the case of active commit, add dummy driver to provide consistent\n-     * reads on the top, while disabling it in the intermediate nodes, and make\n-     * the backing chain writable. */\n+    /* Create mirror BDS */\n     mirror_top_bs = bdrv_new_open_driver(&bdrv_mirror_top, filter_node_name,\n                                          BDRV_O_RDWR, errp);\n     if (mirror_top_bs == NULL) {\n@@ -1256,14 +1318,19 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,\n         mirror_top_bs->implicit = true;\n     }\n     mirror_top_bs->total_sectors = bs->total_sectors;\n+    bs_opaque = g_new0(MirrorBDSOpaque, 1);\n+    mirror_top_bs->opaque = bs_opaque;\n     bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));\n \n-    /* bdrv_append takes ownership of the mirror_top_bs reference, need to keep\n-     * it alive until block_job_create() succeeds even if bs has no parent. */\n-    bdrv_ref(mirror_top_bs);\n-    bdrv_drained_begin(bs);\n-    bdrv_append(mirror_top_bs, bs, &local_err);\n-    bdrv_drained_end(bs);\n+    /* Create reference for bdrv_attach_child() */\n+    bdrv_ref(bs);\n+    mirror_top_bs->file = bdrv_attach_child(mirror_top_bs, bs, \"file\",\n+                                            &source_child_role, &local_err);\n+    if (!local_err) {\n+        bdrv_drained_begin(bs);\n+        bdrv_replace_node(bs, mirror_top_bs, &local_err);\n+        bdrv_drained_end(bs);\n+    }\n \n     if (local_err) {\n         bdrv_unref(mirror_top_bs);\n@@ -1280,6 +1347,8 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,\n     if (!s) {\n         goto fail;\n     }\n+    bs_opaque->job = s;\n+\n     /* The block job now has a reference to this node */\n     bdrv_unref(mirror_top_bs);\n \n@@ -1329,7 +1398,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,\n         s->should_complete = true;\n     }\n \n-    s->source = mirror_top_bs->backing;\n+    s->source = mirror_top_bs->file;\n     s->mirror_top_bs = mirror_top_bs;\n \n     s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);\n@@ -1373,12 +1442,12 @@ fail:\n \n         g_free(s->replaces);\n         blk_unref(s->target);\n-        block_job_early_fail(&s->common);\n+        bs_opaque->job = NULL;\n+        block_job_unref(&s->common);\n     }\n \n-    bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,\n-                            &error_abort);\n-    bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);\n+    bdrv_child_try_set_perm(mirror_top_bs->file, 0, BLK_PERM_ALL, &error_abort);\n+    bdrv_replace_node(mirror_top_bs, mirror_top_bs->file->bs, &error_abort);\n \n     bdrv_unref(mirror_top_bs);\n }\ndiff --git a/block/qapi.c b/block/qapi.c\nindex 7fa2437923..ee792d0cbc 100644\n--- a/block/qapi.c\n+++ b/block/qapi.c\n@@ -147,9 +147,13 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,\n \n         /* Skip automatically inserted nodes that the user isn't aware of for\n          * query-block (blk != NULL), but not for query-named-block-nodes */\n-        while (blk && bs0->drv && bs0->implicit) {\n-            bs0 = backing_bs(bs0);\n-            assert(bs0);\n+        while (blk && bs0 && bs0->drv && bs0->implicit) {\n+            if (bs0->backing) {\n+                bs0 = backing_bs(bs0);\n+            } else {\n+                assert(bs0->file);\n+                bs0 = bs0->file->bs;\n+            }\n         }\n     }\n \n@@ -337,7 +341,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,\n \n     /* Skip automatically inserted nodes that the user isn't aware of */\n     while (bs && bs->drv && bs->implicit) {\n-        bs = backing_bs(bs);\n+        if (bs->backing) {\n+            bs = backing_bs(bs);\n+        } else {\n+            assert(bs->file);\n+            bs = bs->file->bs;\n+        }\n     }\n \n     info->device = g_strdup(blk_name(blk));\n@@ -466,8 +475,12 @@ static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,\n      * a BlockBackend-level command. Stay at the exact node for a node-level\n      * command. */\n     while (blk_level && bs->drv && bs->implicit) {\n-        bs = backing_bs(bs);\n-        assert(bs);\n+        if (bs->backing) {\n+            bs = backing_bs(bs);\n+        } else {\n+            assert(bs->file);\n+            bs = bs->file->bs;\n+        }\n     }\n \n     if (bdrv_get_node_name(bs)[0]) {\ndiff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out\nindex 82e763b68d..8c4dd6d531 100644\n--- a/tests/qemu-iotests/141.out\n+++ b/tests/qemu-iotests/141.out\n@@ -20,7 +20,7 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.\n Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT\n {\"timestamp\": {\"seconds\":  TIMESTAMP, \"microseconds\":  TIMESTAMP}, \"event\": \"BLOCK_JOB_READY\", \"data\": {\"device\": \"job0\", \"len\": 0, \"offset\": 0, \"speed\": 0, \"type\": \"mirror\"}}\n {\"return\": {}}\n-{\"error\": {\"class\": \"GenericError\", \"desc\": \"Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'\"}}\n+{\"error\": {\"class\": \"GenericError\", \"desc\": \"Block device drv0 is in use\"}}\n {\"return\": {}}\n {\"timestamp\": {\"seconds\":  TIMESTAMP, \"microseconds\":  TIMESTAMP}, \"event\": \"BLOCK_JOB_COMPLETED\", \"data\": {\"device\": \"job0\", \"len\": 0, \"offset\": 0, \"speed\": 0, \"type\": \"mirror\"}}\n {\"return\": {}}\n@@ -30,7 +30,7 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.\n {\"return\": {}}\n {\"timestamp\": {\"seconds\":  TIMESTAMP, \"microseconds\":  TIMESTAMP}, \"event\": \"BLOCK_JOB_READY\", \"data\": {\"device\": \"job0\", \"len\": 0, \"offset\": 0, \"speed\": 0, \"type\": \"commit\"}}\n {\"return\": {}}\n-{\"error\": {\"class\": \"GenericError\", \"desc\": \"Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'\"}}\n+{\"error\": {\"class\": \"GenericError\", \"desc\": \"Block device drv0 is in use\"}}\n {\"return\": {}}\n {\"timestamp\": {\"seconds\":  TIMESTAMP, \"microseconds\":  TIMESTAMP}, \"event\": \"BLOCK_JOB_COMPLETED\", \"data\": {\"device\": \"job0\", \"len\": 0, \"offset\": 0, \"speed\": 0, \"type\": \"commit\"}}\n {\"return\": {}}\n",
    "prefixes": [
        "10/18"
    ]
}