qdev: allow setting drive property for realized device
We need an ability to insert filters above top block node, attached to block device. It can't be achieved with blockdev-reopen command. So, we want do it with help of qom-set. Intended usage: Assume there is a node A that is attached to some guest device. 1. blockdev-add to create a filter node B that has A as its child. 2. qom-set to change the node attached to the guest device’s BlockBackend from A to B. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-Id: <20210824083856.17408-5-vsementsov@virtuozzo.com> Signed-off-by: Hanna Reitz <hreitz@redhat.com>
This commit is contained in:
parent
deb2bb163f
commit
d1a58c176a
|
@ -36,11 +36,11 @@
|
||||||
|
|
||||||
static bool check_prop_still_unset(Object *obj, const char *name,
|
static bool check_prop_still_unset(Object *obj, const char *name,
|
||||||
const void *old_val, const char *new_val,
|
const void *old_val, const char *new_val,
|
||||||
Error **errp)
|
bool allow_override, Error **errp)
|
||||||
{
|
{
|
||||||
const GlobalProperty *prop = qdev_find_global_prop(obj, name);
|
const GlobalProperty *prop = qdev_find_global_prop(obj, name);
|
||||||
|
|
||||||
if (!old_val) {
|
if (!old_val || (!prop && allow_override)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +93,34 @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
bool blk_created = false;
|
bool blk_created = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
BlockDriverState *bs;
|
||||||
|
AioContext *ctx;
|
||||||
|
|
||||||
if (!visit_type_str(v, name, &str, errp)) {
|
if (!visit_type_str(v, name, &str, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!check_prop_still_unset(obj, name, *ptr, str, true, errp)) {
|
||||||
* TODO Should this really be an error? If no, the old value
|
return;
|
||||||
* needs to be released before we store the new one.
|
}
|
||||||
*/
|
|
||||||
if (!check_prop_still_unset(obj, name, *ptr, str, errp)) {
|
if (*ptr) {
|
||||||
|
/* BlockBackend alread exists. So, we want to change attached node */
|
||||||
|
blk = *ptr;
|
||||||
|
ctx = blk_get_aio_context(blk);
|
||||||
|
bs = bdrv_lookup_bs(NULL, str, errp);
|
||||||
|
if (!bs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx != bdrv_get_aio_context(bs)) {
|
||||||
|
error_setg(errp, "Different aio context is not supported for new "
|
||||||
|
"node");
|
||||||
|
}
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
blk_replace_bs(blk, bs, errp);
|
||||||
|
aio_context_release(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +132,7 @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
|
||||||
|
|
||||||
blk = blk_by_name(str);
|
blk = blk_by_name(str);
|
||||||
if (!blk) {
|
if (!blk) {
|
||||||
BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
|
bs = bdrv_lookup_bs(NULL, str, NULL);
|
||||||
if (bs) {
|
if (bs) {
|
||||||
/*
|
/*
|
||||||
* If the device supports iothreads, it will make sure to move the
|
* If the device supports iothreads, it will make sure to move the
|
||||||
|
@ -123,8 +141,7 @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
|
||||||
* aware of iothreads require their BlockBackends to be in the main
|
* aware of iothreads require their BlockBackends to be in the main
|
||||||
* AioContext.
|
* AioContext.
|
||||||
*/
|
*/
|
||||||
AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
|
ctx = iothread ? bdrv_get_aio_context(bs) : qemu_get_aio_context();
|
||||||
qemu_get_aio_context();
|
|
||||||
blk = blk_new(ctx, 0, BLK_PERM_ALL);
|
blk = blk_new(ctx, 0, BLK_PERM_ALL);
|
||||||
blk_created = true;
|
blk_created = true;
|
||||||
|
|
||||||
|
@ -196,6 +213,7 @@ static void release_drive(Object *obj, const char *name, void *opaque)
|
||||||
const PropertyInfo qdev_prop_drive = {
|
const PropertyInfo qdev_prop_drive = {
|
||||||
.name = "str",
|
.name = "str",
|
||||||
.description = "Node name or ID of a block device to use as a backend",
|
.description = "Node name or ID of a block device to use as a backend",
|
||||||
|
.realized_set_allowed = true,
|
||||||
.get = get_drive,
|
.get = get_drive,
|
||||||
.set = set_drive,
|
.set = set_drive,
|
||||||
.release = release_drive,
|
.release = release_drive,
|
||||||
|
@ -204,6 +222,7 @@ const PropertyInfo qdev_prop_drive = {
|
||||||
const PropertyInfo qdev_prop_drive_iothread = {
|
const PropertyInfo qdev_prop_drive_iothread = {
|
||||||
.name = "str",
|
.name = "str",
|
||||||
.description = "Node name or ID of a block device to use as a backend",
|
.description = "Node name or ID of a block device to use as a backend",
|
||||||
|
.realized_set_allowed = true,
|
||||||
.get = get_drive,
|
.get = get_drive,
|
||||||
.set = set_drive_iothread,
|
.set = set_drive_iothread,
|
||||||
.release = release_drive,
|
.release = release_drive,
|
||||||
|
@ -238,7 +257,7 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
|
||||||
* TODO Should this really be an error? If no, the old value
|
* TODO Should this really be an error? If no, the old value
|
||||||
* needs to be released before we store the new one.
|
* needs to be released before we store the new one.
|
||||||
*/
|
*/
|
||||||
if (!check_prop_still_unset(obj, name, be->chr, str, errp)) {
|
if (!check_prop_still_unset(obj, name, be->chr, str, false, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +427,7 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
|
||||||
* TODO Should this really be an error? If no, the old value
|
* TODO Should this really be an error? If no, the old value
|
||||||
* needs to be released before we store the new one.
|
* needs to be released before we store the new one.
|
||||||
*/
|
*/
|
||||||
if (!check_prop_still_unset(obj, name, ncs[i], str, errp)) {
|
if (!check_prop_still_unset(obj, name, ncs[i], str, false, errp)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue