Message ID | 1460564276-9750-1-git-send-email-berrange@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 04/13/2016 12:17 PM, Daniel P. Berrange wrote: > The iSCSI block driver has a very strange approach whereby it > does not accept options directly as part of the -drive arg, > but instead takes them indirectly from a -iscsi arg. To make > up -driver and -iscsi args, it takes the iSCSI target name > and uses that as an ID value for the -iscsi arg lookup. > > For example, given a -drive arg that looks like > > -drive file=iscsi://192.168.122.1:3260/iqn.2013-12.com.example%3Aiscsi-chap-netpool/1,format=raw,if=none,id=drive-virtio-disk0 > > The iSCSI driver will try to find the -iscsi arg with an > id of "iqn.2013-12.com.example:iscsi-chap-netpool" eg it > expects > > -iscsi id=iqn.2013-12.com.example:iscsi-chap-netpool,user=fred,password-secret=secret0 > > Unfortunately this is impossible to actually do in practice > because almost all iSCSI target names contain a ':' which > is not a valid ID character for QEMU: > > $ qemu-system-x86_64: -iscsi id=iqn.2013-12.com.example:iscsi-chap-netpool,user=redhat,password=123456: Parameter 'id' expects an identifier > Identifiers consist of letters, digits, '-', '.', '_', starting with a letter. > > So for this to work we need to remove the invalid characters > in some manner. This patch takes the simplest possible approach > of just converting all invalid characters into underscores. eg > you can now use > > $ qemu-system-x86_64: -iscsi id=iqn.2013-12.com.example_iscsi-chap-netpool,user=redhat,password=123456: Parameter 'id' expects an identifier > > There is theoretically the possibility for collison with this > approach if there were 2 iSCSI luns attached to the same VM > with target names that clash on the escaped char: eg > > iqn.2013-12.com.example:iscsi-chap-netpool > iqn.2013-12.com.example_iscsi-chap-netpool > > but in reality this will never happen. In addition in QEMU 2.7 > the need to use the -iscsi arg will be removed by allowing all > the desired options to be listed directly with -drive. IOW this > quick stripping of invalid characters is just a short term fix > that will ultimately go away. For this reason it is not thought > worthwhile to invent a full collision-free escaping syntax for > iSCSI target IDs. > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > --- > Figured I'd chime in since I tripped across this today... I think the one thing that concerns me about this '_' approach is we'd be "stuck" with it. Eventually if 'initiator-name' is added to the -drive command (as well as being able to parse the 'user=' and 'password-secret='), then needing to add -iscsi wouldn't be required for libvirt. Whether this patch would be required after -drive is modified was the other question rattling around. So I figured I'd see if I can get things to work without it... Using the v1 of this patch series did work for libvirt if I passed the "id=" shown above using the '_' instead of ':'; however, taking the Pino Toscano's series in mind, I can also start a domain using the "initiator-name=" and "id=" parameters for '-iscsi' as follows: ... -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-3-jaf/master-key.aes ... -iscsi id=iscsi-chap-netpool,initiator-name=iqn.2013-12.com.example,user=redhat,password-secret=virtio-disk1-ivKey0 -drive file=iscsi://192.168.122.1:3260/iqn.2013-12.com.example%3Aiscsi-chap-netpool/1,format=raw,if=none,id=drive-virtio-disk1 -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x9,drive=drive-virtio-disk1,id=virtio-disk1,bootindex=1 ... So without this patch - I should be able to get things to work starting a domain. Long ago I tagged a libvir-list posting from Rich Jones asking about using the '-iscsi initiator-name=' command: http://www.redhat.com/archives/libvir-list/2014-July/msg00281.html Since what libvirt was using worked, I just left it as one of those someday I'll understand how/if it can be used... John > Note this problem was previously raised: > > http://lists.nongnu.org/archive/html/qemu-devel/2015-11/msg06501.html > > and discussed the following month: > > http://lists.nongnu.org/archive/html/qemu-devel/2015-12/msg00112.html > > Changed in v2: > > - Actually use the escaped target ID for all parameters, > not just chap auth params (Pino) > > block/iscsi.c | 43 +++++++++++++++++++++++++++++++------------ > 1 file changed, 31 insertions(+), 12 deletions(-) > > diff --git a/block/iscsi.c b/block/iscsi.c > index 302baf8..8ee2e4d 100644 > --- a/block/iscsi.c > +++ b/block/iscsi.c > @@ -1070,7 +1070,23 @@ retry: > return 0; > } > > -static void parse_chap(struct iscsi_context *iscsi, const char *target, > + > +static char *convert_target_to_id(const char *target) > +{ > + char *id = g_strdup(target); > + size_t i; > + > + for (i = 1; id[i]; i++) { > + if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { > + id[i] = '_'; > + } > + } > + > + return id; > +} > + > + > +static void parse_chap(struct iscsi_context *iscsi, const char *targetid, > Error **errp) > { > QemuOptsList *list; > @@ -1085,7 +1101,7 @@ static void parse_chap(struct iscsi_context *iscsi, const char *target, > return; > } > > - opts = qemu_opts_find(list, target); > + opts = qemu_opts_find(list, targetid); > if (opts == NULL) { > opts = QTAILQ_FIRST(&list->head); > if (!opts) { > @@ -1123,7 +1139,7 @@ static void parse_chap(struct iscsi_context *iscsi, const char *target, > g_free(secret); > } > > -static void parse_header_digest(struct iscsi_context *iscsi, const char *target, > +static void parse_header_digest(struct iscsi_context *iscsi, const char *targetid, > Error **errp) > { > QemuOptsList *list; > @@ -1135,7 +1151,7 @@ static void parse_header_digest(struct iscsi_context *iscsi, const char *target, > return; > } > > - opts = qemu_opts_find(list, target); > + opts = qemu_opts_find(list, targetid); > if (opts == NULL) { > opts = QTAILQ_FIRST(&list->head); > if (!opts) { > @@ -1161,7 +1177,7 @@ static void parse_header_digest(struct iscsi_context *iscsi, const char *target, > } > } > > -static char *parse_initiator_name(const char *target) > +static char *parse_initiator_name(const char *targetid) > { > QemuOptsList *list; > QemuOpts *opts; > @@ -1171,7 +1187,7 @@ static char *parse_initiator_name(const char *target) > > list = qemu_find_opts("iscsi"); > if (list) { > - opts = qemu_opts_find(list, target); > + opts = qemu_opts_find(list, targetid); > if (!opts) { > opts = QTAILQ_FIRST(&list->head); > } > @@ -1195,7 +1211,7 @@ static char *parse_initiator_name(const char *target) > return iscsi_name; > } > > -static int parse_timeout(const char *target) > +static int parse_timeout(const char *targetid) > { > QemuOptsList *list; > QemuOpts *opts; > @@ -1203,7 +1219,7 @@ static int parse_timeout(const char *target) > > list = qemu_find_opts("iscsi"); > if (list) { > - opts = qemu_opts_find(list, target); > + opts = qemu_opts_find(list, targetid); > if (!opts) { > opts = QTAILQ_FIRST(&list->head); > } > @@ -1453,6 +1469,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > Error *local_err = NULL; > const char *filename; > int i, ret = 0, timeout = 0; > + char *targetid = NULL; > > opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); > qemu_opts_absorb_qdict(opts, options, &local_err); > @@ -1473,7 +1490,8 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > > memset(iscsilun, 0, sizeof(IscsiLun)); > > - initiator_name = parse_initiator_name(iscsi_url->target); > + targetid = convert_target_to_id(iscsi_url->target); > + initiator_name = parse_initiator_name(targetid); > > iscsi = iscsi_create_context(initiator_name); > if (iscsi == NULL) { > @@ -1499,7 +1517,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > } > > /* check if we got CHAP username/password via the options */ > - parse_chap(iscsi, iscsi_url->target, &local_err); > + parse_chap(iscsi, targetid, &local_err); > if (local_err != NULL) { > error_propagate(errp, local_err); > ret = -EINVAL; > @@ -1515,7 +1533,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); > > /* check if we got HEADER_DIGEST via the options */ > - parse_header_digest(iscsi, iscsi_url->target, &local_err); > + parse_header_digest(iscsi, targetid, &local_err); > if (local_err != NULL) { > error_propagate(errp, local_err); > ret = -EINVAL; > @@ -1523,7 +1541,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > } > > /* timeout handling is broken in libiscsi before 1.15.0 */ > - timeout = parse_timeout(iscsi_url->target); > + timeout = parse_timeout(targetid); > #if defined(LIBISCSI_API_VERSION) && LIBISCSI_API_VERSION >= 20150621 > iscsi_set_timeout(iscsi, timeout); > #else > @@ -1643,6 +1661,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > > out: > qemu_opts_del(opts); > + g_free(targetid); > g_free(initiator_name); > if (iscsi_url != NULL) { > iscsi_destroy_url(iscsi_url); >
On Wed, Apr 13, 2016 at 09:41:54PM -0400, John Ferlan wrote: > > > On 04/13/2016 12:17 PM, Daniel P. Berrange wrote: > > The iSCSI block driver has a very strange approach whereby it > > does not accept options directly as part of the -drive arg, > > but instead takes them indirectly from a -iscsi arg. To make > > up -driver and -iscsi args, it takes the iSCSI target name > > and uses that as an ID value for the -iscsi arg lookup. > > > > For example, given a -drive arg that looks like > > > > -drive file=iscsi://192.168.122.1:3260/iqn.2013-12.com.example%3Aiscsi-chap-netpool/1,format=raw,if=none,id=drive-virtio-disk0 > > > > The iSCSI driver will try to find the -iscsi arg with an > > id of "iqn.2013-12.com.example:iscsi-chap-netpool" eg it > > expects > > > > -iscsi id=iqn.2013-12.com.example:iscsi-chap-netpool,user=fred,password-secret=secret0 > > > > Unfortunately this is impossible to actually do in practice > > because almost all iSCSI target names contain a ':' which > > is not a valid ID character for QEMU: > > > > $ qemu-system-x86_64: -iscsi id=iqn.2013-12.com.example:iscsi-chap-netpool,user=redhat,password=123456: Parameter 'id' expects an identifier > > Identifiers consist of letters, digits, '-', '.', '_', starting with a letter. > > > > So for this to work we need to remove the invalid characters > > in some manner. This patch takes the simplest possible approach > > of just converting all invalid characters into underscores. eg > > you can now use > > > > $ qemu-system-x86_64: -iscsi id=iqn.2013-12.com.example_iscsi-chap-netpool,user=redhat,password=123456: Parameter 'id' expects an identifier > > > > There is theoretically the possibility for collison with this > > approach if there were 2 iSCSI luns attached to the same VM > > with target names that clash on the escaped char: eg > > > > iqn.2013-12.com.example:iscsi-chap-netpool > > iqn.2013-12.com.example_iscsi-chap-netpool > > > > but in reality this will never happen. In addition in QEMU 2.7 > > the need to use the -iscsi arg will be removed by allowing all > > the desired options to be listed directly with -drive. IOW this > > quick stripping of invalid characters is just a short term fix > > that will ultimately go away. For this reason it is not thought > > worthwhile to invent a full collision-free escaping syntax for > > iSCSI target IDs. > > > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > > --- > > > > Figured I'd chime in since I tripped across this today... > > I think the one thing that concerns me about this '_' approach is we'd > be "stuck" with it. Eventually if 'initiator-name' is added to the > -drive command (as well as being able to parse the 'user=' and > 'password-secret='), then needing to add -iscsi wouldn't be required for > libvirt. Whether this patch would be required after -drive is modified > was the other question rattling around. So I figured I'd see if I can > get things to work without it... > > Using the v1 of this patch series did work for libvirt if I passed the > "id=" shown above using the '_' instead of ':'; however, taking the Pino > Toscano's series in mind, I can also start a domain using the > "initiator-name=" and "id=" parameters for '-iscsi' as follows: > > ... > -object > secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-3-jaf/master-key.aes > > ... > -iscsi > id=iscsi-chap-netpool,initiator-name=iqn.2013-12.com.example,user=redhat,password-secret=virtio-disk1-ivKey0 > -drive > file=iscsi://192.168.122.1:3260/iqn.2013-12.com.example%3Aiscsi-chap-netpool/1,format=raw,if=none,id=drive-virtio-disk1 > -device > virtio-blk-pci,scsi=off,bus=pci.0,addr=0x9,drive=drive-virtio-disk1,id=virtio-disk1,bootindex=1 > I don't believe that is doing what you think it is doing. QEMU will still be using the "iqn.2013-12.com.example:iscsi-chap-netpool" string as an ID to lookup the corresponding -iscsi arg. It will not find it because your arg uses ID of "iscsi-chap-netpool". So, the code will now be falling backk to just using the /first/ -iscsi arg in the list. IOW, if you add multiple iSCSI disks to the VM, they will all be using the first -iscsi arg, which is certainly not what we want Regards, Daniel
[...] >> >> Figured I'd chime in since I tripped across this today... >> >> I think the one thing that concerns me about this '_' approach is we'd >> be "stuck" with it. Eventually if 'initiator-name' is added to the >> -drive command (as well as being able to parse the 'user=' and >> 'password-secret='), then needing to add -iscsi wouldn't be required for >> libvirt. Whether this patch would be required after -drive is modified >> was the other question rattling around. So I figured I'd see if I can >> get things to work without it... >> >> Using the v1 of this patch series did work for libvirt if I passed the >> "id=" shown above using the '_' instead of ':'; however, taking the Pino >> Toscano's series in mind, I can also start a domain using the >> "initiator-name=" and "id=" parameters for '-iscsi' as follows: >> >> ... >> -object >> secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-3-jaf/master-key.aes >> >> ... >> -iscsi >> id=iscsi-chap-netpool,initiator-name=iqn.2013-12.com.example,user=redhat,password-secret=virtio-disk1-ivKey0 >> -drive >> file=iscsi://192.168.122.1:3260/iqn.2013-12.com.example%3Aiscsi-chap-netpool/1,format=raw,if=none,id=drive-virtio-disk1 >> -device >> virtio-blk-pci,scsi=off,bus=pci.0,addr=0x9,drive=drive-virtio-disk1,id=virtio-disk1,bootindex=1 >> > > I don't believe that is doing what you think it is doing. > > QEMU will still be using the "iqn.2013-12.com.example:iscsi-chap-netpool" > string as an ID to lookup the corresponding -iscsi arg. It will not > find it because your arg uses ID of "iscsi-chap-netpool". So, the code > will now be falling backk to just using the /first/ -iscsi arg in the > list. > > IOW, if you add multiple iSCSI disks to the VM, they will all be using > the first -iscsi arg, which is certainly not what we want > Hmm.. OK, I see... Myopia was thinking get one done first, then think about two... Anyway, assume XML such as: <disk type='network' device='disk'> <driver name='qemu' type='raw'/> <auth username='redhat'> <secret type='iscsi' usage='libvirtiscsi'/> </auth> <source protocol='iscsi' name='iqn.2013-12.com.example:iscsi-chap-netpool/1'> <host name='192.168.122.1' port='3260'/> </source> <target dev='vda' bus='virtio'/> </disk> <disk type='network' device='disk'> <driver name='qemu' type='raw'/> <auth username='redhat'> <secret type='iscsi' usage='libvirtiscsi'/> </auth> <source protocol='iscsi' name='iqn.2013-12.com.example:iscsi-chap-netpool/2'> <host name='192.168.122.1' port='3260'/> </source> <target dev='vdb' bus='virtio'/> </disk> When building the source "path" for the qemu argument, libvirt uses the complete "name" parameter for the -drive "file=" argument. With my recent patches, I would add the "-iscsi id=..." using the same path. If I use the "name" parameter as is without changing it, then even with this patch, I get the "Parameter 'id' error...". If I modify the name for the "id=" to change both ":" and "/" into "_", then I can start a vm. If I only change one, then I get the "Parameter 'id' error..." If I try to remove the "/#", then yes, I get the "Duplicate ID 'iqn.2013-12.com.example_iscsi-chap-netpool' ..." message. If I go back to using the "initiator-name" approach, but instead of chopping off the "/#" lun, I convert the "/" to a "_", then I can start the vm again, thus having: -iscsi id=iscsi-chap-netpool_1,initiator-name=iqn.2013-12.com.example,user=redhat,password-secret=virtio-disk0-ivKey0 and -iscsi id=iscsi-chap-netpool_2,initiator-name=iqn.2013-12.com.example,user=redhat,password-secret=virtio-disk1-ivKey0 If the "/#" isn't provided, the libvirt documented behaviour is to use lun0... I haven't tried that yet, but would suspect given this approach (e.g. convert "/" to "_"), I'd still have unique names. I haven't tried a pass with only adding one "-iscsi" per initiator and target name. That is, prescan the iSCSI devices (for both disk and hostdev) adding one "id=" and seeing if both disks can use it. Thanks - John
diff --git a/block/iscsi.c b/block/iscsi.c index 302baf8..8ee2e4d 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1070,7 +1070,23 @@ retry: return 0; } -static void parse_chap(struct iscsi_context *iscsi, const char *target, + +static char *convert_target_to_id(const char *target) +{ + char *id = g_strdup(target); + size_t i; + + for (i = 1; id[i]; i++) { + if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { + id[i] = '_'; + } + } + + return id; +} + + +static void parse_chap(struct iscsi_context *iscsi, const char *targetid, Error **errp) { QemuOptsList *list; @@ -1085,7 +1101,7 @@ static void parse_chap(struct iscsi_context *iscsi, const char *target, return; } - opts = qemu_opts_find(list, target); + opts = qemu_opts_find(list, targetid); if (opts == NULL) { opts = QTAILQ_FIRST(&list->head); if (!opts) { @@ -1123,7 +1139,7 @@ static void parse_chap(struct iscsi_context *iscsi, const char *target, g_free(secret); } -static void parse_header_digest(struct iscsi_context *iscsi, const char *target, +static void parse_header_digest(struct iscsi_context *iscsi, const char *targetid, Error **errp) { QemuOptsList *list; @@ -1135,7 +1151,7 @@ static void parse_header_digest(struct iscsi_context *iscsi, const char *target, return; } - opts = qemu_opts_find(list, target); + opts = qemu_opts_find(list, targetid); if (opts == NULL) { opts = QTAILQ_FIRST(&list->head); if (!opts) { @@ -1161,7 +1177,7 @@ static void parse_header_digest(struct iscsi_context *iscsi, const char *target, } } -static char *parse_initiator_name(const char *target) +static char *parse_initiator_name(const char *targetid) { QemuOptsList *list; QemuOpts *opts; @@ -1171,7 +1187,7 @@ static char *parse_initiator_name(const char *target) list = qemu_find_opts("iscsi"); if (list) { - opts = qemu_opts_find(list, target); + opts = qemu_opts_find(list, targetid); if (!opts) { opts = QTAILQ_FIRST(&list->head); } @@ -1195,7 +1211,7 @@ static char *parse_initiator_name(const char *target) return iscsi_name; } -static int parse_timeout(const char *target) +static int parse_timeout(const char *targetid) { QemuOptsList *list; QemuOpts *opts; @@ -1203,7 +1219,7 @@ static int parse_timeout(const char *target) list = qemu_find_opts("iscsi"); if (list) { - opts = qemu_opts_find(list, target); + opts = qemu_opts_find(list, targetid); if (!opts) { opts = QTAILQ_FIRST(&list->head); } @@ -1453,6 +1469,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, Error *local_err = NULL; const char *filename; int i, ret = 0, timeout = 0; + char *targetid = NULL; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); @@ -1473,7 +1490,8 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, memset(iscsilun, 0, sizeof(IscsiLun)); - initiator_name = parse_initiator_name(iscsi_url->target); + targetid = convert_target_to_id(iscsi_url->target); + initiator_name = parse_initiator_name(targetid); iscsi = iscsi_create_context(initiator_name); if (iscsi == NULL) { @@ -1499,7 +1517,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, } /* check if we got CHAP username/password via the options */ - parse_chap(iscsi, iscsi_url->target, &local_err); + parse_chap(iscsi, targetid, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); ret = -EINVAL; @@ -1515,7 +1533,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); /* check if we got HEADER_DIGEST via the options */ - parse_header_digest(iscsi, iscsi_url->target, &local_err); + parse_header_digest(iscsi, targetid, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); ret = -EINVAL; @@ -1523,7 +1541,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, } /* timeout handling is broken in libiscsi before 1.15.0 */ - timeout = parse_timeout(iscsi_url->target); + timeout = parse_timeout(targetid); #if defined(LIBISCSI_API_VERSION) && LIBISCSI_API_VERSION >= 20150621 iscsi_set_timeout(iscsi, timeout); #else @@ -1643,6 +1661,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, out: qemu_opts_del(opts); + g_free(targetid); g_free(initiator_name); if (iscsi_url != NULL) { iscsi_destroy_url(iscsi_url);
The iSCSI block driver has a very strange approach whereby it does not accept options directly as part of the -drive arg, but instead takes them indirectly from a -iscsi arg. To make up -driver and -iscsi args, it takes the iSCSI target name and uses that as an ID value for the -iscsi arg lookup. For example, given a -drive arg that looks like -drive file=iscsi://192.168.122.1:3260/iqn.2013-12.com.example%3Aiscsi-chap-netpool/1,format=raw,if=none,id=drive-virtio-disk0 The iSCSI driver will try to find the -iscsi arg with an id of "iqn.2013-12.com.example:iscsi-chap-netpool" eg it expects -iscsi id=iqn.2013-12.com.example:iscsi-chap-netpool,user=fred,password-secret=secret0 Unfortunately this is impossible to actually do in practice because almost all iSCSI target names contain a ':' which is not a valid ID character for QEMU: $ qemu-system-x86_64: -iscsi id=iqn.2013-12.com.example:iscsi-chap-netpool,user=redhat,password=123456: Parameter 'id' expects an identifier Identifiers consist of letters, digits, '-', '.', '_', starting with a letter. So for this to work we need to remove the invalid characters in some manner. This patch takes the simplest possible approach of just converting all invalid characters into underscores. eg you can now use $ qemu-system-x86_64: -iscsi id=iqn.2013-12.com.example_iscsi-chap-netpool,user=redhat,password=123456: Parameter 'id' expects an identifier There is theoretically the possibility for collison with this approach if there were 2 iSCSI luns attached to the same VM with target names that clash on the escaped char: eg iqn.2013-12.com.example:iscsi-chap-netpool iqn.2013-12.com.example_iscsi-chap-netpool but in reality this will never happen. In addition in QEMU 2.7 the need to use the -iscsi arg will be removed by allowing all the desired options to be listed directly with -drive. IOW this quick stripping of invalid characters is just a short term fix that will ultimately go away. For this reason it is not thought worthwhile to invent a full collision-free escaping syntax for iSCSI target IDs. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- Note this problem was previously raised: http://lists.nongnu.org/archive/html/qemu-devel/2015-11/msg06501.html and discussed the following month: http://lists.nongnu.org/archive/html/qemu-devel/2015-12/msg00112.html Changed in v2: - Actually use the escaped target ID for all parameters, not just chap auth params (Pino) block/iscsi.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-)