GlusterFS support in QEMU - v9
Subsystems (2)
v9 cover GlusterFS support in QEMU - v9
Hi,
This is v9 of the patchset to support GlusterFS backend from QEMU.
Changes in v9
-------------
- Drop all inet_parse related patches from the patchset.
- Include generic URI parsing code from libxml2 and libvirt in QEMU and use that in gluster block backend instead of private URI parsing implementation within gluster.
Previous versions can be found here:
v8 - http://lists.gnu.org/archive/html/qemu-devel/2012-09/msg04007.html
v7 - http://lists.nongnu.org/archive/html/qemu-devel/2012-09/msg02532.html
v6 - http://lists.nongnu.org/archive/html/qemu-devel/2012-08/msg01536.html
v5 - http://lists.nongnu.org/archive/html/qemu-devel/2012-08/msg01023.html
v4 - http://lists.nongnu.org/archive/html/qemu-devel/2012-08/msg00147.html
v3 - http://lists.nongnu.org/archive/html/qemu-devel/2012-07/msg03322.html
v2 - http://lists.nongnu.org/archive/html/qemu-devel/2012-07/msg02718.html
v1 - http://lists.nongnu.org/archive/html/qemu-devel/2012-06/msg01745.html
Regards,
Bharata.
PATCH v9 1/4 aio: Fix qemu_aio_wait() to maintain correct walking_handlers count
aio: Fix qemu_aio_wait() to maintain correct walking_handlers count
From: Paolo Bonzini <[email protected]>
Fix qemu_aio_wait() to ensure that registered aio handlers don't get deleted when they are still active. This is ensured by maintaning the right count of walking_handlers.
---
aio.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
aio.c +4 -4
@@ -119,7 +119,7 @@ bool qemu_aio_wait(void)return true; } - walking_handlers =1 ; + walking_handlers++;FD_ZERO (&rdfds);FD_ZERO (&wrfds);
@@ -147,7 +147,7 @@ bool qemu_aio_wait(void) } } - walking_handlers =0 ; + walking_handlers--;/* No AIO operations? Get us out of here */ if (!busy) {
@@ -159,7 +159,7 @@ bool qemu_aio_wait(void)/* if we have any readable fds, dispatch event */ if (ret >0 ) { - walking_handlers =1 ; + walking_handlers++;/* we have to walk very carefully in case * qemu_aio_set_fd_handler is called while we're walking */
@@ -187,7 +187,7 @@ bool qemu_aio_wait(void) } } - walking_handlers =0 ; + walking_handlers--; }return true;
PATCH v9 2/4 qemu: URI parsing library
In reply to Bharata B Raoqemu: URI parsing library
From: Paolo Bonzini <[email protected]>
Add a new URI parsing library to QEMU. The code has been borrowed from libxml2 and libvirt.
---
Makefile.objs | 2 uri.c | 2249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ uri.h | 113 +++ 3 files changed, 2363 insertions(+), 1 deletions(-) create mode 100644 uri.c create mode 100644 uri.h
Makefile.objs +1 -1
@@ -42,7 +42,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o -block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o +block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o uri.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
uri.c new file +2249 -0
2,249 lines not on this page · raw message
uri.h new file +113 -0
113 lines not on this page · raw message
Re: [Qemu-devel] [PATCH v9 2/4] qemu: URI parsing library
Quoted 6 lines · Bharata B Rao
qemu: URI parsing library
From: Paolo Bonzini <[email protected]>
Add a new URI parsing library to QEMU. The code has been borrowed from libxml2 and libvirt.
Rather than duplicating the libxml2 code, I think it would be better to depend on libxml2. While it's not ideal to add more external dependencies, libxml2 is very commonly available. Also libxml2 gets frequent security updates and you never know when the URI code here might be found to contain some sort of bug / security issue.
This will need a change to the qemu configure script of course.
Rich.
Signature · 4 lines
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/
Re: [Qemu-devel] [PATCH v9 2/4] qemu: URI parsing library
----- Messaggio originale -----
Quoted 15 lines
Da: "Richard W.M. Jones" <[email protected]>
A: "Bharata B Rao" <[email protected]>
Cc: [email protected], "Paolo Bonzini" <[email protected]>, "Kevin Wolf" <[email protected]>, "Avi Kivity" <[email protected]>, "Anthony Liguori" <[email protected]>, "Stefan Hajnoczi" <[email protected]>, "Blue Swirl" <[email protected]>, "Anand Avati" <[email protected]>, "Vijay Bellur" <[email protected]>, "Amar Tumballi" <[email protected]>, "Harsh Bora" <[email protected]>, "Daniel Veillard" <[email protected]>
Inviato: Lunedì, 24 settembre 2012 12:27:38
Oggetto: Re: [PATCH v9 2/4] qemu: URI parsing libraryQuoted 4 lines · Bharata B Rao
qemu: URI parsing library
From: Paolo Bonzini <[email protected]>
Quoted 8 lines
Quoted 2 lines
Add a new URI parsing library to QEMU. The code has been borrowed from libxml2 and libvirt.
Rather than duplicating the libxml2 code, I think it would be better to depend on libxml2. While it's not ideal to add more external dependencies, libxml2 is very commonly available. Also libxml2 gets frequent security updates and you never know when the URI code here might be found to contain some sort of bug / security issue.
You're preaching to the choir here, but I think there are limited advantages in this case. The URI parsing has seen hardly any change in the last 2 years and is surprisingly self-contained even in libxml2:
the dependencies were limited to memory allocation hooks basically.
A better plan would be to incorporate this code into glib, completing the extremely sparse URI support that is already there. However, we would not be able to use it anyway, because we support compiling on old glib versions.
Paolo
Quoted 11 lines
This will need a change to the qemu configure script of course.
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows.
http://et.redhat.com/~rjones/virt-df/
Re: [Qemu-devel] [PATCH v9 2/4] qemu: URI parsing library
Quoted 5 lines · Paolo Bonzini
A better plan would be to incorporate this code into glib, completing the extremely sparse URI support that is already there. However, we would not be able to use it anyway, because we support compiling on old glib versions.
If the same (or very similar) API is retained, we could fall back on libxml2 when glib uri parsing is unavailable. Eventually we bump our minimum version requirement and drop the libxml2 dependency (or find out that xml has invaded our code base and we can't get rid of it).
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [Qemu-devel] [PATCH v9 2/4] qemu: URI parsing library
Il 27/09/2012 11:03, Avi Kivity ha scritto:
Quoted 7 lines · Paolo Bonzini
Quoted 4 lines
A better plan would be to incorporate this code into glib, completing the extremely sparse URI support that is already there. However, we would not be able to use it anyway, because we support compiling on old glib versions.
If the same (or very similar) API is retained,
Yes, there is exactly one change in the API (modulo renaming) so we could just use some #defines or wrappers.
Quoted 2 lines
we could fall back on
libxml2 when glib uri parsing is unavailable.
That's an interesting idea. The assumption that glib wants URI parsing is not proved, but it may work out.
Paolo
Quoted 3 lines
Eventually we bump our
minimum version requirement and drop the libxml2 dependency (or find out that xml has invaded our code base and we can't get rid of it).
Re: [Qemu-devel] [PATCH v9 2/4] qemu: URI parsing library
Quoted 11 lines · Paolo Bonzini
Il 27/09/2012 11:03, Avi Kivity ha scritto:
Quoted 7 lines · Paolo Bonzini
Quoted 4 lines
A better plan would be to incorporate this code into glib, completing the extremely sparse URI support that is already there. However, we would not be able to use it anyway, because we support compiling on old glib versions.
If the same (or very similar) API is retained,
Yes, there is exactly one change in the API (modulo renaming) so we could just use some #defines or wrappers.
BTW I'm fine by this assuming:
- someone keeps an eye on libxml2 upstream in case some security problem shows up in that part of the code
- the code used is the 2.9.0 one where I added quite a bit of cleanup on memory handling.
Quoted 5 lines
Quoted 2 lines
we could fall back on
libxml2 when glib uri parsing is unavailable.That's an interesting idea. The assumption that glib wants URI parsing is not proved, but it may work out.
Well glib coding style and libxml2 one are fairly different, assuming
you get the change into glib, that will be a relatively different code base (my recollection is that glib exits on allocation error which tend to impact API design so this may be more complex than just different naming for the functions).
Daniel
Signature · 3 lines
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ [email protected] | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
Re: [Qemu-devel] [PATCH v9 2/4] qemu: URI parsing library
Quoted 4 lines
BTW I'm fine by this assuming:
- someone keeps an eye on libxml2 upstream in case some security problem shows up in that part of the code
Yes.
Quoted 2 lines
- the code used is the 2.9.0 one where I added quite a bit of cleanup on memory handling.
It is, modulo the fact that QEMU uses glib functions and thus exits on allocation error.
The QEMU code would be a good starting point to add a glib URI module.
Paolo
PATCH v9 3/4 configure: Add a config option for GlusterFS as block backend
In reply to Bharata B Raoconfigure: Add a config option for GlusterFS as block backend
From: Bharata B Rao <[email protected]>
GlusterFS support in QEMU depends on libgfapi, libgfrpc and libgfxdr provided by GlusterFS.
---
configure | 35 +++++++++++++++++++++++++++++++++++ 1 files changed, 35 insertions(+), 0 deletions(-)
configure +35 -0
@@ -219,6 +219,7 @@ want_tools="yes" libiscsi="" coroutine="" seccomp="" +glusterfs="" # parse CC options first for opt do
@@ -856,6 +857,10 @@ for opt do ;; --disable-seccomp) seccomp="no" ;; + --disable-glusterfs) glusterfs="no" + ;; + --enable-glusterfs) glusterfs="yes" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac
@@ -1128,6 +1133,8 @@ echo " --disable-seccomp disable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" echo " gthread, ucontext, sigaltstack, windows" +echo " --enable-glusterfs enable GlusterFS backend" +echo " --disable-glusterfs disable GlusterFS backend" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1
@@ -2307,6 +2314,29 @@ EOF fi fi +########################################## +# glusterfs probe +if test "$glusterfs" != "no" ; then + cat > $TMPC <<EOF +#include <glusterfs/api/glfs.h> +int main(void) { + (void) glfs_new("volume"); + return 0; +} +EOF + glusterfs_libs="-lgfapi -lgfrpc -lgfxdr" + if compile_prog "" "$glusterfs_libs" ; then + glusterfs=yes + libs_tools="$glusterfs_libs $libs_tools" + libs_softmmu="$glusterfs_libs $libs_softmmu" + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" + fi + glusterfs=no + fi +fi + # # Check for xxxat() functions when we are building linux-user # emulator. This is done because older glibc versions don't
@@ -3174,6 +3204,7 @@ echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" +echo "GlusterFS support $glusterfs" if test "$sdl_too_old" = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -3520,6 +3551,10 @@ if test "$has_environ" = "yes" ; then echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak fi +if test "$glusterfs" = "yes" ; then + echo "CONFIG_GLUSTERFS=y" >> $config_host_mak +fi + # USB host support case "$usb" in linux)
PATCH v9 4/4 block: Support GlusterFS as a QEMU block backend.
In reply to Bharata B Raoblock: Support GlusterFS as a QEMU block backend.
From: Bharata B Rao <[email protected]>
This patch adds gluster as the new block backend in QEMU. This gives QEMU the ability to boot VM images from gluster volumes. Its already possible to boot from VM images on gluster volumes using FUSE mount, but this patchset provides the ability to boot VM images from gluster volumes by by-passing the FUSE layer in gluster. This is made possible by using libgfapi routines to perform IO on gluster volumes directly.
VM Image on gluster volume is specified like this:
file=gluster[+transport]://[server[:port]]/volname/image[?socket=...]
'gluster' is the protocol.
'transport' specifies the transport type used to connect to gluster management daemon (glusterd). Valid transport types are tcp, unix and rdma. If a transport type isn't specified, then tcp type is assumed.
'server' specifies the server where the volume file specification for the given volume resides. This can be either hostname, ipv4 address or ipv6 address. ipv6 address needs to be within square brackets [ ]. If transport type is 'unix', then server field is ignored, but the 'socket' field needs to be populated with the path to unix domain socket.
'port' is the port number on which glusterd is listening. This is optional and if not specified, QEMU will send 0 which will make gluster to use the default port. port is ignored for unix type of transport.
'volname' is the name of the gluster volume which contains the VM image.
'image' is the path to the actual VM image that resides on gluster volume.
Examples:
file=gluster://1.2.3.4/testvol/a.img file=gluster+tcp://1.2.3.4/testvol/a.img file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket file=gluster+rdma://1.2.3.4:24007/testvol/a.img
---
block/Makefile.objs | 1 block/gluster.c | 642 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 643 insertions(+), 0 deletions(-) create mode 100644 block/gluster.c
block/Makefile.objs +1 -0
@@ -9,3 +9,4 @@ block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o +block-obj-$(CONFIG_GLUSTERFS) += gluster.o
block/gluster.c new file +642 -0
642 lines not on this page · raw message
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Quoted 32 lines
block/gluster.c new file +32
-0+static int qemu_gluster_parseuri (GlusterConf *gconf,const char *filename) +{ +URI *uri; +QueryParams *qp =NULL ; +bool is_unix = false; +int ret =0 ; +char *unescape_str =NULL ; + + uri =uri_parse (filename); +if (!uri) { +return -EINVAL ; + } + +/* transport */ +if (!strcmp (uri->scheme,"gluster" )) { + gconf->transport =g_strdup ("tcp" ); + }else if (!strcmp (uri->scheme,"gluster+tcp" )) { + gconf->transport =g_strdup ("tcp" ); + }else if (!strcmp (uri->scheme,"gluster+unix" )) { + gconf->transport =g_strdup ("unix" ); + is_unix = true; + }else if (!strcmp (uri->scheme,"gluster+rdma" )) { + gconf->transport =g_strdup ("rdma" ); + }else { + ret = -EINVAL ; + goto out; + } + + ret =parse_volume_options (gconf, uri->path); +if (ret <0 ) { + goto out; + }
block/gluster.c line 157
Quoted 10 lines
block/gluster.c new file +10
-0+ +if (uri->query) { + unescape_str =uri_string_unescape (uri->query,-1 ,NULL ); +if (!unescape_str) { + ret = -EINVAL ; + goto out; + } + } + + qp =query_params_parse (unescape_str);
query_params_parse already does the unescaping.
Paolo
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Quoted 3 lines · Paolo Bonzini
Quoted 1 line
+ qp =
query_params_parse(unescape_str);
query_params_parsealready does the unescaping.
Hmm it failed to parse the options properly when I had an escape sequence, hence resorted to unescaping the query string manually.
Look at the below gdb debug steps of your uri.c...
2302 test("gluster+unix:///b?c=d%26e=f");
(gdb) s
test (x=0x4062c4 "gluster+unix:///b?c=d%26e=f") at uri.c:2279
2279 URI *uri = uri_parse(x);
(gdb) n
2283 if (!uri) {
(gdb) p *uri
$1 = {scheme = 0x607070 "gluster+unix", opaque = 0x0, authority = 0x0,
server = 0x0, user = 0x0, port = 0, path = 0x607090 "/b", fragment = 0x0, cleanup = 0, query = 0x6070b0 "c=d%26e=f"}
(gdb) n
2289 qp = query_params_parse(uri->query);
(gdb) p *qp
$2 = {n = 1, alloc = 1, p = 0x6070f0}
You can see that qp->n is still 1, but 2 was expected.
Regards,
Bharata.
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
In reply to Bharata B RaoAm 24.09.2012 11:13, schrieb Bharata B Rao:
Quoted 134 lines
block: Support GlusterFS as a QEMU block backend.
From: Bharata B Rao <[email protected]>
This patch adds gluster as the new block backend in QEMU. This gives QEMU the ability to boot VM images from gluster volumes. Its already possible to boot from VM images on gluster volumes using FUSE mount, but this patchset provides the ability to boot VM images from gluster volumes by by-passing the FUSE layer in gluster. This is made possible by using libgfapi routines to perform IO on gluster volumes directly.
VM Image on gluster volume is specified like this:
file=gluster[+transport]://[server[:port]]/volname/image[?socket=...]
'gluster' is the protocol.
'transport' specifies the transport type used to connect to gluster management daemon (glusterd). Valid transport types are tcp, unix and rdma. If a transport type isn't specified, then tcp type is assumed.
'server' specifies the server where the volume file specification for the given volume resides. This can be either hostname, ipv4 address or ipv6 address. ipv6 address needs to be within square brackets [ ]. If transport type is 'unix', then server field is ignored, but the 'socket' field needs to be populated with the path to unix domain socket.
'port' is the port number on which glusterd is listening. This is optional and if not specified, QEMU will send 0 which will make gluster to use the default port. port is ignored for unix type of transport.
'volname' is the name of the gluster volume which contains the VM image.
'image' is the path to the actual VM image that resides on gluster volume.
Examples:
file=gluster://1.2.3.4/testvol/a.img file=gluster+tcp://1.2.3.4/testvol/a.img file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket file=gluster+rdma://1.2.3.4:24007/testvol/a.img
Signed-off-by Bharata B Rao <[email protected]>---
block/Makefile.objs | 1 block/gluster.c | 642 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 643 insertions(+), 0 deletions(-) create mode 100644 block/gluster.cblock/Makefile.objs +1
-0@@ -9,3 +9,4 @@ block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o +block-obj-$(CONFIG_GLUSTERFS) += gluster.oblock/gluster.c new file +62
-0@@ -0,0 +1,642 @@ +/* +* GlusterFS backend for QEMU +* +* Copyright (C) 2012 Bharata B Rao <[email protected]> +* +* Pipe handling mechanism in AIO implementation is derived from +* block/rbd.c. Hence, +* +* Copyright (C) 2010-2011 Christian Brunner <[email protected]>, +* Josh Durgin <[email protected]> +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the COPYING file in the top-level directory. +* +* Contributions after 2012-01-13 are licensed under the terms of the +* GNU GPL, version 2 or (at your option) any later version. +*/ +#include <glusterfs/api/glfs.h> +#include "block_int.h" +#include "qemu_socket.h" +#include "uri.h" + +typedef struct GlusterAIOCB { +BlockDriverAIOCB common; +int64_t size; +int ret; +bool *finished; +QEMUBH *bh; +}GlusterAIOCB ; + +typedef struct BDRVGlusterState { +struct glfs *glfs; +int fds[2 ]; +struct glfs_fd *fd; +int qemu_aio_count; +int event_reader_pos; +GlusterAIOCB *event_acb; +}BDRVGlusterState ; + +#define GLUSTER_FD_READ 0 +#define GLUSTER_FD_WRITE 1 + +typedef struct GlusterConf { +char *server; +int port; +char *volname; +char *image; +char *transport; +}GlusterConf ; + +static void qemu_gluster_gconf_free (GlusterConf *gconf) +{ +g_free (gconf->server); +g_free (gconf->volname); +g_free (gconf->image); +g_free (gconf->transport); +g_free (gconf); +} + +static int parse_volume_options (GlusterConf *gconf,char *path) +{ +char *token, *saveptr;
block/gluster.c line 72
Quoted 10 lines
block/gluster.c new file +10
-0+ +/* volname */ + token =strtok_r (path,"/" , &saveptr); +if (!token) { +return -EINVAL ; + } + gconf->volname =g_strdup (token); + +/* image */ + token =strtok_r (NULL ,"?" , &saveptr);
If I understand uri.c right, there is no ? in the path, so there's no reason to call strtok. You could just use the rest of the string.
Quoted 73 lines
block/gluster.c new file +73
-0+if (!token) { +return -EINVAL ; + } + gconf->image =g_strdup (token); +return 0 ; +} + +/* +* file=gluster[+transport]://[server[:port]]/volname/image[?socket=...] +* +* 'gluster' is the protocol. +* +* 'transport' specifies the transport type used to connect to gluster +* management daemon (glusterd). Valid transport types are +* tcp, unix and rdma. If a transport type isn't specified, then tcp +* type is assumed. +* +* 'server' specifies the server where the volume file specification for +* the given volume resides. This can be either hostname, ipv4 address +* or ipv6 address. ipv6 address needs to be within square brackets [ ]. +* If transport type is 'unix', then server field is ignored, but the +* 'socket' field needs to be populated with the path to unix domain +* socket. +* +* 'port' is the port number on which glusterd is listening. This is optional +* and if not specified, QEMU will send 0 which will make gluster to use the +* default port. port is ignored for unix type of transport. +* +* 'volname' is the name of the gluster volume which contains the VM image. +* +* 'image' is the path to the actual VM image that resides on gluster volume. +* +* Examples: +* +* file=gluster://1.2.3.4/testvol/a.img +* file=gluster+tcp://1.2.3.4/testvol/a.img +* file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img +* file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img +* file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img +* file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img +* file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket +* file=gluster+rdma://1.2.3.4:24007/testvol/a.img +*/ +static int qemu_gluster_parseuri (GlusterConf *gconf,const char *filename) +{ +URI *uri; +QueryParams *qp =NULL ; +bool is_unix = false; +int ret =0 ; +char *unescape_str =NULL ; + + uri =uri_parse (filename); +if (!uri) { +return -EINVAL ; + } + +/* transport */ +if (!strcmp (uri->scheme,"gluster" )) { + gconf->transport =g_strdup ("tcp" ); + }else if (!strcmp (uri->scheme,"gluster+tcp" )) { + gconf->transport =g_strdup ("tcp" ); + }else if (!strcmp (uri->scheme,"gluster+unix" )) { + gconf->transport =g_strdup ("unix" ); + is_unix = true; + }else if (!strcmp (uri->scheme,"gluster+rdma" )) { + gconf->transport =g_strdup ("rdma" ); + }else { + ret = -EINVAL ; + goto out; + } + + ret =parse_volume_options (gconf, uri->path); +if (ret <0 ) {
block/gluster.c line 155
Quoted 10 lines
block/gluster.c new file +10
-0+ goto out; + } + +if (uri->query) { + unescape_str =uri_string_unescape (uri->query,-1 ,NULL ); +if (!unescape_str) { + ret = -EINVAL ; + goto out; + } + }
I agree with Paolo here, this need to go away.
The example that you posted ("gluster+unix:///b?c=d%26e=f") has indeed only one argument with name 'c' and value 'd&e=f'. If you unescape here, you would incorrectly require double escaping.
block/gluster.c line 168
Quoted 13 lines
block/gluster.c new file +13
-0+ + qp =query_params_parse (unescape_str); +if (qp->n >1 || (is_unix && !qp->n) || (!is_unix && qp->n)) { + ret = -EINVAL ; + goto out; + } + +if (is_unix) { +if (strcmp (qp->p[0 ].name,"socket" )) { + ret = -EINVAL ; + goto out; + } + gconf->server =g_strdup (qp->p[0 ].value);
Maybe add a check that uri->server is empty?
Quoted 49 lines
block/gluster.c new file +49
-0+ }else { + gconf->server =g_strdup (uri->server); + gconf->port = uri->port; + } + +out: +if (qp) { +query_params_free (qp); + } +g_free (unescape_str); +uri_free (uri); +return ret; +} + +static struct glfs *qemu_gluster_init (GlusterConf *gconf,const char *filename) +{ +struct glfs *glfs =NULL ; +int ret; + + ret =qemu_gluster_parseuri (gconf, filename); +if (ret <0 ) { +error_report ("Usage: file=gluster[+transport]://[server[:port]]/" +"volname/image[?socket=...]" ); + errno = -ret; + goto out; + } + + glfs =glfs_new (gconf->volname); +if (!glfs) { + goto out; + } + + ret =glfs_set_volfile_server (glfs, gconf->transport, gconf->server, + gconf->port); +if (ret <0 ) { + goto out; + } + +/* +* TODO: Use GF_LOG_ERROR instead of hard code value of 4 here when +* GlusterFS makes GF_LOG_* macros available to libgfapi users. +*/ + ret =glfs_set_logging (glfs,"-" ,4 ); +if (ret <0 ) { + goto out; + } + + ret =glfs_init (glfs); +if (ret) {
block/gluster.c line 227
Quoted 10 lines
block/gluster.c new file +10
-0+error_report ("Gluster connection failed for server=%s port=%d " +"volume=%s image=%s transport=%s\n" , gconf->server, gconf->port, + gconf->volname, gconf->image, gconf->transport); + goto out; + } +return glfs; + +out: +if (glfs) { +glfs_fini (glfs);
Does this corrupt errno?
Quoted 60 lines
block/gluster.c new file +60
-0+ } +return NULL ; +} + +static void qemu_gluster_complete_aio (GlusterAIOCB *acb,BDRVGlusterState *s) +{ +int ret; +bool *finished = acb->finished; +BlockDriverCompletionFunc *cb = acb->common.cb; +void *opaque = acb->common.opaque; + +if (!acb->ret || acb->ret == acb->size) { + ret =0 ;/* Success */ + }else if (acb->ret <0 ) { + ret = acb->ret;/* Read/Write failed */ + }else { + ret = -EIO ;/* Partial read/write - fail it */ + } + + s->qemu_aio_count--; +qemu_aio_release (acb); +cb (opaque, ret); +if (finished) { + *finished = true; + } +} + +static void qemu_gluster_aio_event_reader (void *opaque) +{ +BDRVGlusterState *s = opaque; +ssize_t ret; + +do { +char *p = (char *)&s->event_acb; + + ret =read (s->fds[GLUSTER_FD_READ ], p + s->event_reader_pos, +sizeof (s->event_acb) - s->event_reader_pos); +if (ret >0 ) { + s->event_reader_pos += ret; +if (s->event_reader_pos ==sizeof (s->event_acb)) { + s->event_reader_pos =0 ; +qemu_gluster_complete_aio (s->event_acb, s); + } + } + }while (ret <0 && errno ==EINTR ); +} + +static int qemu_gluster_aio_flush_cb (void *opaque) +{ +BDRVGlusterState *s = opaque; + +return (s->qemu_aio_count >0 ); +} + +static int qemu_gluster_open (BlockDriverState *bs,const char *filename, +int bdrv_flags) +{ +BDRVGlusterState *s = bs->opaque; +int open_flags =0 ; +int ret =0 ;
block/gluster.c line 297
Quoted 10 lines
block/gluster.c new file +10
-0+GlusterConf *gconf =g_malloc0 (sizeof (GlusterConf)); + + s->glfs =qemu_gluster_init (gconf, filename); +if (!s->glfs) { + ret = -errno; + goto out; + } + + open_flags |=O_BINARY ; + open_flags &= ~O_ACCMODE ;
open_flags == O_BINARY here, so no O_ACCMODE bits to clear.
Quoted 104 lines
block/gluster.c new file +104
-0+if (bdrv_flags &BDRV_O_RDWR ) { + open_flags |=O_RDWR ; + }else { + open_flags |=O_RDONLY ; + } + +if ((bdrv_flags &BDRV_O_NOCACHE )) { + open_flags |=O_DIRECT ; + } + + s->fd =glfs_open (s->glfs, gconf->image, open_flags); +if (!s->fd) { + ret = -errno; + goto out; + } + + ret =qemu_pipe (s->fds); +if (ret <0 ) { + ret = -errno; + goto out; + } +fcntl (s->fds[GLUSTER_FD_READ ],F_SETFL ,O_NONBLOCK ); +qemu_aio_set_fd_handler (s->fds[GLUSTER_FD_READ ], + qemu_gluster_aio_event_reader,NULL , qemu_gluster_aio_flush_cb, s); + +out: +qemu_gluster_gconf_free (gconf); +if (!ret) { +return ret; + } +if (s->fd) { +glfs_close (s->fd); + } +if (s->glfs) { +glfs_fini (s->glfs); + } +return ret; +} + +static int qemu_gluster_create (const char *filename, +QEMUOptionParameter *options) +{ +struct glfs *glfs; +struct glfs_fd *fd; +int ret =0 ; +int64_t total_size =0 ; +GlusterConf *gconf =g_malloc0 (sizeof (GlusterConf)); + + glfs =qemu_gluster_init (gconf, filename); +if (!glfs) { + ret = -errno; + goto out; + } + +while (options && options->name) { +if (!strcmp (options->name,BLOCK_OPT_SIZE )) { + total_size = options->value.n /BDRV_SECTOR_SIZE ; + } + options++; + } + + fd =glfs_creat (glfs, gconf->image, +O_WRONLY |O_CREAT |O_TRUNC |O_BINARY ,S_IRUSR |S_IWUSR ); +if (!fd) { + ret = -errno; + }else { +if (glfs_ftruncate (fd, total_size *BDRV_SECTOR_SIZE ) !=0 ) { + ret = -errno; + } +if (glfs_close (fd) !=0 ) { + ret = -errno; + } + } +out: +qemu_gluster_gconf_free (gconf); +if (glfs) { +glfs_fini (glfs); + } +return ret; +} + +static void qemu_gluster_aio_cancel (BlockDriverAIOCB *blockacb) +{ +GlusterAIOCB *acb = (GlusterAIOCB *)blockacb; +bool finished = false; + + acb->finished = &finished; +while (!finished) { +qemu_aio_wait (); + } +} + +static AIOPool gluster_aio_pool = { + .aiocb_size =sizeof (GlusterAIOCB), + .cancel = qemu_gluster_aio_cancel, +}; + +static int qemu_gluster_send_pipe (BDRVGlusterState *s,GlusterAIOCB *acb) +{ +int ret =0 ; + +while (1 ) { +int fd = s->fds[GLUSTER_FD_WRITE ]; +
block/gluster.c line 411
Quoted 10 lines
block/gluster.c new file +10
-0+ ret =write (fd, (void *)&acb,sizeof (acb)); +if (ret >=0 ) { +break ; + } +if (errno ==EINTR ) { +continue ; + } +if (errno !=EAGAIN ) { +break ; + }
Variatio delectat? ;-)
How about just do { ... } while (errno == EINTR || errno == EAGAIN); ?
block/gluster.c line 181
Quoted 3 lines
block/gluster.c new file +3
-0+ } +return ret; +}
Kevin
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Il 26/09/2012 12:00, Kevin Wolf ha scritto:
Quoted 11 lines
Quoted 11 lines
block/gluster.c line 411
Quoted 11 lines
block/gluster.c new file +11
-0+ + ret =write (fd, (void *)&acb,sizeof (acb)); +if (ret >=0 ) { +break ; + } +if (errno ==EINTR ) { +continue ; + } +if (errno !=EAGAIN ) { +break ; + }
Quoted 3 lines
Variatio delectat? ;-)
How about just do { ... } while (errno == EINTR || errno == EAGAIN); ?
That should be
while ((ret < 0) && (errno == EINTR || errno == EAGAIN));
However, fd here is blocking, so you can just use qemu_write_full.
Paolo
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
In reply to Kevin WolfQuoted 17 lines · Kevin Wolf
Am 24.09.2012 11:13, schrieb Bharata B Rao:
block/gluster.c line 72
Quoted 13 lines
block/gluster.c new file +13
-0+static int parse_volume_options (GlusterConf *gconf,char *path) +{ +char *token, *saveptr; + +/* volname */ + token =strtok_r (path,"/" , &saveptr); +if (!token) { +return -EINVAL ; + } + gconf->volname =g_strdup (token); + +/* image */ + token =strtok_r (NULL ,"?" , &saveptr);If I understand
uri.cright, there is no ? in the path, so there's no reason to call strtok. You could just use the rest of the string.
As you note, I don't need 2nd strtok strictly since the rest of the string is available in saveptr. But I thought using saveptr is not ideal or preferred. I wanted to use the most appropriate/safe delimiter to extract the image string in the 2nd strtok and decided to use '?'.
If you think using saveptr is fine, then I could use that as below...
/* image */
if (!*saveptr) {
return -EINVAL;
}
gconf->image = g_strdup(saveptr);Quoted 10 lines
Quoted 10 lines
block/gluster.c new file +9
-0+if (!token) { +return -EINVAL ; + } + gconf->image =g_strdup (token); +return 0 ; +} + + +if (uri->query) {
Quoted 8 lines
block/gluster.c line 155
Quoted 6 lines
block/gluster.c new file +6
-0+ unescape_str =uri_string_unescape (uri->query,-1 ,NULL ); +if (!unescape_str) { + ret = -EINVAL ; + goto out; + } + }I agree with Paolo here, this need to go away.
Ok will do that.
Quoted 9 lines
block/gluster.c line 168
Quoted 7 lines
block/gluster.c new file +7
-0+ +if (is_unix) { +if (strcmp (qp->p[0 ].name,"socket" )) { + ret = -EINVAL ; + goto out; + } + gconf->server =g_strdup (qp->p[0 ].value);Maybe add a check that
uri->serveris empty?
I am saying that we will ignore the server and port if transport type is unix. But I guess I will add this check and change the comments and patch description accordingly.
Quoted 54 lines
Quoted 54 lines
block/gluster.c new file +53
-0+ }else { + gconf->server =g_strdup (uri->server); + gconf->port = uri->port; + } + +out: +if (qp) { +query_params_free (qp); + } +g_free (unescape_str); +uri_free (uri); +return ret; +} + +static struct glfs *qemu_gluster_init (GlusterConf *gconf,const char *filename) +{ +struct glfs *glfs =NULL ; +int ret; + + ret =qemu_gluster_parseuri (gconf, filename); +if (ret <0 ) { +error_report ("Usage: file=gluster[+transport]://[server[:port]]/" +"volname/image[?socket=...]" ); + errno = -ret; + goto out; + } + + glfs =glfs_new (gconf->volname); +if (!glfs) { + goto out; + } + + ret =glfs_set_volfile_server (glfs, gconf->transport, gconf->server, + gconf->port); +if (ret <0 ) { + goto out; + } + +/* +* TODO: Use GF_LOG_ERROR instead of hard code value of 4 here when +* GlusterFS makes GF_LOG_* macros available to libgfapi users. +*/ + ret =glfs_set_logging (glfs,"-" ,4 ); +if (ret <0 ) { + goto out; + } + + ret =glfs_init (glfs); +if (ret) { +error_report ("Gluster connection failed for server=%s port=%d " +"volume=%s image=%s transport=%s\n" , gconf->server, gconf->port, + gconf->volname, gconf->image, gconf->transport); + goto out;
Quoted 8 lines
block/gluster.c line 227
Quoted 6 lines
block/gluster.c new file +6
-0+ } +return glfs; + +out: +if (glfs) { +glfs_fini (glfs);Does this corrupt errno?
Currently glfs_fini() isn't implemented and it returns -1. I guess it could modify errno when its implemented. At one point of time, I had a logic to save the errno value from previous calls and restore it to errno if glfs_fini() fails, but that looked ugly since I had to save errno values from 4 previous calls. Should I just save the errno from glfs_init() since that does most of the validation, connection establishment etc and is more likely to fail ?
Quoted 10 lines
Quoted 10 lines
block/gluster.c new file +10
-0+static int qemu_gluster_open (BlockDriverState *bs,const char *filename, +int bdrv_flags) +{ +BDRVGlusterState *s = bs->opaque; +int open_flags =0 ; +int ret =0 ; +GlusterConf *gconf =g_malloc0 (sizeof (GlusterConf)); + + s->glfs =qemu_gluster_init (gconf, filename); +if (!s->glfs) {
Quoted 8 lines
block/gluster.c line 297
Quoted 6 lines
block/gluster.c new file +6
-0+ ret = -errno; + goto out; + } + + open_flags |=O_BINARY ; + open_flags &= ~O_ACCMODE ;
open_flags==O_BINARYhere, so noO_ACCMODEbits to clear.
Right, will fix.
Quoted 21 lines
Quoted 8 lines
block/gluster.c new file +7
-0+static int qemu_gluster_send_pipe (BDRVGlusterState *s,GlusterAIOCB *acb) +{ +int ret =0 ; + +while (1 ) { +int fd = s->fds[GLUSTER_FD_WRITE ]; +block/gluster.c line 411
Quoted 10 lines
block/gluster.c new file +10
-0+ ret =write (fd, (void *)&acb,sizeof (acb)); +if (ret >=0 ) { +break ; + } +if (errno ==EINTR ) { +continue ; + } +if (errno !=EAGAIN ) { +break ; + }Variatio delectat? ;-)
Quoted 1 line
How about just do { ... } while (errno == EINTR || errno == EAGAIN); ?
I will go with qemu_write_full(). With that I could get rid of qemu_gluster_send_pipe() totally.
Regards,
Bharata.
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Il 26/09/2012 18:11, Bharata B Rao ha scritto:
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
+static int
parse_volume_options(GlusterConf *gconf, char *path)Quoted 4 lines
Quoted 4 lines
block/gluster.c new file +4
-0+{ +char *token, *saveptr; + +/* volname */ Quoted 8 lines
block/gluster.c line 72
Quoted 8 lines
block/gluster.c new file +8
-0+ token =strtok_r (path,"/" , &saveptr); +if (!token) { +return -EINVAL ; + } + gconf->volname =g_strdup (token); + +/* image */ + token =strtok_r (NULL ,"?" , &saveptr);If I understand
uri.cright, there is no ? in the path, so there's no reason to call strtok. You could just use the rest of the string.
Actually there could be a %3F which uri.c would unescape to ? (only the query part is left escaped), so your usage of strtok_r is incorrect.
Quoted 4 lines
As you note, I don't need 2nd strtok strictly since the rest of the string is available in saveptr. But I thought using saveptr is not ideal or preferred. I wanted to use the most appropriate/safe delimiter to extract the image string in the 2nd strtok and decided to use '?'.
I don't think it is defined what saveptr points to.
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf2/strtok_r.htm
says "the strtok_r subroutine also updates the Pointer parameter with the starting address of the token following the first occurrence of the Separators parameter". I read this as:
*saveptr = token + strlen(token) + 1;
which is consistent with this strtok example from the C standard:
#include <string.h>
static char str[] = "?a???b,";
char *t;
t = strtok(str, "?"); // t points to the token "a"
t = strtok(str, ","); // t points to the token "??b"Have you tested this code with multiple consecutive slashes?
Quoted 8 lines
If you think using saveptr is fine, then I could use that as below...
/* image */ if (!*saveptr) { return -EINVAL; } gconf->image = g_strdup(saveptr);
I would avoid strtok_r completely:
char *p = path + strcpsn(path, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->volname = g_strndup(path, p - path);
p += strspn(p, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->image = g_strdup(p);Paolo
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Quoted 18 lines · Paolo Bonzini
Il 26/09/2012 18:11, Bharata B Rao ha scritto:
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
+static int
parse_volume_options(GlusterConf *gconf, char *path)Quoted 4 lines
Quoted 4 lines
block/gluster.c new file +4
-0+{ +char *token, *saveptr; + +/* volname */ Quoted 8 lines
block/gluster.c line 72
Quoted 8 lines
block/gluster.c new file +8
-0+ token =strtok_r (path,"/" , &saveptr); +if (!token) { +return -EINVAL ; + } + gconf->volname =g_strdup (token); + +/* image */ + token =strtok_r (NULL ,"?" , &saveptr);If I understand
uri.cright, there is no ? in the path, so there's no reason to call strtok. You could just use the rest of the string.
Quoted 2 lines
Actually there could be a %3F which
uri.cwould unescape to ? (only the query part is left escaped), so your usage ofstrtok_ris incorrect.
Ok the approch of using 2 strtok as above would fail for URI's like this:
gluster+unix://server/volname/weird%3Fimage?socket=/path/to/socket
Quoted 16 lines
Quoted 5 lines
As you note, I don't need 2nd strtok strictly since the rest of the string is available in saveptr. But I thought using saveptr is not ideal or preferred. I wanted to use the most appropriate/safe delimiter to extract the image string in the 2nd strtok and decided to use '?'.
I don't think it is defined what saveptr points to.
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf2/strtok_r.htm
says "thestrtok_rsubroutine also updates the Pointer parameter with the starting address of the token following the first occurrence of the Separators parameter". I read this as:*saveptr = token + strlen(token) + 1;which is consistent with this strtok example from the C standard:
Quoted 8 lines
#include <string.h> static char str[] = "?a???b,"; char *t; t = strtok(str, "?"); // t points to the token "a" t = strtok(str, ","); // t points to the token "??b"Have you tested this code with multiple consecutive slashes?
Yes, both 2-strtok and strtok+saveptr approach work correctly (= as per my expectation!) with multiple consecutive slashes. I do understand that 2-strtok approach will not work when we have %3F in the path component of the URI.
For URIs like gluster://server/volname/path/to/image, both the approaches extract image as "path/to/image".
For URIs like gluster://server/volname//path/to/image, both the approaches extract image as "/path/to/image".
For gluster://server/volname////path/to/image, the image is extracted as "//path/to/image".
Quoted 12 lines
Quoted 9 lines
If you think using saveptr is fine, then I could use that as below...
/* image */ if (!*saveptr) { return -EINVAL; } gconf->image = g_strdup(saveptr);I would avoid
strtok_rcompletely:
Quoted 11 lines
char *p = path + strcpsn(path, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->volname = g_strndup(path, p - path);
p += strspn(p, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->image = g_strdup(p);This isn't working because for a URI like gluster://server/volname/path/to/image, uri_parse() will give "/volname/path/to/image" in uri->path. I would have expected to see uri->path as "volname/path/to/image" (without 1st slash).
Note that gluster is currently able to resolve image paths that don't have a preceding slash (like dir/a.img). But I guess we should support specifying complete image paths too (like /dir/a.img)
Regards,
Bharata.
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Il 27/09/2012 08:41, Bharata B Rao ha scritto:
Quoted 29 lines
Quoted 15 lines
Quoted 4 lines
As you note, I don't need 2nd strtok strictly since the rest of the string is available in saveptr. But I thought using saveptr is not ideal or preferred. I wanted to use the most appropriate/safe delimiter to extract the image string in the 2nd strtok and decided to use '?'.
I don't think it is defined what saveptr points to.
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf2/strtok_r.htm
says "thestrtok_rsubroutine also updates the Pointer parameter with the starting address of the token following the first occurrence of the Separators parameter". I read this as:*saveptr = token + strlen(token) + 1;which is consistent with this strtok example from the C standard:
Quoted 8 lines
#include <string.h> static char str[] = "?a???b,"; char *t; t = strtok(str, "?"); // t points to the token "a" t = strtok(str, ","); // t points to the token "??b"Have you tested this code with multiple consecutive slashes?
Yes, both 2-strtok and strtok+saveptr approach work correctly (= as per my expectation!) with multiple consecutive slashes. I do understand that 2-strtok approach will not work when we have %3F in the path component of the URI.
Quoted 8 lines
For URIs like gluster://server/volname/path/to/image, both the approaches extract image as "path/to/image".
For URIs like gluster://server/volname//path/to/image, both the approaches extract image as "/path/to/image".
For gluster://server/volname////path/to/image, the image is extracted as "//path/to/image".
Should there be three /'s here? I assume it's just a typo.
I'm concerned that there is no documentation of what saveptr actually points to. In many cases the strtok specification doesn't leave much free room, but in the case you're testing here:
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
/* image */ if (!*saveptr) { return -EINVAL; }
strtok_r may just as well leave saveptr = NULL for example.
Quoted 17 lines
Quoted 5 lines
Quoted 2 lines
gconf->image = g_strdup(saveptr);I would avoid
strtok_rcompletely:Quoted 11 lines
char *p = path + strcpsn(path, "/"); if (*p == '\0') { return -EINVAL; } gconf->volname = g_strndup(path, p - path); p += strspn(p, "/"); if (*p == '\0') { return -EINVAL; } gconf->image = g_strdup(p);
Quoted 4 lines
This isn't working because for a URI like gluster://server/volname/path/to/image,
uri_parse()will give "/volname/path/to/image" inuri->path. I would have expected to seeuri->pathas "volname/path/to/image" (without 1st slash).
Ok, that's easy enough to fix with an extra strspn,
char *p = path + strpsn(path, "/");
p += strcspn(p, "/");Quoted 3 lines
Note that gluster is currently able to resolve image paths that don't have a preceding slash (like dir/a.img). But I guess we should support specifying complete image paths too (like /dir/a.img)
How would the URIs look like?
Paolo
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Quoted 5 lines · Paolo Bonzini
Quoted 3 lines
For gluster://server/volname////path/to/image, the image is extracted as "//path/to/image".
Should there be three /'s here? I assume it's just a typo.
Yes it was a typo.
Quoted 11 lines
I'm concerned that there is no documentation of what saveptr actually points to. In many cases the strtok specification doesn't leave much free room, but in the case you're testing here:
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
/* image */ if (!*saveptr) { return -EINVAL; }
strtok_rmay just as well leave saveptr = NULL for example.
Haven't seen that, but yes can't depend on that I suppose.
Quoted 23 lines
Quoted 18 lines
Quoted 6 lines
Quoted 3 lines
gconf->image = g_strdup(saveptr);I would avoid
strtok_rcompletely:Quoted 11 lines
char *p = path + strcpsn(path, "/"); if (*p == '\0') { return -EINVAL; } gconf->volname = g_strndup(path, p - path); p += strspn(p, "/"); if (*p == '\0') { return -EINVAL; } gconf->image = g_strdup(p);Quoted 4 lines
This isn't working because for a URI like gluster://server/volname/path/to/image,
uri_parse()will give "/volname/path/to/image" inuri->path. I would have expected to seeuri->pathas "volname/path/to/image" (without 1st slash).
Quoted 4 lines
Ok, that's easy enough to fix with an extra strspn,
char *p = path + strpsn(path, "/"); p += strcspn(p, "/");
Ok, this is how its looking finally...
char *p, *q;
p = q = path + strspn(path, "/");
p += strcspn(p, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->volname = g_strndup(q, p - q);
p += strspn(p, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->image = g_strdup(p);Quoted 7 lines
Quoted 5 lines
Note that gluster is currently able to resolve image paths that don't have a preceding slash (like dir/a.img). But I guess we should support specifying complete image paths too (like /dir/a.img)
How would the URIs look like?
gluster://server/testvol//dir/a.img ?
Isn't this a valid URI ? Here volname=testvol and image=/dir/a.img.
If that's valid and needs to be supported, then the above strspn based parsing logic needs some rewrite.
Regards,
Bharata.
Re: [Qemu-devel] [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend.
Il 27/09/2012 10:28, Bharata B Rao ha scritto:
Quoted 4 lines
Quoted 2 lines
Quoted 2 lines
How would the URIs look like?
gluster://server/testvol//dir/a.img ?
Isn't this a valid URI ? Here volname=testvol and image=/dir/a.img.
It is, but I think it would be canonicalized to
gluster://server/testvol/dir/a.img.
Quoted 2 lines
If that's valid and needs to be supported, then the above strspn based parsing logic needs some rewrite.
I think we can avoid this, it is unintuitive.
Paolo
[Qemu-devel] O_DIRECT on glusterfs (was Re: [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend)
In reply to Bharata B RaoIl 24/09/2012 11:13, Bharata B Rao ha scritto:
block/gluster.c line 307
Quoted 5 lines
block/gluster.c new file +5
-0+ +if ((bdrv_flags &BDRV_O_NOCACHE )) { + open_flags |=O_DIRECT ; + } +
If I understand correctly what I was told, this prevents the brick server from using its own buffer cache. This is quite different from what we do for example over NFS (where the host does no caching, but nothing prevents it on the remote server).
I think these 3 lines should be removed. We're bypassing the host buffer cache just by virtue of using a userspace driver, and that's what cache=none cares about.
Paolo
Re: [Qemu-devel] O_DIRECT on glusterfs (was Re: [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend)
Quoted 12 lines · Paolo Bonzini
Il 24/09/2012 11:13, Bharata B Rao ha scritto:
block/gluster.c line 307
Quoted 5 lines
block/gluster.c new file +5
-0+ +if ((bdrv_flags&BDRV_O_NOCACHE )) { + open_flags |=O_DIRECT ; + } +If I understand correctly what I was told, this prevents the brick server from using its own buffer cache. This is quite different from what we do for example over NFS (where the host does no caching, but nothing prevents it on the remote server).
Quoted 5 lines
I think these 3 lines should be removed. We're bypassing the host buffer cache just by virtue of using a userspace driver, and that's what cache=none cares about.
Paolo
O_DIRECT also has an effect on the behavior of the "client side" (the part within the qemu) of Gluster stack as well. I presume the intention of O_DIRECT is to minimize use of memory (whether as host' page cache or buffered data in user space). To that end it is a good idea to leave O_DIRECT flag set.
The behavior of whether gluster bricks need to get the O_DIRECT propagated or not is a different issue. We are exploring the possibility of not sending O_DIRECT flag over the wire to mimic NFS behavior. That would be independent of the qemu block driver setting the open flag.
Avati
Re: [Qemu-devel] O_DIRECT on glusterfs (was Re: [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend)
Il 03/10/2012 19:58, Anand Avati ha scritto:
Quoted 11 lines
Quoted 4 lines
I think these 3 lines should be removed. We're bypassing the host buffer cache just by virtue of using a userspace driver, and that's what cache=none cares about.
O_DIRECTalso has an effect on the behavior of the "client side" (the part within the qemu) of Gluster stack as well. I presume the intention ofO_DIRECTis to minimize use of memory (whether as host' page cache or buffered data in user space). To that end it is a good idea to leaveO_DIRECTflag set.
Quoted 4 lines
The behavior of whether gluster bricks need to get the
O_DIRECTpropagated or not is a different issue. We are exploring the possibility of not sendingO_DIRECTflag over the wire to mimic NFS behavior. That would be independent of the qemu block driver setting the open flag.
What is the effect of O_DIRECT on the client exactly?
Paolo
Re: [Qemu-devel] O_DIRECT on glusterfs (was Re: [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend)
Quoted 12 lines · Paolo Bonzini
Il 03/10/2012 19:58, Anand Avati ha scritto:
Quoted 11 lines
Quoted 4 lines
I think these 3 lines should be removed. We're bypassing the host buffer cache just by virtue of using a userspace driver, and that's what cache=none cares about.
O_DIRECTalso has an effect on the behavior of the "client side" (the part within the qemu) of Gluster stack as well. I presume the intention ofO_DIRECTis to minimize use of memory (whether as host' page cache or buffered data in user space). To that end it is a good idea to leaveO_DIRECTflag set.
Quoted 6 lines
Quoted 4 lines
The behavior of whether gluster bricks need to get the
O_DIRECTpropagated or not is a different issue. We are exploring the possibility of not sendingO_DIRECTflag over the wire to mimic NFS behavior. That would be independent of the qemu block driver setting the open flag.What is the effect of
O_DIRECTon the client exactly?
To avoid caching in the io-cache module, disable read-ahead etc (if those translators are loaded). The behavior in write-behind is tunable. You could either disable write-behind entirely (which will happen once libgfapi supports 0-copy/RDMA) or perform a sliding-window like size-limited write-behind (defaults to 1MB).
Avati
Re: [Qemu-devel] O_DIRECT on glusterfs (was Re: [PATCH v9 4/4] block: Support GlusterFS as a QEMU block backend)
Il 03/10/2012 20:17, Anand Avati ha scritto:
Quoted 19 lines · Paolo Bonzini
Quoted 18 lines
Il 03/10/2012 19:58, Anand Avati ha scritto:
Quoted 16 lines
Quoted 5 lines
I think these 3 lines should be removed. We're bypassing the host buffer cache just by virtue of using a userspace driver, and that's what
cache=none cares about.
O_DIRECTalso has an effect on the behavior of the "client side" (the part within the qemu) of Gluster stack as well. I presume the intention ofO_DIRECTis to minimize use of memory (whether as host' page cache or buffered data in user space). To that end it is a good idea to leaveO_DIRECTflag set.The behavior of whether gluster bricks need to get the
O_DIRECTpropagated or not is a different issue. We are exploring the possibility of not sendingO_DIRECTflag over the wire to mimic NFS behavior. That would be independent of the qemu block driver setting the open flag.
Quoted 7 lines
Quoted 1 line
What is the effect of
O_DIRECTon the client exactly?To avoid caching in the io-cache module, disable read-ahead etc (if those translators are loaded). The behavior in write-behind is tunable. You could either disable write-behind entirely (which will happen once libgfapi supports 0-copy/RDMA) or perform a sliding-window like size-limited write-behind (defaults to 1MB).
Thanks for the information.
I think we need to benchmark it and see what is the actual difference in memory usage vs. performance. The usual reasons for cache=none (enable Linux native AIO + allow migration with shared non-coherent storage) do not apply to gluster.
Paolo