Usage: -drive file=xxx,id=Y, \ -drive file=xxxx,id=X,backing.backing_reference=Y
It will create such backing chain: {virtio-blk dev 'Y'} {virtio-blk dev 'X'} | | | | v v [base] <- [mid] <- ( Y ) <----------------- ( X ) Signed-off-by: Wen Congyang <we...@cn.fujitsu.com> Signed-off-by: zhanghailiang <zhang.zhanghaili...@huawei.com> Signed-off-by: Gonglei <arei.gong...@huawei.com> --- block.c | 39 +++++++++++++++++++++++++++++++++++---- include/block/block.h | 1 + 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index d02d9e9..f93c50d 100644 --- a/block.c +++ b/block.c @@ -1179,6 +1179,7 @@ out: } #define ALLOW_WRITE_BACKING_FILE "allow-write-backing-file" +#define BACKING_REFERENCE "backing_reference" static QemuOptsList backing_file_opts = { .name = "backing_file", .head = QTAILQ_HEAD_INITIALIZER(backing_file_opts.head), @@ -1188,6 +1189,11 @@ static QemuOptsList backing_file_opts = { .type = QEMU_OPT_BOOL, .help = "allow write to backing file", }, + { + .name = BACKING_REFERENCE, + .type = QEMU_OPT_STRING, + .help = "reference to the exsiting BDS", + }, { /* end of list */ } }, }; @@ -1204,11 +1210,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) { char *backing_filename = g_malloc0(PATH_MAX); int ret = 0; - BlockDriverState *backing_hd; + BlockDriverState *backing_hd = NULL; Error *local_err = NULL; QemuOpts *opts = NULL; bool child_rw = false; const BdrvChildRole *child_role = NULL; + const char *reference = NULL; if (bs->backing_hd != NULL) { QDECREF(options); @@ -1231,9 +1238,10 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) goto free_exit; } child_rw = qemu_opt_get_bool(opts, ALLOW_WRITE_BACKING_FILE, false); + reference = qemu_opt_get(opts, BACKING_REFERENCE); child_role = child_rw ? &child_backing_rw : &child_backing; - if (qdict_haskey(options, "file.filename")) { + if (qdict_haskey(options, "file.filename") || reference) { backing_filename[0] = '\0'; } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) { QDECREF(options); @@ -1256,7 +1264,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) goto free_exit; } - backing_hd = bdrv_new(); + if (!reference) { + backing_hd = bdrv_new(); + } if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { qdict_put(options, "driver", qstring_from_str(bs->backing_format)); @@ -1265,7 +1275,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) assert(bs->backing_hd == NULL); ret = bdrv_open_inherit(&backing_hd, *backing_filename ? backing_filename : NULL, - NULL, options, 0, bs, child_role, + reference, options, 0, bs, child_role, NULL, &local_err); if (ret < 0) { bdrv_unref(backing_hd); @@ -1276,6 +1286,19 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) error_free(local_err); goto free_exit; } + if (reference) { + if (bdrv_op_is_blocked(backing_hd, BLOCK_OP_TYPE_BACKING_REFERENCE, + errp)) { + ret = -EBUSY; + goto free_reference_exit; + } + if (backing_hd->blk && blk_disable_attach_dev(backing_hd->blk)) { + error_setg(errp, "backing_hd %s is used by the other device model", + reference); + ret = -EBUSY; + goto free_reference_exit; + } + } bdrv_set_backing_hd(bs, backing_hd); @@ -1283,6 +1306,11 @@ free_exit: qemu_opts_del(opts); g_free(backing_filename); return ret; + +free_reference_exit: + bdrv_unref(backing_hd); + bs->open_flags |= BDRV_O_NO_BACKING; + goto free_exit; } /* @@ -1947,6 +1975,9 @@ void bdrv_close(BlockDriverState *bs) if (bs->backing_hd) { BlockDriverState *backing_hd = bs->backing_hd; bdrv_set_backing_hd(bs, NULL); + if (backing_hd->blk) { + blk_enable_attach_dev(backing_hd->blk); + } bdrv_unref(backing_hd); } diff --git a/include/block/block.h b/include/block/block.h index 612dcad..5812716 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -170,6 +170,7 @@ typedef enum BlockOpType { BLOCK_OP_TYPE_RESIZE, BLOCK_OP_TYPE_STREAM, BLOCK_OP_TYPE_REPLACE, + BLOCK_OP_TYPE_BACKING_REFERENCE, BLOCK_OP_TYPE_MAX, } BlockOpType; -- 2.4.3