From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50136) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XFo9k-00047L-RN for qemu-devel@nongnu.org; Fri, 08 Aug 2014 13:40:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XFo9f-0006fx-Af for qemu-devel@nongnu.org; Fri, 08 Aug 2014 13:40:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38335) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XFo9e-0006fj-So for qemu-devel@nongnu.org; Fri, 08 Aug 2014 13:40:39 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s78HecuS016899 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 8 Aug 2014 13:40:38 -0400 From: Kevin Wolf Date: Fri, 8 Aug 2014 19:39:24 +0200 Message-Id: <1407519603-6635-24-git-send-email-kwolf@redhat.com> In-Reply-To: <1407519603-6635-1-git-send-email-kwolf@redhat.com> References: <1407519603-6635-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PULL 23/62] block/archipelago: Implement bdrv_parse_filename() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com From: Chrysostomos Nanakos VM Image on Archipelago volume can also be specified like this: file=archipelago:[/mport=[:vport=][: segment=]] Examples: file=archipelago:my_vm_volume file=archipelago:my_vm_volume/mport=123 file=archipelago:my_vm_volume/mport=123:vport=1234 file=archipelago:my_vm_volume/mport=123:vport=1234:segment=my_segment Signed-off-by: Chrysostomos Nanakos Signed-off-by: Stefan Hajnoczi --- block/archipelago.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/block/archipelago.c b/block/archipelago.c index d91872d..297fc27 100644 --- a/block/archipelago.c +++ b/block/archipelago.c @@ -15,6 +15,11 @@ * [,file.mport=[,file.vport=] * [,file.segment=]] * + * or + * + * file=archipelago:[/mport=[:vport=][: + * segment=]] + * * 'archipelago' is the protocol. * * 'mport' is the port number on which mapperd is listening. This is optional @@ -32,11 +37,20 @@ * file.driver=archipelago,file.volume=my_vm_volume * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123 * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123, - * file.vport=1234 + * file.vport=1234 * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123, - * file.vport=1234,file.segment=my_segment + * file.vport=1234,file.segment=my_segment + * + * or + * + * file=archipelago:my_vm_volume + * file=archipelago:my_vm_volume/mport=123 + * file=archipelago:my_vm_volume/mport=123:vport=1234 + * file=archipelago:my_vm_volume/mport=123:vport=1234:segment=my_segment + * */ +#include "qemu-common.h" #include "block/block_int.h" #include "qemu/error-report.h" #include "qemu/thread.h" @@ -309,6 +323,127 @@ static void qemu_archipelago_complete_aio(void *opaque) g_free(reqdata); } +static void xseg_find_port(char *pstr, const char *needle, xport *aport) +{ + const char *a; + char *endptr = NULL; + unsigned long port; + if (strstart(pstr, needle, &a)) { + if (strlen(a) > 0) { + port = strtoul(a, &endptr, 10); + if (strlen(endptr)) { + *aport = -2; + return; + } + *aport = (xport) port; + } + } +} + +static void xseg_find_segment(char *pstr, const char *needle, + char **segment_name) +{ + const char *a; + if (strstart(pstr, needle, &a)) { + if (strlen(a) > 0) { + *segment_name = g_strdup(a); + } + } +} + +static void parse_filename_opts(const char *filename, Error **errp, + char **volume, char **segment_name, + xport *mport, xport *vport) +{ + const char *start; + char *tokens[4], *ds; + int idx; + xport lmport = NoPort, lvport = NoPort; + + strstart(filename, "archipelago:", &start); + + ds = g_strdup(start); + tokens[0] = strtok(ds, "/"); + tokens[1] = strtok(NULL, ":"); + tokens[2] = strtok(NULL, ":"); + tokens[3] = strtok(NULL, "\0"); + + if (!strlen(tokens[0])) { + error_setg(errp, "volume name must be specified first"); + g_free(ds); + return; + } + + for (idx = 1; idx < 4; idx++) { + if (tokens[idx] != NULL) { + if (strstart(tokens[idx], "mport=", NULL)) { + xseg_find_port(tokens[idx], "mport=", &lmport); + } + if (strstart(tokens[idx], "vport=", NULL)) { + xseg_find_port(tokens[idx], "vport=", &lvport); + } + if (strstart(tokens[idx], "segment=", NULL)) { + xseg_find_segment(tokens[idx], "segment=", segment_name); + } + } + } + + if ((lmport == -2) || (lvport == -2)) { + error_setg(errp, "mport and/or vport must be set"); + g_free(ds); + return; + } + *volume = g_strdup(tokens[0]); + *mport = lmport; + *vport = lvport; + g_free(ds); +} + +static void archipelago_parse_filename(const char *filename, QDict *options, + Error **errp) +{ + const char *start; + char *volume = NULL, *segment_name = NULL; + xport mport = NoPort, vport = NoPort; + + if (qdict_haskey(options, ARCHIPELAGO_OPT_VOLUME) + || qdict_haskey(options, ARCHIPELAGO_OPT_SEGMENT) + || qdict_haskey(options, ARCHIPELAGO_OPT_MPORT) + || qdict_haskey(options, ARCHIPELAGO_OPT_VPORT)) { + error_setg(errp, "volume/mport/vport/segment and a file name may not" + " be specified at the same time"); + return; + } + + if (!strstart(filename, "archipelago:", &start)) { + error_setg(errp, "File name must start with 'archipelago:'"); + return; + } + + if (!strlen(start) || strstart(start, "/", NULL)) { + error_setg(errp, "volume name must be specified"); + return; + } + + parse_filename_opts(filename, errp, &volume, &segment_name, &mport, &vport); + + if (volume) { + qdict_put(options, ARCHIPELAGO_OPT_VOLUME, qstring_from_str(volume)); + g_free(volume); + } + if (segment_name) { + qdict_put(options, ARCHIPELAGO_OPT_SEGMENT, + qstring_from_str(segment_name)); + g_free(segment_name); + } + if (mport != NoPort) { + qdict_put(options, ARCHIPELAGO_OPT_MPORT, qint_from_int(mport)); + } + if (vport != NoPort) { + qdict_put(options, ARCHIPELAGO_OPT_VPORT, qint_from_int(vport)); + } +} + static QemuOptsList archipelago_runtime_opts = { .name = "archipelago", .head = QTAILQ_HEAD_INITIALIZER(archipelago_runtime_opts.head), @@ -770,6 +905,7 @@ static BlockDriver bdrv_archipelago = { .format_name = "archipelago", .protocol_name = "archipelago", .instance_size = sizeof(BDRVArchipelagoState), + .bdrv_parse_filename = archipelago_parse_filename, .bdrv_file_open = qemu_archipelago_open, .bdrv_close = qemu_archipelago_close, .bdrv_getlength = qemu_archipelago_getlength, -- 1.8.3.1