Make qemu-img/qemu-nbd/qemu-io CLI more flexible
v6 cover Make qemu-img/qemu-nbd/qemu-io CLI more flexible
This series of patches expands the syntax of the qemu-img, qemu-nbd and qemu-io commands to make them more flexible.
v0: https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg04365.html
v1: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04014.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04354.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03381.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg04984.html
v5: https://lists.gnu.org/archive/html/qemu-block/2016-02/msg00022.html
First all three gain a --object parameter, which allows instantiation of user creatable object types. The immediate use case is to allow for creation of the 'secret' object type to pass passwords for curl, iscsi and rbd drivers. For qemu-nbd this will also be needed to create TLS certificates for encryption support.
Then all three gain a '--image-opts' parameter which causes the positional filenames to be interepreted as option strings rather tha nplain filenames. This avoids the need to use the JSON syntax, or to add custom CLI args for each block backend option that exists. The immediate use case is to allow the user to specify the ID of the 'secret' object they just created.
Finally, there are a few small cleanup patches
NB, this series will conflict with my series adding TLS support to NBD. After one of the series wins the race to merge, I will rebase the other series. I don't mind which merges first really, but the sooner the better considering the forthcoming soft-freeze and that this is a dep for several other patch series.
Changed in v6:
- Add missing docs of --image-opts for qemu-nbd man page (Eric)
- Remove left over special casing of 'file' in QemuOpts (Kevin)
- Pass NULL to getopt_long when optionindex is not needed (Eric)
- Misc typos in qemu-img docs (Eric)
- Fix qemu-io logic error checking argv/argc opt bounds (Eric)
- Ensure 'id' is passed into blk_open in qemu-img (Kevin)
- Share code for doing block dev passwd prompting
Changed in v5:
- Move more common object creation code into qom/ (Kevin)
- Add missing @var{} syntax in CLI help definition (Kevin)
- Declare QemuOpts closer to time of use (Kevin)
- Directly reference registered opts instead of calling qemu_find_opts (Kevin)
- Use consistent exit/return/goto pattern in qemu-img (Kevin)
- Remove special casing of 'file' in QemuOpts handling for bdrv_open (Kevin)
- Split file file opening code out into separate method (Kevin)
Changed in v4:
- Fix error reporting when object_create fails
Changed in v3:
- Rebase to resolve with conflicts against recently merged code
- Remove use of errx()
Changed in v2:
- Share more common code in qom/object_interfaces.c to avoid duplicating so much of 'object_create' in each command
- Remove previously added '--source optstring' parameter which replaced the positional filenames, in favour of keeping the positional filenames but using a --image-opts boolean arg to change their interpretation
- Added docs for --image-opts to qemu-img man page
- Use printf instead of echo -n in examples
- Line wrap help string based on user terminal width not source code width
- Update qemu-nbd/qemu-io to use constants for options
- Update qemu-nbd to avoid overlapping option values
Daniel P. Berrange (10):
qom: add helpers for UserCreatable object types
qemu-io: add support for --object command line arg
qemu-nbd: add support for --object command line arg
qemu-img: add support for --object command line arg
qemu-io: allow specifying image as a set of options args
qemu-nbd: allow specifying image as a set of options args
qemu-img: allow specifying image as a set of options args
qemu-nbd: don't overlap long option values with short options
qemu-nbd: use no_argument/required_argument constants
qemu-io: use no_argument/required_argument constants
hmp.c | 52 +---- include/monitor/monitor.h | 3 - include/qom/object_interfaces.h | 92 ++++++++ qemu-img-cmds.hx | 44 ++-- qemu-img.c | 466 ++++++++++++++++++++++++++++++++++++---- qemu-img.texi | 14 ++ qemu-io.c | 116 ++++++++-- qemu-nbd.c | 128 ++++++++--- qemu-nbd.texi | 13 +- qmp.c | 76 +------ qom/object_interfaces.c | 174 +++++++++++++++ vl.c | 68 +----- 12 files changed, 954 insertions(+), 292 deletions(-)
Signature · 1 line
2.5.0
PATCH v6 1/10 qom: add helpers for UserCreatable object types
The QMP monitor code has two helper methods object_add and qmp_object_del that are called from several places in the code (QMP, HMP and main emulator startup).
The HMP and main emulator startup code also share further logic that extracts the qom-type & id values from a qdict.
We soon need to use this logic from qemu-img, qemu-io and qemu-nbd too, but don't want those to depend on the monitor, nor do we want to duplicate the code.
To avoid this, move some code out of qmp.c and hmp.c adding new methods to qom/object_interfaces.c
- user_creatable_add - takes a QDict holding a full object definition & instantiates it
- user_creatable_add_type - takes an ID, type name, and QDict holding object properties & instantiates it
- user_creatable_add_opts - takes a QemuOpts holding a full object definition & instantiates it
- user_creatable_add_opts_foreach - variant on user_creatable_add_opts which can be directly used in conjunction with qemu_opts_foreach.
- user_creatable_del - takes an ID and deletes the corresponding object
The existing code is updated to use these new methods.
--- hmp.c | 52 +++--------- include/monitor/monitor.h | 3 - include/qom/object_interfaces.h | 92 +++++++++++++++++++++ qmp.c | 76 ++---------------- qom/object_interfaces.c | 174 ++++++++++++++++++++++++++++++++++++++++ vl.c | 68 ++-------------- 6 files changed, 290 insertions(+), 175 deletions(-)
hmp.c +11 -41
@@ -30,6 +30,7 @@#include "qapi/string-output-visitor.h" #include "qapi/util.h" #include "qapi-visit.h" +#include "qom/object_interfaces.h" #include "ui/console.h" #include "block/qapi.h" #include "qemu-io.h"
@@ -1655,58 +1656,27 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)void hmp_object_add (Monitor *mon,const QDict *qdict) {Error *err =NULL ; -Error *err_end =NULL ;QemuOpts *opts; -char *type =NULL ; -char *id =NULL ;OptsVisitor *ov; -QDict *pdict; -Visitor *v; +Object *obj =NULL ; opts =qemu_opts_from_qdict (qemu_find_opts ("object" ), qdict, &err);if (err) { - goto out; +hmp_handle_error (mon, &err); +return ; } ov =opts_visitor_new (opts); - pdict =qdict_clone_shallow (qdict); - v =opts_get_visitor (ov); - -visit_start_struct (v,NULL ,NULL ,0 , &err); -if (err) { - goto out_clean; - } - -qdict_del (pdict,"qom-type" ); -visit_type_str (v,"qom-type" , &type, &err); -if (err) { - goto out_end; - } + obj =user_creatable_add (qdict,opts_get_visitor (ov), &err); +opts_visitor_cleanup (ov); +qemu_opts_del (opts); -qdict_del (pdict,"id" ); -visit_type_str (v,"id" , &id, &err);if (err) { - goto out_end; +hmp_handle_error (mon, &err); } - -object_add (type, id, pdict, v, &err); - -out_end: -visit_end_struct (v, &err_end); -if (!err && err_end) { -qmp_object_del (id,NULL ); +if (obj) { +object_unref (obj); } -error_propagate (&err, err_end); -out_clean: -opts_visitor_cleanup (ov); - -QDECREF (pdict); -qemu_opts_del (opts); -g_free (id); -g_free (type); - -out: -hmp_handle_error (mon, &err); }void hmp_getfd (Monitor *mon,const QDict *qdict)
@@ -1934,7 +1904,7 @@ void hmp_object_del(Monitor *mon, const QDict *qdict)const char *id =qdict_get_str (qdict,"id" );Error *err =NULL ; -qmp_object_del (id, &err); +user_creatable_del (id, &err);hmp_handle_error (mon, &err); }
include/monitor/monitor.h +0 -3
@@ -43,9 +43,6 @@ void monitor_read_command(Monitor *mon, int show_prompt);int monitor_read_password (Monitor *mon,ReadLineFunc *readline_func,void *opaque); -void object_add (const char *type,const char *id,const QDict *qdict, -Visitor *v,Error **errp); -AddfdInfo *monitor_fdset_add_fd (int fd,bool has_fdset_id,int64_t fdset_id,bool has_opaque,const char *opaque,Error **errp);
include/qom/object_interfaces.h +92 -0
102 lines not on this page · raw message
qmp.c +7 -69
99 lines not on this page · raw message
qom/object_interfaces.c +174 -0
186 lines not on this page · raw message
vl.c +6 -62
86 lines not on this page · raw message
Signature · 1 line
2.5.0
Re: [Qemu-devel] [PATCH v6 01/10] qom: add helpers for UserCreatable object types
This commit regresses error message quality from
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar
qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundto just
qemu-system-x86_64: Property '.foo' not found
Clue: cur_loc points to garbage.
(gdb) p cur_loc
$1 = (Location *) 0x7fffffffdc10
(gdb) p *cur_loc
$2 = {kind = (unknown: 4294958128), num = 32767,
ptr = 0x555555b804a2 <error_report_err+44>, prev = 0x5555565d2770 <std_loc>}Looks like cur_loc is dangling. Happens when you forget to loc_pop() a Location before it dies. This one is on the stack.
*Might* be release critical.
For comparison, this is how it looks before the patch:
(gdb) p cur_loc
$1 = (Location *) 0x7fffffffdc10
(gdb) p *cur_loc
$2 = {kind = LOC_CMDLINE, num = 2, ptr = 0x7fffffffe018, prev =
0x5555565d2770 <std_loc>}Quoted 641 lines · Daniel P. Berrange
The QMP monitor code has two helper methods
object_addandqmp_object_delthat are called from several places in the code (QMP, HMP and main emulator startup).The HMP and main emulator startup code also share further logic that extracts the qom-type & id values from a qdict.
We soon need to use this logic from qemu-img, qemu-io and qemu-nbd too, but don't want those to depend on the monitor, nor do we want to duplicate the code.
To avoid this, move some code out of
qmp.candhmp.cadding new methods toqom/object_interfaces.c-
user_creatable_add- takes a QDict holding a full object definition & instantiates it
-user_creatable_add_type- takes an ID, type name, and QDict holding object properties & instantiates it
-user_creatable_add_opts- takes a QemuOpts holding a full object definition & instantiates it
-user_creatable_add_opts_foreach- variant onuser_creatable_add_optswhich can be directly used in conjunction withqemu_opts_foreach.
-user_creatable_del- takes an ID and deletes the corresponding objectThe existing code is updated to use these new methods.
Reviewed-by Eric Blake <[email protected]>Signed-off-by Daniel P. Berrange <[email protected]>--- hmp.c | 52 +++--------- include/monitor/monitor.h | 3 - include/qom/object_interfaces.h | 92 +++++++++++++++++++++ qmp.c | 76 ++---------------- qom/object_interfaces.c | 174 ++++++++++++++++++++++++++++++++++++++++ vl.c | 68 ++-------------- 6 files changed, 290 insertions(+), 175 deletions(-)hmp.c +11
-41@@ -30,6 +30,7 @@#include "qapi/string-output-visitor.h" #include "qapi/util.h" #include "qapi-visit.h" +#include "qom/object_interfaces.h" #include "ui/console.h" #include "block/qapi.h" #include "qemu-io.h" @@ -1655,58 +1656,27 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)void hmp_object_add (Monitor *mon,const QDict *qdict) {Error *err =NULL ; -Error *err_end =NULL ;QemuOpts *opts; -char *type =NULL ; -char *id =NULL ;OptsVisitor *ov; -QDict *pdict; -Visitor *v; +Object *obj =NULL ; opts =qemu_opts_from_qdict (qemu_find_opts ("object" ), qdict, &err);if (err) { - goto out; +hmp_handle_error (mon, &err); +return ; } ov =opts_visitor_new (opts); - pdict =qdict_clone_shallow (qdict); - v =opts_get_visitor (ov); - -visit_start_struct (v,NULL ,NULL ,0 , &err); -if (err) { - goto out_clean; - } - -qdict_del (pdict,"qom-type" ); -visit_type_str (v,"qom-type" , &type, &err); -if (err) { - goto out_end; - } + obj =user_creatable_add (qdict,opts_get_visitor (ov), &err); +opts_visitor_cleanup (ov); +qemu_opts_del (opts); -qdict_del (pdict,"id" ); -visit_type_str (v,"id" , &id, &err);if (err) { - goto out_end; +hmp_handle_error (mon, &err); } - -object_add (type, id, pdict, v, &err); - -out_end: -visit_end_struct (v, &err_end); -if (!err && err_end) { -qmp_object_del (id,NULL ); +if (obj) { +object_unref (obj); } -error_propagate (&err, err_end); -out_clean: -opts_visitor_cleanup (ov); - -QDECREF (pdict); -qemu_opts_del (opts); -g_free (id); -g_free (type); - -out: -hmp_handle_error (mon, &err); }void hmp_getfd (Monitor *mon,const QDict *qdict)@@ -1934,7 +1904,7 @@ void hmp_object_del(Monitor *mon, const QDict *qdict)const char *id =qdict_get_str (qdict,"id" );Error *err =NULL ; -qmp_object_del (id, &err); +user_creatable_del (id, &err);hmp_handle_error (mon, &err); }include/monitor/monitor.h +0
-3@@ -43,9 +43,6 @@ void monitor_read_command(Monitor *mon, int show_prompt);int monitor_read_password (Monitor *mon,ReadLineFunc *readline_func,void *opaque); -void object_add (const char *type,const char *id,const QDict *qdict, -Visitor *v,Error **errp); -AddfdInfo *monitor_fdset_add_fd (int fd,bool has_fdset_id,int64_t fdset_id,bool has_opaque,const char *opaque,Error **errp);include/qom/object_interfaces.h +92
-0@@ -2,6 +2,8 @@#define OBJECT_INTERFACES_H #include "qom/object.h" +#include "qapi/qmp/qdict.h" +#include "qapi/visitor.h" #define TYPE_USER_CREATABLE "user-creatable"@@ -72,4 +74,94 @@ void user_creatable_complete(Object *obj, Error **errp);* from implements USER_CREATABLE interface. */ bool user_creatable_can_be_deleted (UserCreatable *uc,Error **errp); + +/** +* user_creatable_add: +* @qdict: the object definition +* @v: the visitor +* @errp: if an error occurs, a pointer to an area to store the error +* +* Create an instance of the user creatable object whose type +* is defined in @qdict by the 'qom-type' field, placing it +* in the object composition tree with name provided by the +* 'id' field. The remaining fields in @qdict are used to +* initialize the object properties. +* +* Returns: the newly created object or NULL on error +*/ +Object *user_creatable_add (const QDict *qdict, +Visitor *v,Error **errp); + +/** +* user_creatable_add_type: +* @type: the object type name +* @id: the unique ID for the object +* @qdict: the object properties +* @v: the visitor +* @errp: if an error occurs, a pointer to an area to store the error +* +* Create an instance of the user creatable object @type, placing +* it in the object composition tree with name @id, initializing +* it with properties from @qdict +* +* Returns: the newly created object or NULL on error +*/ +Object *user_creatable_add_type (const char *type,const char *id, +const QDict *qdict, +Visitor *v,Error **errp); + +/** +* user_creatable_add_opts: +* @opts: the object definition +* @errp: if an error occurs, a pointer to an area to store the error +* +* Create an instance of the user creatable object whose type +* is defined in @opts by the 'qom-type' option, placing it +* in the object composition tree with name provided by the +* 'id' field. The remaining options in @opts are used to +* initialize the object properties. +* +* Returns: the newly created object or NULL on error +*/ +Object *user_creatable_add_opts (QemuOpts *opts,Error **errp); + + +/** +* user_creatable_add_opts_predicate: +* @type: the QOM type to be added +* +* A callback function to determine whether an object +* of type @type should be created. Instances of this +* callback should be passed to user_creatable_add_opts_foreach +*/ +typedef bool (*user_creatable_add_opts_predicate )(const char *type); + +/** +* user_creatable_add_opts_foreach: +* @opaque: a user_creatable_add_opts_predicate callback or NULL +* @opts: options to create +* @errp: if an error occurs, a pointer to an area to store the error +* +* An iterator callback to be used in conjunction with +* the qemu_opts_foreach() method for creating a list of +* objects from a set of QemuOpts +* +* The @opaque parameter can be passed a user_creatable_add_opts_predicate +* callback to filter which types of object are created during iteration. +* +* Returns: 0 on success, -1 on error +*/ +int user_creatable_add_opts_foreach (void *opaque, +QemuOpts *opts,Error **errp); + +/** +* user_creatable_del: +* @id: the unique ID for the object +* @errp: if an error occurs, a pointer to an area to store the error +* +* Delete an instance of the user creatable object identified +* by @id. +*/ +void user_creatable_del (const char *id,Error **errp); +#endif qmp.c +7
-69@@ -633,65 +633,13 @@ void qmp_add_client(const char *protocol, const char *fdname,close (fd); } -void object_add (const char *type,const char *id,const QDict *qdict, -Visitor *v,Error **errp) -{ -Object *obj; -ObjectClass *klass; -const QDictEntry *e; -Error *local_err =NULL ; - - klass =object_class_by_name (type); -if (!klass) { -error_setg (errp,"invalid object type: %s" , type); -return ; - } - -if (!object_class_dynamic_cast (klass,TYPE_USER_CREATABLE )) { -error_setg (errp,"object type '%s' isn't supported by object-add" , - type); -return ; - } - -if (object_class_is_abstract (klass)) { -error_setg (errp,"object type '%s' is abstract" , type); -return ; - } - - obj =object_new (type); -if (qdict) { -for (e =qdict_first (qdict); e; e =qdict_next (qdict, e)) { -object_property_set (obj, v, e->key, &local_err); -if (local_err) { - goto out; - } - } - } - -object_property_add_child (object_get_objects_root (), - id, obj, &local_err); -if (local_err) { - goto out; - } - -user_creatable_complete (obj, &local_err); -if (local_err) { -object_property_del (object_get_objects_root (), - id, &error_abort); - goto out; - } -out: -if (local_err) { -error_propagate (errp, local_err); - } -object_unref (obj); -}void qmp_object_add (const char *type,const char *id,bool has_props,QObject *props,Error **errp) {const QDict *pdict =NULL ;QmpInputVisitor *qiv; +Object *obj;if (props) { pdict =qobject_to_qdict (props);@@ -702,27 +650,17 @@ void qmp_object_add(const char *type, const char *id, } qiv =qmp_input_visitor_new (props); -object_add (type, id, pdict,qmp_input_get_visitor (qiv), errp); + obj =user_creatable_add_type (type, id, pdict, +qmp_input_get_visitor (qiv), errp);qmp_input_visitor_cleanup (qiv); +if (obj) { +object_unref (obj); + } }void qmp_object_del (const char *id,Error **errp) { -Object *container; -Object *obj; - - container =object_get_objects_root (); - obj =object_resolve_path_component (container, id); -if (!obj) { -error_setg (errp,"object id not found" ); -return ; - } - -if (!user_creatable_can_be_deleted (USER_CREATABLE (obj), errp)) { -error_setg (errp,"%s is in use, can not be deleted" , id); -return ; - } -object_unparent (obj); +user_creatable_del (id, errp); }MemoryDeviceInfoList *qmp_query_memory_devices (Error **errp)qom/object_interfaces.c +174
-0@@ -1,6 +1,9 @@#include "qemu/osdep.h" #include "qom/object_interfaces.h" #include "qemu/module.h" +#include "qapi-visit.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/opts-visitor.h" void user_creatable_complete (Object *obj,Error **errp) {@@ -31,6 +34,177 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp) } } + +Object *user_creatable_add (const QDict *qdict, +Visitor *v,Error **errp) +{ +char *type =NULL ; +char *id =NULL ; +Object *obj =NULL ; +Error *local_err =NULL , *end_err =NULL ; +QDict *pdict; + + pdict =qdict_clone_shallow (qdict); + +visit_start_struct (v,NULL ,NULL ,0 , &local_err); +if (local_err) { + goto out; + } + +qdict_del (pdict,"qom-type" ); +visit_type_str (v,"qom-type" , &type, &local_err); +if (local_err) { + goto out_visit; + } + +qdict_del (pdict,"id" ); +visit_type_str (v,"id" , &id, &local_err); +if (local_err) { + goto out_visit; + } + + obj =user_creatable_add_type (type, id, pdict, v, &local_err); +if (local_err) { + goto out_visit; + } + + out_visit: +visit_end_struct (v, &end_err); +if (end_err) { +error_propagate (&local_err, end_err); +if (obj) { +user_creatable_del (id,NULL ); + } + goto out; + } + +out: +QDECREF (pdict); +g_free (id); +g_free (type); +if (local_err) { +error_propagate (errp, local_err); +object_unref (obj); +return NULL ; + } +return obj; +} + + +Object *user_creatable_add_type (const char *type,const char *id, +const QDict *qdict, +Visitor *v,Error **errp) +{ +Object *obj; +ObjectClass *klass; +const QDictEntry *e; +Error *local_err =NULL ; + + klass =object_class_by_name (type); +if (!klass) { +error_setg (errp,"invalid object type: %s" , type); +return NULL ; + } + +if (!object_class_dynamic_cast (klass,TYPE_USER_CREATABLE )) { +error_setg (errp,"object type '%s' isn't supported by object-add" , + type); +return NULL ; + } + +if (object_class_is_abstract (klass)) { +error_setg (errp,"object type '%s' is abstract" , type); +return NULL ; + } + + obj =object_new (type); +if (qdict) { +for (e =qdict_first (qdict); e; e =qdict_next (qdict, e)) { +object_property_set (obj, v, e->key, &local_err); +if (local_err) { + goto out; + } + } + } + +object_property_add_child (object_get_objects_root (), + id, obj, &local_err); +if (local_err) { + goto out; + } + +user_creatable_complete (obj, &local_err); +if (local_err) { +object_property_del (object_get_objects_root (), + id, &error_abort); + goto out; + } +out: +if (local_err) { +error_propagate (errp, local_err); +object_unref (obj); +return NULL ; + } +return obj; +} + + +Object *user_creatable_add_opts (QemuOpts *opts,Error **errp) +{ +OptsVisitor *ov; +QDict *pdict; +Object *obj =NULL ; + + ov =opts_visitor_new (opts); + pdict =qemu_opts_to_qdict (opts,NULL ); + + obj =user_creatable_add (pdict,opts_get_visitor (ov), errp); +opts_visitor_cleanup (ov); +QDECREF (pdict); +return obj; +} + + +int user_creatable_add_opts_foreach (void *opaque,QemuOpts *opts,Error **errp) +{ +bool (*type_predicate)(const char *) = opaque; +Object *obj =NULL ; +const char *type; + + type =qemu_opt_get (opts,"qom-type" ); +if (type && type_predicate && + !type_predicate (type)) { +return 0 ; + } + + obj =user_creatable_add_opts (opts, errp); +if (!obj) { +return -1 ; + } +object_unref (obj); +return 0 ; +} + + +void user_creatable_del (const char *id,Error **errp) +{ +Object *container; +Object *obj; + + container =object_get_objects_root (); + obj =object_resolve_path_component (container, id); +if (!obj) { +error_setg (errp,"object '%s' not found" , id); +return ; + } + +if (!user_creatable_can_be_deleted (USER_CREATABLE (obj), errp)) { +error_setg (errp,"object '%s' is in use, can not be deleted" , id); +return ; + } +object_unparent (obj); +} +static void register_types (void ) {static const TypeInfo uc_interface_info = {vl.c +6
-62@@ -2816,64 +2816,6 @@ static bool object_create_delayed(const char *type) } -static int object_create (void *opaque,QemuOpts *opts,Error **errp) -{ -Error *err =NULL ; -Error *err_end =NULL ; -char *type =NULL ; -char *id =NULL ; -OptsVisitor *ov; -QDict *pdict; -bool (*type_predicate)(const char *) = opaque; -Visitor *v; - - ov =opts_visitor_new (opts); - pdict =qemu_opts_to_qdict (opts,NULL ); - v =opts_get_visitor (ov); - -visit_start_struct (v,NULL ,NULL ,0 , &err); -if (err) { - goto out; - } - -qdict_del (pdict,"qom-type" ); -visit_type_str (v,"qom-type" , &type, &err); -if (err) { - goto out; - } -if (!type_predicate (type)) { -visit_end_struct (v,NULL ); - goto out; - } - -qdict_del (pdict,"id" ); -visit_type_str (v,"id" , &id, &err); -if (err) { - goto out_end; - } - -object_add (type, id, pdict, v, &err); - -out_end: -visit_end_struct (v, &err_end); -if (!err && err_end) { -qmp_object_del (id,NULL ); - } -error_propagate (&err, err_end); - -out: -opts_visitor_cleanup (ov); - -QDECREF (pdict); -g_free (id); -g_free (type); -if (err) { -error_report_err (err); -return -1 ; - } -return 0 ; -} -static void set_memory_options (uint64_t *ram_slots,ram_addr_t *maxram_size,MachineClass *mc) {@@ -4299,8 +4241,9 @@ int main(int argc, char **argv, char **envp)socket_init ();if (qemu_opts_foreach (qemu_find_opts ("object" ), - object_create, - object_create_initial,NULL )) { + user_creatable_add_opts_foreach, + object_create_initial, &err)) { +error_report_err (err);exit (1 ); }@@ -4417,8 +4360,9 @@ int main(int argc, char **argv, char **envp) }if (qemu_opts_foreach (qemu_find_opts ("object" ), - object_create, - object_create_delayed,NULL )) { + user_creatable_add_opts_foreach, + object_create_delayed, &err)) { +error_report_err (err);exit (1 ); }
Re: [Qemu-devel] [PATCH v6 01/10] qom: add helpers for UserCreatable object types
Quoted 8 lines · Markus Armbruster
This commit regresses error message quality from
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundto just
qemu-system-x86_64: Property '.foo' not found
I'm not seeing that behaviour myself in current git master, nor immediately before or after 90998d58964cd17f8b0b03800b0a4508f8b543da is applied. I always just get
$ ./x86_64-softmmu/qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not found
So it all appears to be working correctly. How reliably reproducable is it for you ? I'm testing on Fedora 23 x86_64 host and can't see the failure despite many invokations.
Quoted 8 lines
Clue:
cur_locpoints to garbage.(gdb) p cur_loc $1 = (Location *) 0x7fffffffdc10 (gdb) p *cur_loc $2 = {kind = (unknown: 4294958128), num = 32767, ptr = 0x555555b804a2 <error_report_err+44>, prev = 0x5555565d2770 <std_loc>}
Quoted 4 lines
Looks like
cur_locis dangling. Happens when you forget toloc_pop()a Location before it dies. This one is on the stack.*Might* be release critical.
This patch doesn't even touch any code which calls loc_push/loc_pop so I'm kind of surprised if this patch breaks it. Given that it looks like stack corruption though, I wonder if this commit has just exposed an already latent non-deterministic bug for you ? IOW root cause could be an earlier patch ?
Quoted 648 lines
For comparison, this is how it looks before the patch:
(gdb) p cur_loc $1 = (Location *) 0x7fffffffdc10 (gdb) p *cur_loc $2 = {kind = LOC_CMDLINE, num = 2, ptr = 0x7fffffffe018, prev = 0x5555565d2770 <std_loc>}Reported-by Eric Blake <[email protected]>Quoted 633 lines · Daniel P. Berrange
The QMP monitor code has two helper methods
object_addandqmp_object_delthat are called from several places in the code (QMP, HMP and main emulator startup).The HMP and main emulator startup code also share further logic that extracts the qom-type & id values from a qdict.
We soon need to use this logic from qemu-img, qemu-io and qemu-nbd too, but don't want those to depend on the monitor, nor do we want to duplicate the code.
To avoid this, move some code out of
qmp.candhmp.cadding new methods toqom/object_interfaces.c-
user_creatable_add- takes a QDict holding a full object definition & instantiates it
-user_creatable_add_type- takes an ID, type name, and QDict holding object properties & instantiates it
-user_creatable_add_opts- takes a QemuOpts holding a full object definition & instantiates it
-user_creatable_add_opts_foreach- variant onuser_creatable_add_optswhich can be directly used in conjunction withqemu_opts_foreach.
-user_creatable_del- takes an ID and deletes the corresponding objectThe existing code is updated to use these new methods.
Reviewed-by Eric Blake <[email protected]>Signed-off-by Daniel P. Berrange <[email protected]>--- hmp.c | 52 +++--------- include/monitor/monitor.h | 3 - include/qom/object_interfaces.h | 92 +++++++++++++++++++++ qmp.c | 76 ++---------------- qom/object_interfaces.c | 174 ++++++++++++++++++++++++++++++++++++++++ vl.c | 68 ++-------------- 6 files changed, 290 insertions(+), 175 deletions(-)hmp.c +11
-41@@ -30,6 +30,7 @@#include "qapi/string-output-visitor.h" #include "qapi/util.h" #include "qapi-visit.h" +#include "qom/object_interfaces.h" #include "ui/console.h" #include "block/qapi.h" #include "qemu-io.h" @@ -1655,58 +1656,27 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)void hmp_object_add (Monitor *mon,const QDict *qdict) {Error *err =NULL ; -Error *err_end =NULL ;QemuOpts *opts; -char *type =NULL ; -char *id =NULL ;OptsVisitor *ov; -QDict *pdict; -Visitor *v; +Object *obj =NULL ; opts =qemu_opts_from_qdict (qemu_find_opts ("object" ), qdict, &err);if (err) { - goto out; +hmp_handle_error (mon, &err); +return ; } ov =opts_visitor_new (opts); - pdict =qdict_clone_shallow (qdict); - v =opts_get_visitor (ov); - -visit_start_struct (v,NULL ,NULL ,0 , &err); -if (err) { - goto out_clean; - } - -qdict_del (pdict,"qom-type" ); -visit_type_str (v,"qom-type" , &type, &err); -if (err) { - goto out_end; - } + obj =user_creatable_add (qdict,opts_get_visitor (ov), &err); +opts_visitor_cleanup (ov); +qemu_opts_del (opts); -qdict_del (pdict,"id" ); -visit_type_str (v,"id" , &id, &err);if (err) { - goto out_end; +hmp_handle_error (mon, &err); } - -object_add (type, id, pdict, v, &err); - -out_end: -visit_end_struct (v, &err_end); -if (!err && err_end) { -qmp_object_del (id,NULL ); +if (obj) { +object_unref (obj); } -error_propagate (&err, err_end); -out_clean: -opts_visitor_cleanup (ov); - -QDECREF (pdict); -qemu_opts_del (opts); -g_free (id); -g_free (type); - -out: -hmp_handle_error (mon, &err); }void hmp_getfd (Monitor *mon,const QDict *qdict)@@ -1934,7 +1904,7 @@ void hmp_object_del(Monitor *mon, const QDict *qdict)const char *id =qdict_get_str (qdict,"id" );Error *err =NULL ; -qmp_object_del (id, &err); +user_creatable_del (id, &err);hmp_handle_error (mon, &err); }include/monitor/monitor.h +0
-3@@ -43,9 +43,6 @@ void monitor_read_command(Monitor *mon, int show_prompt);int monitor_read_password (Monitor *mon,ReadLineFunc *readline_func,void *opaque); -void object_add (const char *type,const char *id,const QDict *qdict, -Visitor *v,Error **errp); -AddfdInfo *monitor_fdset_add_fd (int fd,bool has_fdset_id,int64_t fdset_id,bool has_opaque,const char *opaque,Error **errp);include/qom/object_interfaces.h +92
-0@@ -2,6 +2,8 @@#define OBJECT_INTERFACES_H #include "qom/object.h" +#include "qapi/qmp/qdict.h" +#include "qapi/visitor.h" #define TYPE_USER_CREATABLE "user-creatable"@@ -72,4 +74,94 @@ void user_creatable_complete(Object *obj, Error **errp);* from implements USER_CREATABLE interface. */ bool user_creatable_can_be_deleted (UserCreatable *uc,Error **errp); + +/** +* user_creatable_add: +* @qdict: the object definition +* @v: the visitor +* @errp: if an error occurs, a pointer to an area to store the error +* +* Create an instance of the user creatable object whose type +* is defined in @qdict by the 'qom-type' field, placing it +* in the object composition tree with name provided by the +* 'id' field. The remaining fields in @qdict are used to +* initialize the object properties. +* +* Returns: the newly created object or NULL on error +*/ +Object *user_creatable_add (const QDict *qdict, +Visitor *v,Error **errp); + +/** +* user_creatable_add_type: +* @type: the object type name +* @id: the unique ID for the object +* @qdict: the object properties +* @v: the visitor +* @errp: if an error occurs, a pointer to an area to store the error +* +* Create an instance of the user creatable object @type, placing +* it in the object composition tree with name @id, initializing +* it with properties from @qdict +* +* Returns: the newly created object or NULL on error +*/ +Object *user_creatable_add_type (const char *type,const char *id, +const QDict *qdict, +Visitor *v,Error **errp); + +/** +* user_creatable_add_opts: +* @opts: the object definition +* @errp: if an error occurs, a pointer to an area to store the error +* +* Create an instance of the user creatable object whose type +* is defined in @opts by the 'qom-type' option, placing it +* in the object composition tree with name provided by the +* 'id' field. The remaining options in @opts are used to +* initialize the object properties. +* +* Returns: the newly created object or NULL on error +*/ +Object *user_creatable_add_opts (QemuOpts *opts,Error **errp); + + +/** +* user_creatable_add_opts_predicate: +* @type: the QOM type to be added +* +* A callback function to determine whether an object +* of type @type should be created. Instances of this +* callback should be passed to user_creatable_add_opts_foreach +*/ +typedef bool (*user_creatable_add_opts_predicate )(const char *type); + +/** +* user_creatable_add_opts_foreach: +* @opaque: a user_creatable_add_opts_predicate callback or NULL +* @opts: options to create +* @errp: if an error occurs, a pointer to an area to store the error +* +* An iterator callback to be used in conjunction with +* the qemu_opts_foreach() method for creating a list of +* objects from a set of QemuOpts +* +* The @opaque parameter can be passed a user_creatable_add_opts_predicate +* callback to filter which types of object are created during iteration. +* +* Returns: 0 on success, -1 on error +*/ +int user_creatable_add_opts_foreach (void *opaque, +QemuOpts *opts,Error **errp); + +/** +* user_creatable_del: +* @id: the unique ID for the object +* @errp: if an error occurs, a pointer to an area to store the error +* +* Delete an instance of the user creatable object identified +* by @id. +*/ +void user_creatable_del (const char *id,Error **errp); +#endif qmp.c +7
-69@@ -633,65 +633,13 @@ void qmp_add_client(const char *protocol, const char *fdname,close (fd); } -void object_add (const char *type,const char *id,const QDict *qdict, -Visitor *v,Error **errp) -{ -Object *obj; -ObjectClass *klass; -const QDictEntry *e; -Error *local_err =NULL ; - - klass =object_class_by_name (type); -if (!klass) { -error_setg (errp,"invalid object type: %s" , type); -return ; - } - -if (!object_class_dynamic_cast (klass,TYPE_USER_CREATABLE )) { -error_setg (errp,"object type '%s' isn't supported by object-add" , - type); -return ; - } - -if (object_class_is_abstract (klass)) { -error_setg (errp,"object type '%s' is abstract" , type); -return ; - } - - obj =object_new (type); -if (qdict) { -for (e =qdict_first (qdict); e; e =qdict_next (qdict, e)) { -object_property_set (obj, v, e->key, &local_err); -if (local_err) { - goto out; - } - } - } - -object_property_add_child (object_get_objects_root (), - id, obj, &local_err); -if (local_err) { - goto out; - } - -user_creatable_complete (obj, &local_err); -if (local_err) { -object_property_del (object_get_objects_root (), - id, &error_abort); - goto out; - } -out: -if (local_err) { -error_propagate (errp, local_err); - } -object_unref (obj); -}void qmp_object_add (const char *type,const char *id,bool has_props,QObject *props,Error **errp) {const QDict *pdict =NULL ;QmpInputVisitor *qiv; +Object *obj;if (props) { pdict =qobject_to_qdict (props);@@ -702,27 +650,17 @@ void qmp_object_add(const char *type, const char *id, } qiv =qmp_input_visitor_new (props); -object_add (type, id, pdict,qmp_input_get_visitor (qiv), errp); + obj =user_creatable_add_type (type, id, pdict, +qmp_input_get_visitor (qiv), errp);qmp_input_visitor_cleanup (qiv); +if (obj) { +object_unref (obj); + } }void qmp_object_del (const char *id,Error **errp) { -Object *container; -Object *obj; - - container =object_get_objects_root (); - obj =object_resolve_path_component (container, id); -if (!obj) { -error_setg (errp,"object id not found" ); -return ; - } - -if (!user_creatable_can_be_deleted (USER_CREATABLE (obj), errp)) { -error_setg (errp,"%s is in use, can not be deleted" , id); -return ; - } -object_unparent (obj); +user_creatable_del (id, errp); }MemoryDeviceInfoList *qmp_query_memory_devices (Error **errp)qom/object_interfaces.c +174
-0@@ -1,6 +1,9 @@#include "qemu/osdep.h" #include "qom/object_interfaces.h" #include "qemu/module.h" +#include "qapi-visit.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/opts-visitor.h" void user_creatable_complete (Object *obj,Error **errp) {@@ -31,6 +34,177 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp) } } + +Object *user_creatable_add (const QDict *qdict, +Visitor *v,Error **errp) +{ +char *type =NULL ; +char *id =NULL ; +Object *obj =NULL ; +Error *local_err =NULL , *end_err =NULL ; +QDict *pdict; + + pdict =qdict_clone_shallow (qdict); + +visit_start_struct (v,NULL ,NULL ,0 , &local_err); +if (local_err) { + goto out; + } + +qdict_del (pdict,"qom-type" ); +visit_type_str (v,"qom-type" , &type, &local_err); +if (local_err) { + goto out_visit; + } + +qdict_del (pdict,"id" ); +visit_type_str (v,"id" , &id, &local_err); +if (local_err) { + goto out_visit; + } + + obj =user_creatable_add_type (type, id, pdict, v, &local_err); +if (local_err) { + goto out_visit; + } + + out_visit: +visit_end_struct (v, &end_err); +if (end_err) { +error_propagate (&local_err, end_err); +if (obj) { +user_creatable_del (id,NULL ); + } + goto out; + } + +out: +QDECREF (pdict); +g_free (id); +g_free (type); +if (local_err) { +error_propagate (errp, local_err); +object_unref (obj); +return NULL ; + } +return obj; +} + + +Object *user_creatable_add_type (const char *type,const char *id, +const QDict *qdict, +Visitor *v,Error **errp) +{ +Object *obj; +ObjectClass *klass; +const QDictEntry *e; +Error *local_err =NULL ; + + klass =object_class_by_name (type); +if (!klass) { +error_setg (errp,"invalid object type: %s" , type); +return NULL ; + } + +if (!object_class_dynamic_cast (klass,TYPE_USER_CREATABLE )) { +error_setg (errp,"object type '%s' isn't supported by object-add" , + type); +return NULL ; + } + +if (object_class_is_abstract (klass)) { +error_setg (errp,"object type '%s' is abstract" , type); +return NULL ; + } + + obj =object_new (type); +if (qdict) { +for (e =qdict_first (qdict); e; e =qdict_next (qdict, e)) { +object_property_set (obj, v, e->key, &local_err); +if (local_err) { + goto out; + } + } + } + +object_property_add_child (object_get_objects_root (), + id, obj, &local_err); +if (local_err) { + goto out; + } + +user_creatable_complete (obj, &local_err); +if (local_err) { +object_property_del (object_get_objects_root (), + id, &error_abort); + goto out; + } +out: +if (local_err) { +error_propagate (errp, local_err); +object_unref (obj); +return NULL ; + } +return obj; +} + + +Object *user_creatable_add_opts (QemuOpts *opts,Error **errp) +{ +OptsVisitor *ov; +QDict *pdict; +Object *obj =NULL ; + + ov =opts_visitor_new (opts); + pdict =qemu_opts_to_qdict (opts,NULL ); + + obj =user_creatable_add (pdict,opts_get_visitor (ov), errp); +opts_visitor_cleanup (ov); +QDECREF (pdict); +return obj; +} + + +int user_creatable_add_opts_foreach (void *opaque,QemuOpts *opts,Error **errp) +{ +bool (*type_predicate)(const char *) = opaque; +Object *obj =NULL ; +const char *type; + + type =qemu_opt_get (opts,"qom-type" ); +if (type && type_predicate && + !type_predicate (type)) { +return 0 ; + } + + obj =user_creatable_add_opts (opts, errp); +if (!obj) { +return -1 ; + } +object_unref (obj); +return 0 ; +} + + +void user_creatable_del (const char *id,Error **errp) +{ +Object *container; +Object *obj; + + container =object_get_objects_root (); + obj =object_resolve_path_component (container, id); +if (!obj) { +error_setg (errp,"object '%s' not found" , id); +return ; + } + +if (!user_creatable_can_be_deleted (USER_CREATABLE (obj), errp)) { +error_setg (errp,"object '%s' is in use, can not be deleted" , id); +return ; + } +object_unparent (obj); +} +static void register_types (void ) {static const TypeInfo uc_interface_info = {vl.c +3
-60@@ -2816,64 +2816,6 @@ static bool object_create_delayed(const char *type) } -static int object_create (void *opaque,QemuOpts *opts,Error **errp) -{ -Error *err =NULL ; -Error *err_end =NULL ; -char *type =NULL ; -char *id =NULL ; -OptsVisitor *ov; -QDict *pdict; -bool (*type_predicate)(const char *) = opaque; -Visitor *v; - - ov =opts_visitor_new (opts); - pdict =qemu_opts_to_qdict (opts,NULL ); - v =opts_get_visitor (ov); - -visit_start_struct (v,NULL ,NULL ,0 , &err); -if (err) { - goto out; - } - -qdict_del (pdict,"qom-type" ); -visit_type_str (v,"qom-type" , &type, &err); -if (err) { - goto out; - } -if (!type_predicate (type)) { -visit_end_struct (v,NULL ); - goto out; - } - -qdict_del (pdict,"id" ); -visit_type_str (v,"id" , &id, &err); -if (err) { - goto out_end; - } - -object_add (type, id, pdict, v, &err); - -out_end: -visit_end_struct (v, &err_end); -if (!err && err_end) { -qmp_object_del (id,NULL ); - } -error_propagate (&err, err_end); - -out: -opts_visitor_cleanup (ov); - -QDECREF (pdict); -g_free (id); -g_free (type); -if (err) { -error_report_err (err); -return -1 ; - } -return 0 ; -} -static void set_memory_options (uint64_t *ram_slots,ram_addr_t *maxram_size,MachineClass *mc) {@@ -4299,8 +4241,9 @@ int main(int argc, char **argv, char **envp)socket_init ();if (qemu_opts_foreach (qemu_find_opts ("object" ), - object_create, - object_create_initial,NULL )) { + user_creatable_add_opts_foreach, + object_create_initial, &err)) { +error_report_err (err);exit (1 ); }@@ -4417,8 +4360,9 @@ int main(int argc, char **argv, char **envp) }
Quoted 8 lines
vl.c int main(int argc, char **argv, char **envp) · line 4367
Quoted 8 lines
vl.c +3
-2if (qemu_opts_foreach (qemu_find_opts ("object" ), - object_create, - object_create_delayed,NULL )) { + user_creatable_add_opts_foreach, + object_create_delayed, &err)) { +error_report_err (err);exit (1 ); }
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Re: [Qemu-devel] [PATCH v6 01/10] qom: add helpers for UserCreatable object types
Quoted 14 lines · Daniel P. Berrange
Quoted 8 lines · Markus Armbruster
This commit regresses error message quality from
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundto just
qemu-system-x86_64: Property '.foo' not found
I'm not seeing that behaviour myself in current git master, nor immediately before or after
90998d58964cd17f8b0b03800b0a4508f8b543dais applied. I always just get
Quoted 6 lines
$ ./x86_64-softmmu/qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundSo it all appears to be working correctly. How reliably reproducable is it for you ? I'm testing on Fedora 23
x86_64host and can't see the failure despite many invokations.
I'm reproducing it on my F23 machine, where 90998d58 indeed flips the behavior I'm seeing. Maybe it's a factor of which malloc engine is in use, or level of compiler optimization?
My config.status states:
exec '/home/eblake/qemu/configure' '--enable-kvm' '--enable-system' '--disable-user' '--target-list=x86_64-softmmu,ppc64-softmmu' '--enable-debug'
Quoted 12 lines
Quoted 12 lines
Clue:
cur_locpoints to garbage.(gdb) p cur_loc $1 = (Location *) 0x7fffffffdc10 (gdb) p *cur_loc $2 = {kind = (unknown: 4294958128), num = 32767, ptr = 0x555555b804a2 <error_report_err+44>, prev = 0x5555565d2770 <std_loc>}Looks like
cur_locis dangling. Happens when you forget toloc_pop()a Location before it dies. This one is on the stack.
Quoted 7 lines
Quoted 1 line
*Might* be release critical.
This patch doesn't even touch any code which calls loc_push/loc_pop so I'm kind of surprised if this patch breaks it. Given that it looks like stack corruption though, I wonder if this commit has just exposed an already latent non-deterministic bug for you ? IOW root cause could be an earlier patch ?
Could it be a latent bug in qemu_opts_foreach()? Your patch changes a call from qemu_opts_foreach(object_create) to qemu_opts_foreach(user_creatable_add_opts_foreach), where the new callback may expose different behavior to the stack and thus expose the latent problem.
Quoted 15 lines
Quoted 11 lines
vl.c int main(int argc, char **argv, char **envp) · line 4367
Quoted 11 lines
vl.c +3
-2@@ -4417,8 +4360,9 @@ int main(int argc, char **argv, char **envp) }if (qemu_opts_foreach (qemu_find_opts ("object" ), - object_create, - object_create_delayed,NULL )) { + user_creatable_add_opts_foreach, + object_create_delayed, &err)) { +error_report_err (err);exit (1 ); }Regards,
Daniel
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH v6 01/10] qom: add helpers for UserCreatable object types
Quoted 22 lines · Eric Blake
Quoted 14 lines · Daniel P. Berrange
Quoted 8 lines · Markus Armbruster
This commit regresses error message quality from
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundto just
qemu-system-x86_64: Property '.foo' not found
I'm not seeing that behaviour myself in current git master, nor immediately before or after
90998d58964cd17f8b0b03800b0a4508f8b543dais applied. I always just getQuoted 6 lines
$ ./x86_64-softmmu/qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundSo it all appears to be working correctly. How reliably reproducable is it for you ? I'm testing on Fedora 23
x86_64host and can't see the failure despite many invokations.
Quoted 8 lines
I'm reproducing it on my F23 machine, where
90998d58indeed flips the behavior I'm seeing. Maybe it's a factor of which malloc engine is in use, or level of compiler optimization?My config.status states:
exec '/home/eblake/qemu/configure' '--enable-kvm' '--enable-system' '--disable-user' '--target-list=x86_64-softmmu,ppc64-softmmu' '--enable-debug'
For the record, the --enable-debug flag was the key to making this bug reproducable
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Re: [Qemu-devel] [PATCH v6 01/10] qom: add helpers for UserCreatable object types
In reply to Markus ArmbrusterQuoted 24 lines · Markus Armbruster
This commit regresses error message quality from
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=sec0,data=letmein,format=raw,foo=bar qemu-system-x86_64: -object secret,id=sec0,data=letmein,format=raw,foo=bar: Property '.foo' not foundto just
qemu-system-x86_64: Property '.foo' not found
Clue:
cur_locpoints to garbage.(gdb) p cur_loc $1 = (Location *) 0x7fffffffdc10 (gdb) p *cur_loc $2 = {kind = (unknown: 4294958128), num = 32767, ptr = 0x555555b804a2 <error_report_err+44>, prev = 0x5555565d2770 <std_loc>}Looks like
cur_locis dangling. Happens when you forget toloc_pop()a Location before it dies. This one is on the stack.*Might* be release critical.
For comparison, this is how it looks before the patch:
Quoted 7 lines
(gdb) p cur_loc $1 = (Location *) 0x7fffffffdc10 (gdb) p *cur_loc $2 = {kind = LOC_CMDLINE, num = 2, ptr = 0x7fffffffe018, prev = 0x5555565d2770 <std_loc>}Reported-by Eric Blake <[email protected]>
I think I nailed it. Preparing patches...
PATCH v6 2/10 qemu-io: add support for --object command line arg
In reply to Daniel P. BerrangeAllow creation of user creatable object types with qemu-io via a new --object command line arg. This will be used to supply passwords and/or encryption keys to the various block driver backends via the recently added 'secret' object type.
# printf letmein > mypasswd.txt
# qemu-io --object secret,id=sec0,file=mypasswd.txt \
...other args...--- qemu-io.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
qemu-io.c +35 -0
@@ -18,6 +18,7 @@#include "qemu/config-file.h" #include "qemu/readline.h" #include "qapi/qmp/qstring.h" +#include "qom/object_interfaces.h" #include "sysemu/block-backend.h" #include "block/block_int.h" #include "trace/control.h"
@@ -200,6 +201,8 @@ static void usage(const char *name)"Usage: %s [-h] [-V] [-rsnm] [-f FMT] [-c STRING] ... [file]\n" "QEMU Disk exerciser\n" "\n" +" --object OBJECTDEF define an object such as 'secret' for\n" +" passwords and/or encryption keys\n" " -c, --cmd STRING execute command with its arguments\n" " from the given string\n" " -f, --format FMT specifies the block driver to use\n"
@@ -361,6 +364,20 @@ static void reenable_tty_echo(void)qemu_set_tty_echo (STDIN_FILENO , true); } +enum { +OPTION_OBJECT =256 , +}; + +static QemuOptsList qemu_object_opts = { + .name ="object" , + .implied_opt_name ="qom-type" , + .head =QTAILQ_HEAD_INITIALIZER (qemu_object_opts.head), + .desc = { + { } + }, +}; + +int main (int argc,char **argv) {int readonly =0 ;
@@ -379,6 +396,7 @@ int main(int argc, char **argv) { "discard", 1, NULL, 'd' }, { "cache", 1, NULL, 't' }, { "trace", 1, NULL, 'T' }, + { "object", 1, NULL, OPTION_OBJECT }, { NULL, 0, NULL, 0 } };int c;
@@ -394,6 +412,8 @@ int main(int argc, char **argv) progname =basename (argv[0 ]);qemu_init_exec_dir (argv[0 ]); +module_call_init (MODULE_INIT_QOM ); +qemu_add_opts (&qemu_object_opts);bdrv_init ();while ((c =getopt_long (argc, argv, sopt, lopt, &opt_index)) !=-1 ) {
@@ -445,6 +465,14 @@ int main(int argc, char **argv)case 'h' :usage (progname);exit (0 ); +case OPTION_OBJECT : { +QemuOpts *qopts =NULL ; + qopts =qemu_opts_parse_noisily (&qemu_object_opts, + optarg, true); +if (!qopts) { +exit (1 ); + } + }break ;default :usage (progname);exit (1 );
@@ -461,6 +489,13 @@ int main(int argc, char **argv)exit (1 ); } +if (qemu_opts_foreach (&qemu_object_opts, + user_creatable_add_opts_foreach, +NULL , &local_error)) { +error_report_err (local_error); +exit (1 ); + } +/* initialize commands */ qemuio_add_command (&quit_cmd);qemuio_add_command (&open_cmd);
Signature · 1 line
2.5.0
PATCH v6 3/10 qemu-nbd: add support for --object command line arg
In reply to Daniel P. BerrangeAllow creation of user creatable object types with qemu-nbd via a new --object command line arg. This will be used to supply passwords and/or encryption keys to the various block driver backends via the recently added 'secret' object type.
# printf letmein > mypasswd.txt
# qemu-nbd --object secret,id=sec0,file=mypasswd.txt \
...other nbd args...--- qemu-nbd.c | 34 ++++++++++++++++++++++++++++++++++ qemu-nbd.texi | 6 ++++++ 2 files changed, 40 insertions(+)
qemu-nbd.c +34 -0
@@ -24,9 +24,11 @@#include "qemu/main-loop.h" #include "qemu/sockets.h" #include "qemu/error-report.h" +#include "qemu/config-file.h" #include "block/snapshot.h" #include "qapi/util.h" #include "qapi/qmp/qstring.h" +#include "qom/object_interfaces.h" #include <getopt.h> #include <sys/socket.h>
@@ -41,6 +43,7 @@#define QEMU_NBD_OPT_AIO 2#define QEMU_NBD_OPT_DISCARD 3#define QEMU_NBD_OPT_DETECT_ZEROES 4 +#define QEMU_NBD_OPT_OBJECT 5static NBDExport *exp;static int verbose;
@@ -74,6 +77,9 @@ static void usage(const char *name)" -o, --offset=OFFSET offset into the image\n" " -P, --partition=NUM only expose partition NUM\n" "\n" +"General purpose options:\n" +" --object type,id=ID,... define an object such as 'secret' for providing\n" +" passwords and/or encryption keys\n" #ifdef __linux__"Kernel NBD client support:\n" " -c, --connect=DEV connect FILE to the local NBD device DEV\n"
@@ -371,6 +377,16 @@ static SocketAddress *nbd_build_socket_address(const char *sockpath, } +static QemuOptsList qemu_object_opts = { + .name ="object" , + .implied_opt_name ="qom-type" , + .head =QTAILQ_HEAD_INITIALIZER (qemu_object_opts.head), + .desc = { + { } + }, +}; + +int main (int argc,char **argv) {BlockBackend *blk;
@@ -408,6 +424,7 @@ int main(int argc, char **argv) { "format", 1, NULL, 'f' }, { "persistent", 0, NULL, 't' }, { "verbose", 0, NULL, 'v' }, + { "object", 1, NULL, QEMU_NBD_OPT_OBJECT }, { NULL, 0, NULL, 0 } };int ch;
@@ -433,6 +450,8 @@ int main(int argc, char **argv)memset (&sa_sigterm,0 ,sizeof (sa_sigterm)); sa_sigterm.sa_handler = termsig_handler;sigaction (SIGTERM , &sa_sigterm,NULL ); +module_call_init (MODULE_INIT_QOM ); +qemu_add_opts (&qemu_object_opts);qemu_init_exec_dir (argv[0 ]);while ((ch =getopt_long (argc, argv, sopt, lopt, &opt_ind)) !=-1 ) {
@@ -588,6 +607,14 @@ int main(int argc, char **argv)case '?' :error_report ("Try `%s --help' for more information." , argv[0 ]);exit (EXIT_FAILURE ); +case QEMU_NBD_OPT_OBJECT : { +QemuOpts *opts; + opts =qemu_opts_parse_noisily (&qemu_object_opts, + optarg, true); +if (!opts) { +exit (EXIT_FAILURE ); + } + }break ; } }
@@ -597,6 +624,13 @@ int main(int argc, char **argv)exit (EXIT_FAILURE ); } +if (qemu_opts_foreach (&qemu_object_opts, + user_creatable_add_opts_foreach, +NULL , &local_err)) { +error_report_err (local_err); +exit (EXIT_FAILURE ); + } +if (disconnect) { fd =open (argv[optind],O_RDWR );if (fd <0 ) {
qemu-nbd.texi +6 -0
@@ -18,6 +18,12 @@ Export a QEMU disk image using the NBD protocol. @var{dev} is an NBD device. @table @option +@item --object type,id=@var{id},...props... +Define a new instance of the @var{type} object class identified by @var{id}. +See the @code{qemu(1)} manual page for full details of the properties +supported. The common object type that it makes sense to define is the +@code{secret} object, which is used to supply passwords and/or encryption +keys. @item -p, --port=@var{port} The TCP port to listen on (default @samp{10809}) @item -o, --offset=@var{offset}
Signature · 1 line
2.5.0
PATCH v6 4/10 qemu-img: add support for --object command line arg
In reply to Daniel P. BerrangeAllow creation of user creatable object types with qemu-img via a new --object command line arg. This will be used to supply passwords and/or encryption keys to the various block driver backends via the recently added 'secret' object type.
# printf letmein > mypasswd.txt
# qemu-img info --object secret,id=sec0,file=mypasswd.txt \
...other info args...--- qemu-img-cmds.hx | 44 +++++----- qemu-img.c | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- qemu-img.texi | 8 ++ 3 files changed, 283 insertions(+), 30 deletions(-)
qemu-img-cmds.hx +22 -22
@@ -10,68 +10,68 @@ STEXI ETEXI DEF("check", img_check, - "check [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename") + "check [-q] [--object objectdef] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename") STEXI -@item check [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename} +@item check [--object @var{objectdef}] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename} ETEXI DEF("create", img_create, - "create [-q] [-f fmt] [-o options] filename [size]") + "create [-q] [--object objectdef] [-f fmt] [-o options] filename [size]") STEXI -@item create [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] +@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] ETEXI DEF("commit", img_commit, - "commit [-q] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") + "commit [-q] [--object objectdef] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") STEXI -@item commit [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename} +@item commit [--object @var{objectdef}] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename} ETEXI DEF("compare", img_compare, - "compare [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2") + "compare [--object objectdef] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2") STEXI -@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2} +@item compare [--object @var{objectdef}] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2} ETEXI DEF("convert", img_convert, - "convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename") + "convert [--object objectdef] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename") STEXI -@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [--object @var{objectdef}] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ETEXI DEF("info", img_info, - "info [-f fmt] [--output=ofmt] [--backing-chain] filename") + "info [--object objectdef] [-f fmt] [--output=ofmt] [--backing-chain] filename") STEXI -@item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} +@item info [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} ETEXI DEF("map", img_map, - "map [-f fmt] [--output=ofmt] filename") + "map [--object objectdef] [-f fmt] [--output=ofmt] filename") STEXI -@item map [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} +@item map [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} ETEXI DEF("snapshot", img_snapshot, - "snapshot [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") + "snapshot [--object objectdef] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") STEXI -@item snapshot [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} +@item snapshot [--object @var{objectdef}] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} ETEXI DEF("rebase", img_rebase, - "rebase [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") + "rebase [--object objectdef] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") STEXI -@item rebase [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} +@item rebase [--object @var{objectdef}] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} ETEXI DEF("resize", img_resize, - "resize [-q] filename [+ | -]size") + "resize [--object objectdef] [-q] filename [+ | -]size") STEXI -@item resize [-q] @var{filename} [+ | -]@var{size} +@item resize [--object @var{objectdef}] [-q] @var{filename} [+ | -]@var{size} ETEXI DEF("amend", img_amend, - "amend [-p] [-q] [-f fmt] [-t cache] -o options filename") + "amend [--object objectdef] [-p] [-q] [-f fmt] [-t cache] -o options filename") STEXI -@item amend [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} +@item amend [--object @var{objectdef}] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} @end table ETEXI
qemu-img.c +253 -8
530 lines not on this page · raw message
qemu-img.texi +8 -0
@@ -24,6 +24,14 @@ Command parameters: @table @var @item filename is a disk image filename + +@item --object @var{objectdef} + +is a QEMU user creatable object definition. See the @code{qemu(1)} manual +page for a description of the object properties. The most common object +type is a @code{secret}, which is used to supply passwords and/or encryption +keys. + @item fmt is the disk image format. It is guessed automatically in most cases. See below for a description of the supported disk formats.
Signature · 1 line
2.5.0
PATCH v6 5/10 qemu-io: allow specifying image as a set of options args
In reply to Daniel P. BerrangeCurrently qemu-io allows an image filename to be passed on the command line, but unless using the JSON format, it does not have a way to set any options except the format eg
qemu-io https://127.0.0.1/images/centos7.iso
qemu-io /home/berrange/demo.qcow2
By contrast when using the interactive shell, it is possible to use --option with the 'open' command, or to omit the filename.
This adds a --image-opts arg that indicates that the positional filename should be interpreted as a full option string, not just a filename.
qemu-io --image-opts driver=https,url=https://127.0.0.1/images,sslverify=off qemu-io --image-opts driver=qcow2,file.filename=/home/berrange/demo.qcow2
This flag is mutually exclusive with the '-f' flag and with the '-o' flag to the 'open' command
--- qemu-io.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-)
qemu-io.c +51 -6
@@ -32,6 +32,7 @@ static BlockBackend *qemuio_blk;/* qemu-io commands passed using -c */ static int ncmdline;static char **cmdline; +static bool imageOpts;static ReadLineState *readline_state;
@@ -151,6 +152,10 @@ static int open_f(BlockBackend *blk, int argc, char **argv) readonly =1 ;break ;case 'o' : +if (imageOpts) { +printf ("--image-opts and 'open -o' are mutually exclusive\n" ); +return 0 ; + }if (!qemu_opts_parse_noisily (&empty_opts, optarg, false)) {qemu_opts_reset (&empty_opts);return 0 ;
@@ -166,6 +171,14 @@ static int open_f(BlockBackend *blk, int argc, char **argv) flags |=BDRV_O_RDWR ; } +if (imageOpts && (optind == argc -1 )) { +if (!qemu_opts_parse_noisily (&empty_opts, argv[optind], false)) { +qemu_opts_reset (&empty_opts); +return 0 ; + } + optind++; + } + qopts =qemu_opts_find (&empty_opts,NULL ); opts = qopts ?qemu_opts_to_qdict (qopts,NULL ) :NULL ;qemu_opts_reset (&empty_opts);
@@ -366,6 +379,7 @@ static void reenable_tty_echo(void)enum {OPTION_OBJECT =256 , +OPTION_IMAGE_OPTS =257 , };static QemuOptsList qemu_object_opts = {
@@ -378,6 +392,16 @@ static QemuOptsList qemu_object_opts = { }; +static QemuOptsList file_opts = { + .name ="file" , + .implied_opt_name ="file" , + .head =QTAILQ_HEAD_INITIALIZER (file_opts.head), + .desc = { +/* no elements => accept any params */ + {/* end of list */ } + }, +}; +int main (int argc,char **argv) {int readonly =0 ;
@@ -397,6 +421,7 @@ int main(int argc, char **argv) { "cache", 1, NULL, 't' }, { "trace", 1, NULL, 'T' }, { "object", 1, NULL, OPTION_OBJECT }, + { "image-opts", 0, NULL, OPTION_IMAGE_OPTS }, { NULL, 0, NULL, 0 } };int c;
@@ -404,6 +429,7 @@ int main(int argc, char **argv)int flags =BDRV_O_UNMAP ;Error *local_error =NULL ;QDict *opts =NULL ; +const char *format =NULL ;#ifdef CONFIG_POSIX signal (SIGPIPE ,SIG_IGN );
@@ -431,10 +457,7 @@ int main(int argc, char **argv) }break ;case 'f' : -if (!opts) { - opts =qdict_new (); - } -qdict_put (opts,"driver" ,qstring_from_str (optarg)); + format = optarg;break ;case 'c' :add_user_command (optarg);
@@ -466,13 +489,16 @@ int main(int argc, char **argv)usage (progname);exit (0 );case OPTION_OBJECT : { -QemuOpts *qopts =NULL ; +QemuOpts *qopts; qopts =qemu_opts_parse_noisily (&qemu_object_opts, optarg, true);if (!qopts) {exit (1 ); } }break ; +case OPTION_IMAGE_OPTS : + imageOpts = true; +break ;default :usage (progname);exit (1 );
@@ -484,6 +510,11 @@ int main(int argc, char **argv)exit (1 ); } +if (format && imageOpts) { +error_report ("--image-opts and -f are mutually exclusive" ); +exit (1 ); + } +if (qemu_init_main_loop (&local_error)) {error_report_err (local_error);exit (1 );
@@ -516,7 +547,21 @@ int main(int argc, char **argv) }if ((argc - optind) ==1 ) { -openfile (argv[optind], flags, opts); +if (imageOpts) { +QemuOpts *qopts =NULL ; + qopts =qemu_opts_parse_noisily (&file_opts, argv[optind], false); +if (!qopts) { +exit (1 ); + } + opts =qemu_opts_to_qdict (qopts,NULL ); +openfile (NULL , flags, opts); + }else { +if (format) { + opts =qdict_new (); +qdict_put (opts,"driver" ,qstring_from_str (format)); + } +openfile (argv[optind], flags, opts); + } }command_loop ();
Signature · 1 line
2.5.0
PATCH v6 6/10 qemu-nbd: allow specifying image as a set of options args
In reply to Daniel P. BerrangeCurrently qemu-nbd allows an image filename to be passed on the command line, but unless using the JSON format, it does not have a way to set any options except the format eg
qemu-nbd https://127.0.0.1/images/centos7.iso
qemu-nbd /home/berrange/demo.qcow2
This adds a --image-opts arg that indicates that the positional filename should be interpreted as a full option string, not just a filename.
qemu-nbd --image-opts driver=https,url=https://127.0.0.1/images,sslverify=off qemu-nbd --image-opts driver=file,filename=/home/berrange/demo.qcow2
This flag is mutually exclusive with the '-f' flag.
--- qemu-nbd.c | 43 ++++++++++++++++++++++++++++++++++++++----- qemu-nbd.texi | 7 ++++++- 2 files changed, 44 insertions(+), 6 deletions(-)
qemu-nbd.c +38 -5
@@ -44,6 +44,7 @@#define QEMU_NBD_OPT_DISCARD 3#define QEMU_NBD_OPT_DETECT_ZEROES 4#define QEMU_NBD_OPT_OBJECT 5 +#define QEMU_NBD_OPT_IMAGE_OPTS 7static NBDExport *exp;static int verbose;
@@ -103,6 +104,7 @@ static void usage(const char *name)" --aio=MODE set AIO mode (native or threads)\n" " --discard=MODE set discard mode (ignore, unmap)\n" " --detect-zeroes=MODE set detect-zeroes mode (off, on, unmap)\n" +" --image-opts treat FILE as a full set of image options\n" "\n" "Report bugs to <[email protected]>\n" , name, NBD_DEFAULT_PORT, "DEVICE");
@@ -377,6 +379,16 @@ static SocketAddress *nbd_build_socket_address(const char *sockpath, } +static QemuOptsList file_opts = { + .name ="file" , + .implied_opt_name ="file" , + .head =QTAILQ_HEAD_INITIALIZER (file_opts.head), + .desc = { +/* no elements => accept any params */ + {/* end of list */ } + }, +}; +static QemuOptsList qemu_object_opts = { .name ="object" , .implied_opt_name ="qom-type" ,
@@ -425,6 +437,7 @@ int main(int argc, char **argv) { "persistent", 0, NULL, 't' }, { "verbose", 0, NULL, 'v' }, { "object", 1, NULL, QEMU_NBD_OPT_OBJECT }, + { "image-opts", 0, NULL, QEMU_NBD_OPT_IMAGE_OPTS }, { NULL, 0, NULL, 0 } };int ch;
@@ -442,6 +455,7 @@ int main(int argc, char **argv)Error *local_err =NULL ;BlockdevDetectZeroesOptions detect_zeroes =BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF ;QDict *options =NULL ; +bool imageOpts = false;/* The client thread uses SIGTERM to interrupt the server. A signal * handler ensures that "qemu-nbd -v -c" exits with a nice status code.
@@ -615,6 +629,9 @@ int main(int argc, char **argv)exit (EXIT_FAILURE ); } }break ; +case QEMU_NBD_OPT_IMAGE_OPTS : + imageOpts = true; +break ; } }
@@ -721,13 +738,29 @@ int main(int argc, char **argv)bdrv_init ();atexit (bdrv_close_all); -if (fmt) { - options =qdict_new (); -qdict_put (options,"driver" ,qstring_from_str (fmt)); + srcpath = argv[optind]; +if (imageOpts) { +QemuOpts *opts; +if (fmt) { +error_report ("--image-opts and -f are mutually exclusive" ); +exit (EXIT_FAILURE ); + } + opts =qemu_opts_parse_noisily (&file_opts, srcpath, true); +if (!opts) { +qemu_opts_reset (&file_opts); +exit (EXIT_FAILURE ); + } + options =qemu_opts_to_qdict (opts,NULL ); +qemu_opts_reset (&file_opts); + blk =blk_new_open ("hda" ,NULL ,NULL , options, flags, &local_err); + }else { +if (fmt) { + options =qdict_new (); +qdict_put (options,"driver" ,qstring_from_str (fmt)); + } + blk =blk_new_open ("hda" , srcpath,NULL , options, flags, &local_err); } - srcpath = argv[optind]; - blk =blk_new_open ("hda" , srcpath,NULL , options, flags, &local_err);if (!blk) {error_reportf_err (local_err,"Failed to blk_new_open '%s': " , argv[optind]);
qemu-nbd.texi +6 -1
@@ -13,7 +13,8 @@ Export a QEMU disk image using the NBD protocol. @c man end @c man begin OPTIONS -@var{filename} is a disk image filename. +@var{filename} is a disk image filename, or a set of block +driver options if @var{--image-opts} is specified. @var{dev} is an NBD device.
@@ -32,6 +33,10 @@ The offset into the image The interface to bind to (default @samp{0.0.0.0}) @item -k, --socket=@var{path} Use a unix socket with path @var{path} +@item --image-opts +Treat @var{filename} as a set of image options, instead of a plain +filename. If this flag is specified, the @var{-f} flag should +not be used, instead the '@code{format=}' option should be set. @item -f, --format=@var{fmt} Force the use of the block driver for format @var{fmt} instead of auto-detecting
Signature · 1 line
2.5.0
PATCH v6 7/10 qemu-img: allow specifying image as a set of options args
In reply to Daniel P. BerrangeCurrently qemu-img allows an image filename to be passed on the command line, but unless using the JSON format, it does not have a way to set any options except the format eg
qemu-img info https://127.0.0.1/images/centos7.iso
This adds a --image-opts arg that indicates that the positional filename should be interpreted as a full option string, not just a filename.
qemu-img info --image-opts driver=https,url=https://127.0.0.1/images,sslverify=off
This flag is mutually exclusive with the '-f' / '-F' flags.
--- qemu-img-cmds.hx | 44 ++++++------ qemu-img.c | 205 ++++++++++++++++++++++++++++++++++++++++++++----------- qemu-img.texi | 6 ++ 3 files changed, 195 insertions(+), 60 deletions(-)
qemu-img-cmds.hx +22 -22
@@ -10,68 +10,68 @@ STEXI ETEXI DEF("check", img_check, - "check [-q] [--object objectdef] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename") + "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename") STEXI -@item check [--object @var{objectdef}] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename} +@item check [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename} ETEXI DEF("create", img_create, - "create [-q] [--object objectdef] [-f fmt] [-o options] filename [size]") + "create [-q] [--object objectdef] [--image-opts] [-f fmt] [-o options] filename [size]") STEXI -@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] +@item create [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] ETEXI DEF("commit", img_commit, - "commit [-q] [--object objectdef] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") + "commit [-q] [--object objectdef] [--image-opts] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") STEXI -@item commit [--object @var{objectdef}] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename} +@item commit [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename} ETEXI DEF("compare", img_compare, - "compare [--object objectdef] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2") + "compare [--object objectdef] [--image-opts] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2") STEXI -@item compare [--object @var{objectdef}] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2} +@item compare [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2} ETEXI DEF("convert", img_convert, - "convert [--object objectdef] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename") + "convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename") STEXI -@item convert [--object @var{objectdef}] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ETEXI DEF("info", img_info, - "info [--object objectdef] [-f fmt] [--output=ofmt] [--backing-chain] filename") + "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] filename") STEXI -@item info [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} +@item info [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} ETEXI DEF("map", img_map, - "map [--object objectdef] [-f fmt] [--output=ofmt] filename") + "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] filename") STEXI -@item map [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} +@item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} ETEXI DEF("snapshot", img_snapshot, - "snapshot [--object objectdef] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") + "snapshot [--object objectdef] [--image-opts] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") STEXI -@item snapshot [--object @var{objectdef}] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} +@item snapshot [--object @var{objectdef}] [--image-opts] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} ETEXI DEF("rebase", img_rebase, - "rebase [--object objectdef] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") + "rebase [--object objectdef] [--image-opts] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") STEXI -@item rebase [--object @var{objectdef}] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} +@item rebase [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} ETEXI DEF("resize", img_resize, - "resize [--object objectdef] [-q] filename [+ | -]size") + "resize [--object objectdef] [--image-opts] [-q] filename [+ | -]size") STEXI -@item resize [--object @var{objectdef}] [-q] @var{filename} [+ | -]@var{size} +@item resize [--object @var{objectdef}] [--image-opts] [-q] @var{filename} [+ | -]@var{size} ETEXI DEF("amend", img_amend, - "amend [--object objectdef] [-p] [-q] [-f fmt] [-t cache] -o options filename") + "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename") STEXI -@item amend [--object @var{objectdef}] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} +@item amend [--object @var{objectdef}] [--image-opts] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} @end table ETEXI
qemu-img.c +167 -38
517 lines not on this page · raw message
qemu-img.texi +6 -0
@@ -32,6 +32,12 @@ page for a description of the object properties. The most common object type is a @code{secret}, which is used to supply passwords and/or encryption keys. +@item --image-opts + +Indicates that the @var{filename} parameter is to be interpreted as a +full option string, not a plain filename. This parameter is mutually +exclusive with the @var{-f} and @var{-F} parameters. + @item fmt is the disk image format. It is guessed automatically in most cases. See below for a description of the supported disk formats.
Signature · 1 line
2.5.0
PATCH v6 8/10 qemu-nbd: don't overlap long option values with short options
In reply to Daniel P. BerrangeWhen defining values for long options, the normal practice is to start numbering from 256, to avoid overlap with the range of valid values for short options.
--- qemu-nbd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
qemu-nbd.c +6 -6
@@ -39,12 +39,12 @@#include <pthread.h> #define SOCKET_PATH "/var/lock/qemu-nbd-%s" -#define QEMU_NBD_OPT_CACHE 1 -#define QEMU_NBD_OPT_AIO 2 -#define QEMU_NBD_OPT_DISCARD 3 -#define QEMU_NBD_OPT_DETECT_ZEROES 4 -#define QEMU_NBD_OPT_OBJECT 5 -#define QEMU_NBD_OPT_IMAGE_OPTS 7 +#define QEMU_NBD_OPT_CACHE 256 +#define QEMU_NBD_OPT_AIO 257 +#define QEMU_NBD_OPT_DISCARD 258 +#define QEMU_NBD_OPT_DETECT_ZEROES 259 +#define QEMU_NBD_OPT_OBJECT 260 +#define QEMU_NBD_OPT_IMAGE_OPTS 261static NBDExport *exp;static int verbose;
Signature · 1 line
2.5.0
PATCH v6 9/10 qemu-nbd: use no_argument/required_argument constants
In reply to Daniel P. BerrangeWhen declaring the 'struct option' array, use the standard constants no_argument/required_argument, instead of magic values 0 and 1.
--- qemu-nbd.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-)
qemu-nbd.c +24 -23
@@ -415,29 +415,30 @@ int main(int argc, char **argv)const char *sn_id_or_name =NULL ;const char *sopt ="hVb:o:p:rsnP:c:dvk:e:f:tl:" ;struct option lopt[] = { - {"help" ,0 ,NULL ,'h' }, - {"version" ,0 ,NULL ,'V' }, - {"bind" ,1 ,NULL ,'b' }, - {"port" ,1 ,NULL ,'p' }, - {"socket" ,1 ,NULL ,'k' }, - {"offset" ,1 ,NULL ,'o' }, - {"read-only" ,0 ,NULL ,'r' }, - {"partition" ,1 ,NULL ,'P' }, - {"connect" ,1 ,NULL ,'c' }, - {"disconnect" ,0 ,NULL ,'d' }, - {"snapshot" ,0 ,NULL ,'s' }, - {"load-snapshot" ,1 ,NULL ,'l' }, - {"nocache" ,0 ,NULL ,'n' }, - {"cache" ,1 ,NULL ,QEMU_NBD_OPT_CACHE }, - {"aio" ,1 ,NULL ,QEMU_NBD_OPT_AIO }, - {"discard" ,1 ,NULL ,QEMU_NBD_OPT_DISCARD }, - {"detect-zeroes" ,1 ,NULL ,QEMU_NBD_OPT_DETECT_ZEROES }, - {"shared" ,1 ,NULL ,'e' }, - {"format" ,1 ,NULL ,'f' }, - {"persistent" ,0 ,NULL ,'t' }, - {"verbose" ,0 ,NULL ,'v' }, - {"object" ,1 ,NULL ,QEMU_NBD_OPT_OBJECT }, - {"image-opts" ,0 ,NULL ,QEMU_NBD_OPT_IMAGE_OPTS }, + {"help" , no_argument,NULL ,'h' }, + {"version" , no_argument,NULL ,'V' }, + {"bind" , required_argument,NULL ,'b' }, + {"port" , required_argument,NULL ,'p' }, + {"socket" , required_argument,NULL ,'k' }, + {"offset" , required_argument,NULL ,'o' }, + {"read-only" , no_argument,NULL ,'r' }, + {"partition" , required_argument,NULL ,'P' }, + {"connect" , required_argument,NULL ,'c' }, + {"disconnect" , no_argument,NULL ,'d' }, + {"snapshot" , no_argument,NULL ,'s' }, + {"load-snapshot" , required_argument,NULL ,'l' }, + {"nocache" , no_argument,NULL ,'n' }, + {"cache" , required_argument,NULL ,QEMU_NBD_OPT_CACHE }, + {"aio" , required_argument,NULL ,QEMU_NBD_OPT_AIO }, + {"discard" , required_argument,NULL ,QEMU_NBD_OPT_DISCARD }, + {"detect-zeroes" , required_argument,NULL , +QEMU_NBD_OPT_DETECT_ZEROES }, + {"shared" , required_argument,NULL ,'e' }, + {"format" , required_argument,NULL ,'f' }, + {"persistent" , no_argument,NULL ,'t' }, + {"verbose" , no_argument,NULL ,'v' }, + {"object" , required_argument,NULL ,QEMU_NBD_OPT_OBJECT }, + {"image-opts" , no_argument,NULL ,QEMU_NBD_OPT_IMAGE_OPTS }, {NULL ,0 ,NULL ,0 } };int ch;
Signature · 1 line
2.5.0
PATCH v6 10/10 qemu-io: use no_argument/required_argument constants
In reply to Daniel P. BerrangeWhen declaring the 'struct option' array, use the standard constants no_argument/required_argument, instead of magic values 0 and 1.
--- qemu-io.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
qemu-io.c +15 -15
@@ -407,21 +407,21 @@ int main(int argc, char **argv)int readonly =0 ;const char *sopt ="hVc:d:f:rsnmgkt:T:" ;const struct option lopt[] = { - {"help" ,0 ,NULL ,'h' }, - {"version" ,0 ,NULL ,'V' }, - {"offset" ,1 ,NULL ,'o' }, - {"cmd" ,1 ,NULL ,'c' }, - {"format" ,1 ,NULL ,'f' }, - {"read-only" ,0 ,NULL ,'r' }, - {"snapshot" ,0 ,NULL ,'s' }, - {"nocache" ,0 ,NULL ,'n' }, - {"misalign" ,0 ,NULL ,'m' }, - {"native-aio" ,0 ,NULL ,'k' }, - {"discard" ,1 ,NULL ,'d' }, - {"cache" ,1 ,NULL ,'t' }, - {"trace" ,1 ,NULL ,'T' }, - {"object" ,1 ,NULL ,OPTION_OBJECT }, - {"image-opts" ,0 ,NULL ,OPTION_IMAGE_OPTS }, + {"help" , no_argument,NULL ,'h' }, + {"version" , no_argument,NULL ,'V' }, + {"offset" , required_argument,NULL ,'o' }, + {"cmd" , required_argument,NULL ,'c' }, + {"format" , required_argument,NULL ,'f' }, + {"read-only" , no_argument,NULL ,'r' }, + {"snapshot" , no_argument,NULL ,'s' }, + {"nocache" , no_argument,NULL ,'n' }, + {"misalign" , no_argument,NULL ,'m' }, + {"native-aio" , no_argument,NULL ,'k' }, + {"discard" , required_argument,NULL ,'d' }, + {"cache" , required_argument,NULL ,'t' }, + {"trace" , required_argument,NULL ,'T' }, + {"object" , required_argument,NULL ,OPTION_OBJECT }, + {"image-opts" , no_argument,NULL ,OPTION_IMAGE_OPTS }, {NULL ,0 ,NULL ,0 } };int c;
Signature · 1 line
2.5.0
Kevin Wolf
AppliedAm 15.02.2016 um 15:33 hat Daniel P. Berrange geschrieben:
Quoted 17 lines
This series of patches expands the syntax of the qemu-img, qemu-nbd and qemu-io commands to make them more flexible.
v0: https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg04365.html
v1: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04014.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04354.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03381.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg04984.html
v5: https://lists.gnu.org/archive/html/qemu-block/2016-02/msg00022.htmlFirst all three gain a --object parameter, which allows instantiation of user creatable object types. The immediate use case is to allow for creation of the 'secret' object type to pass passwords for curl, iscsi and rbd drivers. For qemu-nbd this will also be needed to create TLS certificates for encryption support.
Quoted 8 lines
Then all three gain a '--image-opts' parameter which causes the positional filenames to be interepreted as option strings rather tha nplain filenames. This avoids the need to use the JSON syntax, or to add custom CLI args for each block backend option that exists. The immediate use case is to allow the user to specify the ID of the 'secret' object they just created.
Finally, there are a few small cleanup patches
Thanks, applied to the block branch.
Kevin
Quoted 25 lines · Kevin Wolf
Am 15.02.2016 um 15:33 hat Daniel P. Berrange geschrieben:
Quoted 24 lines
This series of patches expands the syntax of the qemu-img, qemu-nbd and qemu-io commands to make them more flexible.
v0: https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg04365.html
v1: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04014.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04354.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03381.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg04984.html
v5: https://lists.gnu.org/archive/html/qemu-block/2016-02/msg00022.htmlFirst all three gain a --object parameter, which allows instantiation of user creatable object types. The immediate use case is to allow for creation of the 'secret' object type to pass passwords for curl, iscsi and rbd drivers. For qemu-nbd this will also be needed to create TLS certificates for encryption support.
Then all three gain a '--image-opts' parameter which causes the positional filenames to be interepreted as option strings rather tha nplain filenames. This avoids the need to use the JSON syntax, or to add custom CLI args for each block backend option that exists. The immediate use case is to allow the user to specify the ID of the 'secret' object they just created.
Quoted 3 lines
Quoted 1 line
Finally, there are a few small cleanup patches
Thanks, applied to the block branch.
The NBD patches just merged, so I've rebased this series and sent you a v7 to resolve the conflicts
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Am 17.02.2016 um 11:10 hat Daniel P. Berrange geschrieben:
Quoted 26 lines · Kevin Wolf
Quoted 25 lines
Am 15.02.2016 um 15:33 hat Daniel P. Berrange geschrieben:
Quoted 24 lines
This series of patches expands the syntax of the qemu-img, qemu-nbd and qemu-io commands to make them more flexible.
v0: https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg04365.html
v1: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04014.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04354.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03381.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg04984.html
v5: https://lists.gnu.org/archive/html/qemu-block/2016-02/msg00022.htmlFirst all three gain a --object parameter, which allows instantiation of user creatable object types. The immediate use case is to allow for creation of the 'secret' object type to pass passwords for curl, iscsi and rbd drivers. For qemu-nbd this will also be needed to create TLS certificates for encryption support.
Then all three gain a '--image-opts' parameter which causes the positional filenames to be interepreted as option strings rather tha nplain filenames. This avoids the need to use the JSON syntax, or to add custom CLI args for each block backend option that exists. The immediate use case is to allow the user to specify the ID of the 'secret' object they just created.
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Finally, there are a few small cleanup patches
Thanks, applied to the block branch.
The NBD patches just merged, so I've rebased this series and sent you a v7 to resolve the conflicts
*sigh* Okay, I'll drop this series and re-review sometime later.
Kevin
Quoted 27 lines · Kevin Wolf
Am 17.02.2016 um 11:10 hat Daniel P. Berrange geschrieben:
Quoted 26 lines · Kevin Wolf
Quoted 25 lines
Am 15.02.2016 um 15:33 hat Daniel P. Berrange geschrieben:
Quoted 24 lines
This series of patches expands the syntax of the qemu-img, qemu-nbd and qemu-io commands to make them more flexible.
v0: https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg04365.html
v1: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04014.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg04354.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03381.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg04984.html
v5: https://lists.gnu.org/archive/html/qemu-block/2016-02/msg00022.htmlFirst all three gain a --object parameter, which allows instantiation of user creatable object types. The immediate use case is to allow for creation of the 'secret' object type to pass passwords for curl, iscsi and rbd drivers. For qemu-nbd this will also be needed to create TLS certificates for encryption support.
Then all three gain a '--image-opts' parameter which causes the positional filenames to be interepreted as option strings rather tha nplain filenames. This avoids the need to use the JSON syntax, or to add custom CLI args for each block backend option that exists. The immediate use case is to allow the user to specify the ID of the 'secret' object they just created.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Finally, there are a few small cleanup patches
Thanks, applied to the block branch.
The NBD patches just merged, so I've rebased this series and sent you a v7 to resolve the conflicts
*sigh* Okay, I'll drop this series and re-review sometime later.
NB it was a pretty clear rebase with no functional changes. Mostly just resolving conflicts in the "struct option" list entries used for getopt_long
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|