Auto-generated IDs
PATCH v2 1/2 util - add automated ID generation utility
In reply to Jeff CodyMultiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
This patch enforces the following rules when generating an ID:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictability, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).
The scheme for this is as follows (no spaces):
# subsys D RR Reserved char --| | | | Subsystem String ----| | | Unique number (64-bit) --| | Two-digit random number ---|
For example, a generated node-name for the block sub-system may look like this:
#block076
The caller of id_generate() is responsible for freeing the generated node name string with g_free().
--- include/qemu-common.h | 8 ++++++++ util/id.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)
include/qemu-common.h +8 -0
@@ -237,6 +237,14 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,#define STR_OR_NULL (str) ((str) ? (str) : "null")/* id.c */ + +typedef enum IdSubSystems { +ID_QDEV , +ID_BLOCK , +ID_MAX /* last element, used as array size */ +}IdSubSystems ; + +char *id_generate (IdSubSystems );bool id_wellformed (const char *id);/* path.c */
util/id.c +36 -0
@@ -26,3 +26,39 @@ bool id_wellformed(const char *id) }return true; } + +#define ID_SPECIAL_CHAR '#' + +static const char *const id_subsys_str[] = { + [ID_QDEV ] ="qdev" , + [ID_BLOCK ] ="block" , +}; + +/* Generates an ID of the form: +* +* "#block146", +* +* where: +* - "#" is always the reserved character '#' +* - "block" refers to the subsystem identifed via IdSubSystems +* and id_subsys_str[] +* - "1" is a unique number (up to a uint64_t) for the subsystem +* - "46" is a zero-padded two digit pseudo-random number +* +* The caller is responsible for freeing the returned string with g_free() +*/ +char *id_generate (IdSubSystems id) +{ +static uint64_t id_counters[ID_MAX ]; +uint32_t rnd; + +assert (id <ID_MAX ); +assert (id_subsys_str[id]); + + rnd =g_random_int_range (0 ,99 ); + +return g_strdup_printf ("%c%s%" PRIu64"%02" PRId32,ID_SPECIAL_CHAR , + id_subsys_str[id], + id_counters[id]++, + rnd); +}
Signature · 1 line
1.9.3
PATCH v2 2/2 block: auto-generated node-names
In reply to Jeff CodyIf a node-name is not specified, automatically generate the node-name.
Generated node-names will use the "block" sub-system identifier.
--- block.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
block.c +16 -9
@@ -771,32 +771,39 @@ static void bdrv_assign_node_name(BlockDriverState *bs,const char *node_name, Error **errp) { + char *gen_node_name = NULL; +if (!node_name) { -return ; - } - -/* Check for empty string or invalid characters */ -if (!id_wellformed (node_name)) { -error_setg (errp,"Invalid node name" ); -return ; + gen_node_name =id_generate (ID_BLOCK ); + node_name = gen_node_name; + }else { +/* Check for empty string or invalid characters, but not if it is +* generated (generated names use characters not available to the user) +* */ +if (!id_wellformed (node_name)) { +error_setg (errp,"Invalid node name" ); +return ; + } }/* takes care of avoiding namespaces collisions */ if (blk_by_name (node_name)) {error_setg (errp,"node-name=%s is conflicting with a device id" , node_name); -return ; + goto out; }/* takes care of avoiding duplicates node names */ if (bdrv_find_node (node_name)) {error_setg (errp,"Duplicate node name" ); -return ; + goto out; }/* copy node name into the bs and insert it into the graph list */ pstrcpy (bs->node_name,sizeof (bs->node_name), node_name);QTAILQ_INSERT_TAIL (&graph_bdrv_states, bs, node_list); +out: +g_free (gen_node_name); } static QemuOptsList bdrv_runtime_opts = {
Signature · 1 line
1.9.3
v2 cover Auto-generated IDs
Changes from RFC v1:
Patch 1: Several typos / grammatical errors (thanks Eric, John)
Make id_subsys_str[] const pointer to const strings (thanks Eric) Moved id_subsys_str[] out from id_generate() (thanks John) Assert on null string for given id (thanks Eric) Zero-pad the 2-digit random # (thanks John)
Patch 2: None
Born from the conversation on qemu-devel, this generation scheme uses the format ultimately proposed by Kevin, after list discussion.
It attempts to keep the ID strings as small as possible, while fulfilling:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictibility, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).
See patch 1 for the generation scheme details.
Jeff Cody (2):
util - add automated ID generation utility
block: auto-generated node-names
block.c | 25 ++++++++++++++++--------- include/qemu-common.h | 8 ++++++++ util/id.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 9 deletions(-)
Signature · 1 line
1.9.3
Re: [Qemu-devel] [PATCH v2 1/2] util - add automated ID generation utility
In reply to Jeff CodyQuoted 27 lines · Jeff Cody
Multiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
This patch enforces the following rules when generating an ID:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictability, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).The scheme for this is as follows (no spaces):
# subsys D RR Reserved char --| | | | Subsystem String ----| | | Unique number (64-bit) --| | Two-digit random number ---|For example, a generated node-name for the block sub-system may look like this:
#block076
Quoted 8 lines
The caller of
id_generate()is responsible for freeing the generated node name string withg_free().Signed-off-by Jeff Cody <[email protected]>--- include/qemu-common.h | 8 ++++++++ util/id.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)
util/id.c bool id_wellformed(const char *id) · line 35
Quoted 5 lines
util/id.c +5
-0+ +static const char *const id_subsys_str[] = { + [ID_QDEV ] ="qdev" , + [ID_BLOCK ] ="block" , +};
We're inconsistent on whether there should be a space in '*const' (compare commit a91e211 with b86f461, for example). But since qemu.git has both spellings in various contexts, it's probably not worth changing here.
Review
Quoted 2 lines
(quoted diff) +2
-0+ + rnd = g_random_int_range(0, 99);
Thankfully, g_random_* is a PRNG that is not consuming system entropy (auto-generated names should not be starving /dev/random).
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH v2 1/2] util - add automated ID generation utility
Quoted 39 lines · Eric Blake
Quoted 27 lines · Jeff Cody
Multiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
This patch enforces the following rules when generating an ID:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictability, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).The scheme for this is as follows (no spaces):
# subsys D RR Reserved char --| | | | Subsystem String ----| | | Unique number (64-bit) --| | Two-digit random number ---|For example, a generated node-name for the block sub-system may look like this:
#block076Quoted 8 lines
The caller of
id_generate()is responsible for freeing the generated node name string withg_free().Signed-off-by Jeff Cody <[email protected]>--- include/qemu-common.h | 8 ++++++++ util/id.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)Reviewed-by Eric Blake <[email protected]>
Quoted 11 lines
util/id.c bool id_wellformed(const char *id) · line 35
Quoted 5 lines
util/id.c +5
-0+ +static const char *const id_subsys_str[] = { + [ID_QDEV ] ="qdev" , + [ID_BLOCK ] ="block" , +};We're inconsistent on whether there should be a space in '*const' (compare commit a91e211 with b86f461, for example). But since qemu.git has both spellings in various contexts, it's probably not worth changing here.
If this ends up needing another rev, I'll change it for you :)
Quoted 6 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ + rnd = g_random_int_range(0, 99);Thankfully, g_random_* is a PRNG that is not consuming system entropy (auto-generated names should not be starving
/dev/random).
Yup.
Thanks,
Jeff
Re: [Qemu-devel] [PATCH v2 1/2] util - add automated ID generation utility
In reply to Jeff CodyQuoted 90 lines · Jeff Cody
Multiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
This patch enforces the following rules when generating an ID:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictability, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).The scheme for this is as follows (no spaces):
# subsys D RR Reserved char --| | | | Subsystem String ----| | | Unique number (64-bit) --| | Two-digit random number ---|For example, a generated node-name for the block sub-system may look like this:
#block076The caller of
id_generate()is responsible for freeing the generated node name string withg_free().Signed-off-by Jeff Cody <[email protected]>--- include/qemu-common.h | 8 ++++++++ util/id.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)include/qemu-common.h +8
-0@@ -237,6 +237,14 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,#define STR_OR_NULL (str) ((str) ? (str) : "null")/* id.c */ + +typedef enum IdSubSystems { +ID_QDEV , +ID_BLOCK , +ID_MAX /* last element, used as array size */ +}IdSubSystems ; + +char *id_generate (IdSubSystems );bool id_wellformed (const char *id);/* path.c */ util/id.c +26
-0@@ -26,3 +26,39 @@ bool id_wellformed(const char *id) }return true; } + +#define ID_SPECIAL_CHAR '#' + +static const char *const id_subsys_str[] = { + [ID_QDEV ] ="qdev" , + [ID_BLOCK ] ="block" , +}; + +/* Generates an ID of the form: +* +* "#block146", +* +* where: +* - "#" is always the reserved character '#' +* - "block" refers to the subsystem identifed via IdSubSystems +* and id_subsys_str[] +* - "1" is a unique number (up to a uint64_t) for the subsystem +* - "46" is a zero-padded two digit pseudo-random number +* +* The caller is responsible for freeing the returned string with g_free() +*/ +char *id_generate (IdSubSystems id) +{ +static uint64_t id_counters[ID_MAX ]; +uint32_t rnd; +
util/id.c bool id_wellformed(const char *id) · line 64
Quoted 10 lines
util/id.c +10
-0+assert (id <ID_MAX ); +assert (id_subsys_str[id]); + + rnd =g_random_int_range (0 ,99 ); + +return g_strdup_printf ("%c%s%" PRIu64"%02" PRId32,ID_SPECIAL_CHAR , + id_subsys_str[id], + id_counters[id]++, + rnd); +}
Seems good to me.
Re: [Qemu-devel] [Qemu-block] [PATCH v2 1/2] util - add automated ID generation utility
In reply to Jeff Codyinclude/qemu-common.h int64_t strtosz_suffix_unit(const char *nptr, char **end, · line 247
Quoted 13 lines · Jeff Cody
Multiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
include/qemu-common.h +8
-0+ +typedef enum IdSubSystems { +ID_QDEV , +ID_BLOCK , +ID_MAX /* last element, used as array size */ +}IdSubSystems ; + +char *id_generate (IdSubSystems );
Not that it matters much, but it seems that everywhere else in the QEMU source code the rule is to name the parameters in function prototypes.
Otherwise, the patch looks good!
Berto
Re: [Qemu-devel] [Qemu-block] [PATCH v2 1/2] util - add automated ID generation utility
Quoted 7 lines · Alberto Garcia
Quoted 4 lines · Jeff Cody
Multiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
Quoted 12 lines
include/qemu-common.h int64_t strtosz_suffix_unit(const char *nptr, char **end, · line 247
Quoted 8 lines
include/qemu-common.h +8
-0+ +typedef enum IdSubSystems { +ID_QDEV , +ID_BLOCK , +ID_MAX /* last element, used as array size */ +}IdSubSystems ; + +char *id_generate (IdSubSystems );Not that it matters much, but it seems that everywhere else in the QEMU source code the rule is to name the parameters in function prototypes.
Indeed... another syntactic tweak to make if a v3 is needed (or a maintainer insists!)
Quoted 5 lines
Otherwise, the patch looks good!
Reviewed-by Alberto Garcia <[email protected]>Berto
Thanks!
-Jeff
Kevin Wolf
AppliedAm 02.09.2015 um 00:30 hat Jeff Cody geschrieben:
Quoted 15 lines
Changes from RFC v1:
Patch 1: Several typos / grammatical errors (thanks Eric, John)
Make id_subsys_str[] const pointer to const strings (thanks Eric) Moved id_subsys_str[] out fromid_generate()(thanks John) Assert on null string for given id (thanks Eric) Zero-pad the 2-digit random # (thanks John)Patch 2: None
Born from the conversation on qemu-devel, this generation scheme uses the format ultimately proposed by Kevin, after list discussion.
It attempts to keep the ID strings as small as possible, while fulfilling:
Quoted 8 lines
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictibility, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).See patch 1 for the generation scheme details.
Thanks, applied to the block branch.
While applying, I fixed up the id_generate() declaration in the header file to include an identifier for the parameter.
Kevin
Am 03.09.2015 um 17:02 hat Kevin Wolf geschrieben:
Quoted 23 lines
Am 02.09.2015 um 00:30 hat Jeff Cody geschrieben:
Quoted 22 lines
Changes from RFC v1:
Patch 1: Several typos / grammatical errors (thanks Eric, John)
Make id_subsys_str[] const pointer to const strings (thanks Eric) Moved id_subsys_str[] out fromid_generate()(thanks John) Assert on null string for given id (thanks Eric) Zero-pad the 2-digit random # (thanks John)Patch 2: None
Born from the conversation on qemu-devel, this generation scheme uses the format ultimately proposed by Kevin, after list discussion.
It attempts to keep the ID strings as small as possible, while fulfilling:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictibility, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).
Quoted 6 lines
Quoted 1 line
See patch 1 for the generation scheme details.
Thanks, applied to the block branch.
While applying, I fixed up the
id_generate()declaration in the header file to include an identifier for the parameter.
I'm afraid we'll need a v3 that fixes the qemu-iotests output for 051 and 067. It will also require a new filter function because of the random part in the ID.
Kevin
Re: [Qemu-devel] [PATCH v2 1/2] util - add automated ID generation utility
In reply to Jeff CodyQuoted 60 lines · Jeff Cody
Multiple sub-systems in QEMU may find it useful to generate IDs for objects that a user may reference via QMP or HMP. This patch presents a standardized way to do it, so that automatic ID generation follows the same rules.
This patch enforces the following rules when generating an ID:
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictability, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).The scheme for this is as follows (no spaces):
# subsys D RR Reserved char --| | | | Subsystem String ----| | | Unique number (64-bit) --| | Two-digit random number ---|For example, a generated node-name for the block sub-system may look like this:
#block076The caller of
id_generate()is responsible for freeing the generated node name string withg_free().Signed-off-by Jeff Cody <[email protected]>--- include/qemu-common.h | 8 ++++++++ util/id.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)include/qemu-common.h +8
-0@@ -237,6 +237,14 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,#define STR_OR_NULL (str) ((str) ? (str) : "null")/* id.c */ + +typedef enum IdSubSystems { +ID_QDEV , +ID_BLOCK , +ID_MAX /* last element, used as array size */ +}IdSubSystems ; + +char *id_generate (IdSubSystems );bool id_wellformed (const char *id);/* path.c */ util/id.c +0
-0
util/id.c bool id_wellformed(const char *id) · line 32
Quoted 7 lines
util/id.c +4
-0@@ -26,3 +26,39 @@ bool id_wellformed(const char *id) }return true; } + +#define ID_SPECIAL_CHAR '#' + +static const char *const id_subsys_str[] = {
Like Eric, I'd prefer *const.
util/id.c bool id_wellformed(const char *id) · line 37
Quoted 5 lines
util/id.c +5
-0+ [ID_QDEV] = "qdev", + [ID_BLOCK] = "block", +}; + +/* Generates an ID of the form:
Style nit: wing you comments on both ends, please.
util/id.c bool id_wellformed(const char *id) · line 46
Quoted 9 lines
util/id.c +9
-0+* +* "#block146", +* +* where: +* - "#" is always the reserved character '#' +* - "block" refers to the subsystem identifed via IdSubSystems +* and id_subsys_str[] +* - "1" is a unique number (up to a uint64_t) for the subsystem +* - "46" is a zero-padded two digit pseudo-random number
Recommend to note that the value does not satisfy id_wellformed().
I'd specify a bit more losely:
/*
* Generates an ID of the form PREFIX SUBSYSTEM NUMBER
* where
* - PREFIX is the reserved character '#'
* - SUBSYSTEM identifies the subsystem creating the ID
* - NUMBER is a decimal number unique within SUBSYSTEM.
* Example: "#block146"
*
* Note that these IDs do not satisfy id_wellformed().
util/id.c bool id_wellformed(const char *id) · line 58
Quoted 12 lines
util/id.c +12
-0+* +* The caller is responsible for freeing the returned string with g_free() +*/ +char *id_generate (IdSubSystems id) +{ +static uint64_t id_counters[ID_MAX ]; +uint32_t rnd; + +assert (id <ID_MAX ); +assert (id_subsys_str[id]); + + rnd =g_random_int_range (0 ,99 );
99 is off by one: "Returns a random gint32 equally distributed over the range [begin ..end -1]."
Quoted 6 lines
util/id.c +6
-0+ +return g_strdup_printf ("%c%s%" PRIu64"%02" PRId32,ID_SPECIAL_CHAR , + id_subsys_str[id], + id_counters[id]++, + rnd); +}
Re: [Qemu-devel] [PATCH v2 2/2] block: auto-generated node-names
In reply to Jeff CodyQuoted 21 lines · Jeff Cody
If a node-name is not specified, automatically generate the node-name.
Generated node-names will use the "block" sub-system identifier.
Reviewed-by Eric Blake <[email protected]>Reviewed-by John Snow <[email protected]>Signed-off-by Jeff Cody <[email protected]>--- block.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)block.c +2
-0@@ -771,32 +771,39 @@ static void bdrv_assign_node_name(BlockDriverState *bs,const char *node_name, Error **errp) { + char *gen_node_name = NULL; +
block.c static void bdrv_assign_node_name(BlockDriverState *bs, · line 778
Quoted 10 lines
block.c +2
-7if (!node_name) { -return ; - } - -/* Check for empty string or invalid characters */ -if (!id_wellformed (node_name)) { -error_setg (errp,"Invalid node name" ); -return ; + gen_node_name =id_generate (ID_BLOCK ); + node_name = gen_node_name;
I'd do
node_name = gen_node_name = id_generate(ID_BLOCK);
but that's clearly a matter of taste.
block.c static void bdrv_assign_node_name(BlockDriverState *bs, · line 782
Quoted 4 lines
block.c +4
-0+ }else { +/* Check for empty string or invalid characters, but not if it is +* generated (generated names use characters not available to the user) +* */
Untidy comment. Make it:
/*
* Check for empty string or invalid characters, but not if it
* is generated (generated names use characters not available to
* the user)
*/
block.c static void bdrv_assign_node_name(BlockDriverState *bs, · line 787
Quoted 5 lines
block.c +4
-0+if (!id_wellformed (node_name)) { +error_setg (errp,"Invalid node name" ); +return ; + } }
I'd probably do an else if here. Additional benefit: smaller diff.
Quoted 24 lines
block.c +4
-2/* takes care of avoiding namespaces collisions */ if (blk_by_name (node_name)) {error_setg (errp,"node-name=%s is conflicting with a device id" , node_name); -return ; + goto out; }/* takes care of avoiding duplicates node names */ if (bdrv_find_node (node_name)) {error_setg (errp,"Duplicate node name" ); -return ; + goto out; }/* copy node name into the bs and insert it into the graph list */ pstrcpy (bs->node_name,sizeof (bs->node_name), node_name);QTAILQ_INSERT_TAIL (&graph_bdrv_states, bs, node_list); +out: +g_free (gen_node_name); }static QemuOptsList bdrv_runtime_opts = {
Quoted 15 lines · Jeff Cody
Changes from RFC v1:
Patch 1: Several typos / grammatical errors (thanks Eric, John)
Make id_subsys_str[] const pointer to const strings (thanks Eric) Moved id_subsys_str[] out fromid_generate()(thanks John) Assert on null string for given id (thanks Eric) Zero-pad the 2-digit random # (thanks John)Patch 2: None
Born from the conversation on qemu-devel, this generation scheme uses the format ultimately proposed by Kevin, after list discussion.
It attempts to keep the ID strings as small as possible, while fulfilling:
Quoted 8 lines
1.) Guarantee no collisions with a user-specified ID
2.) Identify the sub-system the ID belongs to
3.) Guarantee of uniqueness
4.) Spoiling predictibility, to avoid creating an assumption
of object ordering and parsing (i.e., we don't want users to think they can guess the next ID based on prior behavior).See patch 1 for the generation scheme details.
Since PATCH 1 defines an ID for the qdev subsystem, I expected a patch to put it to use. As long as there is none, PATCH 1 shouldn't define ID_QDEV.
Looks good apart from a harmless off-by-one and a few style nits.