Message ID | 1481203391-9523-2-git-send-email-kwolf@redhat.com |
---|---|
State | New |
Headers | show |
On Thu, Dec 08, 2016 at 02:23:06PM +0100, Kevin Wolf wrote: > This introduces a .bdrv_parse_filename handler for iscsi which parses an > URL if given and translates it to individual options. > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > --- > block/iscsi.c | 189 ++++++++++++++++++++++++++++++++++++++++++---------------- > 1 file changed, 136 insertions(+), 53 deletions(-) > > diff --git a/block/iscsi.c b/block/iscsi.c > index 0960929..7a6664e 100644 > --- a/block/iscsi.c > +++ b/block/iscsi.c > @@ -1469,20 +1469,6 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp) > } > } > > -/* TODO Convert to fine grained options */ > -static QemuOptsList runtime_opts = { > - .name = "iscsi", > - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), > - .desc = { > - { > - .name = "filename", > - .type = QEMU_OPT_STRING, > - .help = "URL to the iscsi image", > - }, > - { /* end of list */ } > - }, > -}; > - > static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun, > int evpd, int pc, void **inq, Error **errp) > { > @@ -1604,20 +1590,98 @@ out: > * We support iscsi url's on the form > * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> > */ > +static void iscsi_parse_filename(const char *filename, QDict *options, > + Error **errp) > +{ > + struct iscsi_url *iscsi_url; > + const char *transport_name; > + char *lun_str; > + > + iscsi_url = iscsi_parse_full_url(NULL, filename); > + if (iscsi_url == NULL) { > + error_setg(errp, "Failed to parse URL : %s", filename); > + return; > + } > + > +#if LIBISCSI_API_VERSION >= (20160603) > + switch (iscsi_url->transport) { > + case TCP_TRANSPORT: transport_name = "tcp"; break; > + case ISER_TRANSPORT: transport_name = "iser"; break; > + default: > + error_setg(errp, "Unknown transport type (%d)", > + iscsi_url->transport); > + return; > + } > +#else > + transport_name = "tcp"; > +#endif Here if the URI contained a transport "iser" and we're using an old libiscsi, we silently ignore that and use 'tcp'. IMHO we should be reporting "Unsupported transport type 'iser'" when using the old libiscsi API/ > + qdict_set_default_str(options, "transport", transport_name); > + qdict_set_default_str(options, "portal", iscsi_url->portal); > + qdict_set_default_str(options, "target", iscsi_url->target); > + > + lun_str = g_strdup_printf("%d", iscsi_url->lun); > + qdict_set_default_str(options, "lun", lun_str); > + g_free(lun_str); > + > + if (iscsi_url->user[0] != '\0') { > + qdict_set_default_str(options, "user", iscsi_url->user); > + qdict_set_default_str(options, "password", iscsi_url->passwd); If the URI contains "user" but not "password", this stores bogus data in the "password" field I believe. > + } > + > + iscsi_destroy_url(iscsi_url); > +} > + > +/* TODO Add -iscsi options */ > +static QemuOptsList runtime_opts = { > + .name = "iscsi", > + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), > + .desc = { > + { > + .name = "transport", > + .type = QEMU_OPT_STRING, > + }, > + { > + .name = "portal", > + .type = QEMU_OPT_STRING, > + }, > + { > + .name = "target", > + .type = QEMU_OPT_STRING, > + }, > + { > + .name = "user", > + .type = QEMU_OPT_STRING, > + }, > + { > + .name = "password", > + .type = QEMU_OPT_STRING, > + }, > + { > + .name = "lun", > + .type = QEMU_OPT_NUMBER, > + }, > + { /* end of list */ } > + }, > +}; > + > static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > Error **errp) > { > IscsiLun *iscsilun = bs->opaque; > struct iscsi_context *iscsi = NULL; > - struct iscsi_url *iscsi_url = NULL; > struct scsi_task *task = NULL; > struct scsi_inquiry_standard *inq = NULL; > struct scsi_inquiry_supported_pages *inq_vpd; > char *initiator_name = NULL; > QemuOpts *opts; > Error *local_err = NULL; > - const char *filename; > - int i, ret = 0, timeout = 0; > + const char *transport_name, *portal, *target; > + const char *user, *password; > +#if LIBISCSI_API_VERSION >= (20160603) > + enum iscsi_transport_type transport; > +#endif > + int i, ret = 0, timeout = 0, lun; > > opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); > qemu_opts_absorb_qdict(opts, options, &local_err); > @@ -1627,18 +1691,41 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > goto out; > } > > - filename = qemu_opt_get(opts, "filename"); > + transport_name = qemu_opt_get(opts, "transport"); > + portal = qemu_opt_get(opts, "portal"); > + target = qemu_opt_get(opts, "target"); > + user = qemu_opt_get(opts, "user"); > + password = qemu_opt_get(opts, "password"); > + lun = qemu_opt_get_number(opts, "lun", 0); Do we really want to default to '0' for LUN ? With Linux tgtd at least this is not a valid LUN to use as a volume. It feels like we should be raising an error if 'lun' is not explcitly set by the user > > - iscsi_url = iscsi_parse_full_url(iscsi, filename); > - if (iscsi_url == NULL) { > - error_setg(errp, "Failed to parse URL : %s", filename); > + if (!transport_name || !portal || !target) { > + error_setg(errp, "Need all of transport, portal and target options"); > + ret = -EINVAL; > + goto out; > + } > + if (user && !password) { > + error_setg(errp, "If a user name is given, a password is required"); > + ret = -EINVAL; > + goto out; > + } > + > + if (!strcmp(transport_name, "tcp")) { > +#if LIBISCSI_API_VERSION >= (20160603) > + transport = TCP_TRANSPORT; > + } else if (!strcmp(transport_name, "iser")) { > + transport = ISER_TRANSPORT; > +#else > + /* TCP is what older libiscsi versions always use */ Again we should report an error if user set a transport_name of 'iser' here. > +#endif > + } else { > + error_setg(errp, "Unknown transport: %s", transport_name); > ret = -EINVAL; > goto out; > } > > memset(iscsilun, 0, sizeof(IscsiLun)); Regards, Daniel
Am 08.12.2016 um 15:10 hat Daniel P. Berrange geschrieben: > On Thu, Dec 08, 2016 at 02:23:06PM +0100, Kevin Wolf wrote: > > This introduces a .bdrv_parse_filename handler for iscsi which parses an > > URL if given and translates it to individual options. > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > --- > > block/iscsi.c | 189 ++++++++++++++++++++++++++++++++++++++++++---------------- > > 1 file changed, 136 insertions(+), 53 deletions(-) > > > > diff --git a/block/iscsi.c b/block/iscsi.c > > index 0960929..7a6664e 100644 > > --- a/block/iscsi.c > > +++ b/block/iscsi.c > > @@ -1469,20 +1469,6 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp) > > } > > } > > > > -/* TODO Convert to fine grained options */ > > -static QemuOptsList runtime_opts = { > > - .name = "iscsi", > > - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), > > - .desc = { > > - { > > - .name = "filename", > > - .type = QEMU_OPT_STRING, > > - .help = "URL to the iscsi image", > > - }, > > - { /* end of list */ } > > - }, > > -}; > > - > > static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun, > > int evpd, int pc, void **inq, Error **errp) > > { > > @@ -1604,20 +1590,98 @@ out: > > * We support iscsi url's on the form > > * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> > > */ > > +static void iscsi_parse_filename(const char *filename, QDict *options, > > + Error **errp) > > +{ > > + struct iscsi_url *iscsi_url; > > + const char *transport_name; > > + char *lun_str; > > + > > + iscsi_url = iscsi_parse_full_url(NULL, filename); > > + if (iscsi_url == NULL) { > > + error_setg(errp, "Failed to parse URL : %s", filename); > > + return; > > + } > > + > > +#if LIBISCSI_API_VERSION >= (20160603) > > + switch (iscsi_url->transport) { > > + case TCP_TRANSPORT: transport_name = "tcp"; break; > > + case ISER_TRANSPORT: transport_name = "iser"; break; > > + default: > > + error_setg(errp, "Unknown transport type (%d)", > > + iscsi_url->transport); > > + return; > > + } > > +#else > > + transport_name = "tcp"; > > +#endif > > Here if the URI contained a transport "iser" and we're using > an old libiscsi, we silently ignore that and use 'tcp'. IMHO > we should be reporting "Unsupported transport type 'iser'" > when using the old libiscsi API/ No, old libiscsi would error out in iscsi_parse_full_url(), so you get the "Failed to parse URL" message from above. Not ideal, but with the parsing in the library (which I consider a bad idea, but that's how it works with libiscsi) that's all we can do. (Okay, not quite true, we could create a context a pass that instead of NULL, and then we would get access to a slightly better message from libiscsi. Anyway, we do fail when we should fail, and improving error messages is out of scope for this series.) > > + qdict_set_default_str(options, "transport", transport_name); > > + qdict_set_default_str(options, "portal", iscsi_url->portal); > > + qdict_set_default_str(options, "target", iscsi_url->target); > > + > > + lun_str = g_strdup_printf("%d", iscsi_url->lun); > > + qdict_set_default_str(options, "lun", lun_str); > > + g_free(lun_str); > > + > > + if (iscsi_url->user[0] != '\0') { > > + qdict_set_default_str(options, "user", iscsi_url->user); > > + qdict_set_default_str(options, "password", iscsi_url->passwd); > > If the URI contains "user" but not "password", this stores bogus > data in the "password" field I believe. If any field isn't given, it is zeroed (i.e. an empty string); and if iscsi_url->user is non-empty, iscsi_url->password is non-empty as well. I basically just used the same condition as the original code, but I checked it now once more against the libiscsi implementation to be sure. > > + } > > + > > + iscsi_destroy_url(iscsi_url); > > +} > > + > > +/* TODO Add -iscsi options */ > > +static QemuOptsList runtime_opts = { > > + .name = "iscsi", > > + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), > > + .desc = { > > + { > > + .name = "transport", > > + .type = QEMU_OPT_STRING, > > + }, > > + { > > + .name = "portal", > > + .type = QEMU_OPT_STRING, > > + }, > > + { > > + .name = "target", > > + .type = QEMU_OPT_STRING, > > + }, > > + { > > + .name = "user", > > + .type = QEMU_OPT_STRING, > > + }, > > + { > > + .name = "password", > > + .type = QEMU_OPT_STRING, > > + }, > > + { > > + .name = "lun", > > + .type = QEMU_OPT_NUMBER, > > + }, > > + { /* end of list */ } > > + }, > > +}; > > + > > static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > > Error **errp) > > { > > IscsiLun *iscsilun = bs->opaque; > > struct iscsi_context *iscsi = NULL; > > - struct iscsi_url *iscsi_url = NULL; > > struct scsi_task *task = NULL; > > struct scsi_inquiry_standard *inq = NULL; > > struct scsi_inquiry_supported_pages *inq_vpd; > > char *initiator_name = NULL; > > QemuOpts *opts; > > Error *local_err = NULL; > > - const char *filename; > > - int i, ret = 0, timeout = 0; > > + const char *transport_name, *portal, *target; > > + const char *user, *password; > > +#if LIBISCSI_API_VERSION >= (20160603) > > + enum iscsi_transport_type transport; > > +#endif > > + int i, ret = 0, timeout = 0, lun; > > > > opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); > > qemu_opts_absorb_qdict(opts, options, &local_err); > > @@ -1627,18 +1691,41 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, > > goto out; > > } > > > > - filename = qemu_opt_get(opts, "filename"); > > + transport_name = qemu_opt_get(opts, "transport"); > > + portal = qemu_opt_get(opts, "portal"); > > + target = qemu_opt_get(opts, "target"); > > + user = qemu_opt_get(opts, "user"); > > + password = qemu_opt_get(opts, "password"); > > + lun = qemu_opt_get_number(opts, "lun", 0); > > Do we really want to default to '0' for LUN ? With Linux tgtd at > least this is not a valid LUN to use as a volume. It feels like > we should be raising an error if 'lun' is not explcitly set by > the user I wasn't sure about this one. But it's mandatory in the URL, so I guess you're right that making it mandatory here as well would make sense. > > > > - iscsi_url = iscsi_parse_full_url(iscsi, filename); > > - if (iscsi_url == NULL) { > > - error_setg(errp, "Failed to parse URL : %s", filename); > > + if (!transport_name || !portal || !target) { > > + error_setg(errp, "Need all of transport, portal and target options"); > > + ret = -EINVAL; > > + goto out; > > + } > > + if (user && !password) { > > + error_setg(errp, "If a user name is given, a password is required"); > > + ret = -EINVAL; > > + goto out; > > + } > > + > > + if (!strcmp(transport_name, "tcp")) { > > +#if LIBISCSI_API_VERSION >= (20160603) > > + transport = TCP_TRANSPORT; > > + } else if (!strcmp(transport_name, "iser")) { > > + transport = ISER_TRANSPORT; > > +#else > > + /* TCP is what older libiscsi versions always use */ > > Again we should report an error if user set a transport_name > of 'iser' here. If you read the code carefully, we do. :-) A value of "tcp" is ignored and everything else gets the error message below in the else branch. > > +#endif > > + } else { > > + error_setg(errp, "Unknown transport: %s", transport_name); > > ret = -EINVAL; > > goto out; > > } > > > > memset(iscsilun, 0, sizeof(IscsiLun)); Kevin
diff --git a/block/iscsi.c b/block/iscsi.c index 0960929..7a6664e 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1469,20 +1469,6 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp) } } -/* TODO Convert to fine grained options */ -static QemuOptsList runtime_opts = { - .name = "iscsi", - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), - .desc = { - { - .name = "filename", - .type = QEMU_OPT_STRING, - .help = "URL to the iscsi image", - }, - { /* end of list */ } - }, -}; - static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun, int evpd, int pc, void **inq, Error **errp) { @@ -1604,20 +1590,98 @@ out: * We support iscsi url's on the form * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> */ +static void iscsi_parse_filename(const char *filename, QDict *options, + Error **errp) +{ + struct iscsi_url *iscsi_url; + const char *transport_name; + char *lun_str; + + iscsi_url = iscsi_parse_full_url(NULL, filename); + if (iscsi_url == NULL) { + error_setg(errp, "Failed to parse URL : %s", filename); + return; + } + +#if LIBISCSI_API_VERSION >= (20160603) + switch (iscsi_url->transport) { + case TCP_TRANSPORT: transport_name = "tcp"; break; + case ISER_TRANSPORT: transport_name = "iser"; break; + default: + error_setg(errp, "Unknown transport type (%d)", + iscsi_url->transport); + return; + } +#else + transport_name = "tcp"; +#endif + + qdict_set_default_str(options, "transport", transport_name); + qdict_set_default_str(options, "portal", iscsi_url->portal); + qdict_set_default_str(options, "target", iscsi_url->target); + + lun_str = g_strdup_printf("%d", iscsi_url->lun); + qdict_set_default_str(options, "lun", lun_str); + g_free(lun_str); + + if (iscsi_url->user[0] != '\0') { + qdict_set_default_str(options, "user", iscsi_url->user); + qdict_set_default_str(options, "password", iscsi_url->passwd); + } + + iscsi_destroy_url(iscsi_url); +} + +/* TODO Add -iscsi options */ +static QemuOptsList runtime_opts = { + .name = "iscsi", + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), + .desc = { + { + .name = "transport", + .type = QEMU_OPT_STRING, + }, + { + .name = "portal", + .type = QEMU_OPT_STRING, + }, + { + .name = "target", + .type = QEMU_OPT_STRING, + }, + { + .name = "user", + .type = QEMU_OPT_STRING, + }, + { + .name = "password", + .type = QEMU_OPT_STRING, + }, + { + .name = "lun", + .type = QEMU_OPT_NUMBER, + }, + { /* end of list */ } + }, +}; + static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = NULL; - struct iscsi_url *iscsi_url = NULL; struct scsi_task *task = NULL; struct scsi_inquiry_standard *inq = NULL; struct scsi_inquiry_supported_pages *inq_vpd; char *initiator_name = NULL; QemuOpts *opts; Error *local_err = NULL; - const char *filename; - int i, ret = 0, timeout = 0; + const char *transport_name, *portal, *target; + const char *user, *password; +#if LIBISCSI_API_VERSION >= (20160603) + enum iscsi_transport_type transport; +#endif + int i, ret = 0, timeout = 0, lun; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); @@ -1627,18 +1691,41 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, goto out; } - filename = qemu_opt_get(opts, "filename"); + transport_name = qemu_opt_get(opts, "transport"); + portal = qemu_opt_get(opts, "portal"); + target = qemu_opt_get(opts, "target"); + user = qemu_opt_get(opts, "user"); + password = qemu_opt_get(opts, "password"); + lun = qemu_opt_get_number(opts, "lun", 0); - iscsi_url = iscsi_parse_full_url(iscsi, filename); - if (iscsi_url == NULL) { - error_setg(errp, "Failed to parse URL : %s", filename); + if (!transport_name || !portal || !target) { + error_setg(errp, "Need all of transport, portal and target options"); + ret = -EINVAL; + goto out; + } + if (user && !password) { + error_setg(errp, "If a user name is given, a password is required"); + ret = -EINVAL; + goto out; + } + + if (!strcmp(transport_name, "tcp")) { +#if LIBISCSI_API_VERSION >= (20160603) + transport = TCP_TRANSPORT; + } else if (!strcmp(transport_name, "iser")) { + transport = ISER_TRANSPORT; +#else + /* TCP is what older libiscsi versions always use */ +#endif + } else { + error_setg(errp, "Unknown transport: %s", transport_name); ret = -EINVAL; goto out; } memset(iscsilun, 0, sizeof(IscsiLun)); - initiator_name = parse_initiator_name(iscsi_url->target); + initiator_name = parse_initiator_name(target); iscsi = iscsi_create_context(initiator_name); if (iscsi == NULL) { @@ -1647,21 +1734,20 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, goto out; } #if LIBISCSI_API_VERSION >= (20160603) - if (iscsi_init_transport(iscsi, iscsi_url->transport)) { + if (iscsi_init_transport(iscsi, transport)) { error_setg(errp, ("Error initializing transport.")); ret = -EINVAL; goto out; } #endif - if (iscsi_set_targetname(iscsi, iscsi_url->target)) { + if (iscsi_set_targetname(iscsi, target)) { error_setg(errp, "iSCSI: Failed to set target name."); ret = -EINVAL; goto out; } - if (iscsi_url->user[0] != '\0') { - ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, - iscsi_url->passwd); + if (user) { + ret = iscsi_set_initiator_username_pwd(iscsi, user, password); if (ret != 0) { error_setg(errp, "Failed to set initiator username and password"); ret = -EINVAL; @@ -1670,7 +1756,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, target, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); ret = -EINVAL; @@ -1686,7 +1772,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, target, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); ret = -EINVAL; @@ -1694,7 +1780,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(target); #if LIBISCSI_API_VERSION >= 20150621 iscsi_set_timeout(iscsi, timeout); #else @@ -1703,7 +1789,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, } #endif - if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) { + if (iscsi_full_connect_sync(iscsi, portal, lun) != 0) { error_setg(errp, "iSCSI: Failed to connect to LUN : %s", iscsi_get_error(iscsi)); ret = -EINVAL; @@ -1712,7 +1798,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, iscsilun->iscsi = iscsi; iscsilun->aio_context = bdrv_get_aio_context(bs); - iscsilun->lun = iscsi_url->lun; + iscsilun->lun = lun; iscsilun->has_write_same = true; task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0, @@ -1815,9 +1901,6 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, out: qemu_opts_del(opts); g_free(initiator_name); - if (iscsi_url != NULL) { - iscsi_destroy_url(iscsi_url); - } if (task != NULL) { scsi_free_scsi_task(task); } @@ -2026,15 +2109,15 @@ static BlockDriver bdrv_iscsi = { .format_name = "iscsi", .protocol_name = "iscsi", - .instance_size = sizeof(IscsiLun), - .bdrv_needs_filename = true, - .bdrv_file_open = iscsi_open, - .bdrv_close = iscsi_close, - .bdrv_create = iscsi_create, - .create_opts = &iscsi_create_opts, - .bdrv_reopen_prepare = iscsi_reopen_prepare, - .bdrv_reopen_commit = iscsi_reopen_commit, - .bdrv_invalidate_cache = iscsi_invalidate_cache, + .instance_size = sizeof(IscsiLun), + .bdrv_parse_filename = iscsi_parse_filename, + .bdrv_file_open = iscsi_open, + .bdrv_close = iscsi_close, + .bdrv_create = iscsi_create, + .create_opts = &iscsi_create_opts, + .bdrv_reopen_prepare = iscsi_reopen_prepare, + .bdrv_reopen_commit = iscsi_reopen_commit, + .bdrv_invalidate_cache = iscsi_invalidate_cache, .bdrv_getlength = iscsi_getlength, .bdrv_get_info = iscsi_get_info, @@ -2061,15 +2144,15 @@ static BlockDriver bdrv_iser = { .format_name = "iser", .protocol_name = "iser", - .instance_size = sizeof(IscsiLun), - .bdrv_needs_filename = true, - .bdrv_file_open = iscsi_open, - .bdrv_close = iscsi_close, - .bdrv_create = iscsi_create, - .create_opts = &iscsi_create_opts, - .bdrv_reopen_prepare = iscsi_reopen_prepare, - .bdrv_reopen_commit = iscsi_reopen_commit, - .bdrv_invalidate_cache = iscsi_invalidate_cache, + .instance_size = sizeof(IscsiLun), + .bdrv_parse_filename = iscsi_parse_filename, + .bdrv_file_open = iscsi_open, + .bdrv_close = iscsi_close, + .bdrv_create = iscsi_create, + .create_opts = &iscsi_create_opts, + .bdrv_reopen_prepare = iscsi_reopen_prepare, + .bdrv_reopen_commit = iscsi_reopen_commit, + .bdrv_invalidate_cache = iscsi_invalidate_cache, .bdrv_getlength = iscsi_getlength, .bdrv_get_info = iscsi_get_info,
This introduces a .bdrv_parse_filename handler for iscsi which parses an URL if given and translates it to individual options. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- block/iscsi.c | 189 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 136 insertions(+), 53 deletions(-)