GlusterFS support in QEMU - v8
v8 cover GlusterFS support in QEMU - v8
Hi,
This is v8 of the patchset to support GlusterFS backend from QEMU.
I will follow up this post by v9 that will use a generic URI parsing code borrowed from libxml2 and libvirt. In case there is no agreement on using that generic URI parsing code in QEMU, I would like v8 to be considered for inclusion.
Changes in v8
-------------
- Fixed a few problems with the URI parsing code.
- Instead of exposing socket_opts via vm_config_groups, use Paolo's patch that just globalizes socket_opts.
Previous versions can be found here:
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 v8 1/6 sockets: publish dummy_opts
sockets: publish dummy_opts
From: Paolo Bonzini <[email protected]>
This is needed so that we can set up a QemuOpts instance from QMP parameters. The way to go here is to and move qemu-sockets.c away from QemuOpts and use Laszlo's QemuOptsVisitor whenever *_opts functions are called now. This can be done later, however.
This would also enable block backends like gluster to make use of inet_parse() for inet address parsing.
---
qemu-sockets.c | 14 +++++++------- qemu_socket.h | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-)
qemu-sockets.c +7 -7
@@ -32,9 +32,9 @@static const int on=1 , off=0 ;/* used temporarely until all users are converted to QemuOpts */ -static QemuOptsList dummy_opts = { - .name ="dummy" , - .head =QTAILQ_HEAD_INITIALIZER (dummy_opts.head), +QemuOptsList socket_opts = { + .name ="socket" , + .head =QTAILQ_HEAD_INITIALIZER (socket_opts.head), .desc = { { .name ="path" ,
@@ -469,7 +469,7 @@ int inet_listen(const char *str, char *ostr, int olen,char *optstr;int sock =-1 ; - opts =qemu_opts_create (&dummy_opts,NULL ,0 ,NULL ); + opts =qemu_opts_create (&socket_opts,NULL ,0 ,NULL );if (inet_parse (opts, str) ==0 ) { sock =inet_listen_opts (opts, port_offset, errp);if (sock !=-1 && ostr) {
@@ -498,7 +498,7 @@ int inet_connect(const char *str, bool block, bool *in_progress, Error **errp)QemuOpts *opts;int sock =-1 ; - opts =qemu_opts_create (&dummy_opts,NULL ,0 ,NULL ); + opts =qemu_opts_create (&socket_opts,NULL ,0 ,NULL );if (inet_parse (opts, str) ==0 ) {if (block) {qemu_opt_set (opts,"block" ,"on" );
@@ -597,7 +597,7 @@ int unix_listen(const char *str, char *ostr, int olen)char *path, *optstr;int sock, len; - opts =qemu_opts_create (&dummy_opts,NULL ,0 ,NULL ); + opts =qemu_opts_create (&socket_opts,NULL ,0 ,NULL ); optstr =strchr (str,',' );if (optstr) {
@@ -625,7 +625,7 @@ int unix_connect(const char *path)QemuOpts *opts;int sock; - opts =qemu_opts_create (&dummy_opts,NULL ,0 ,NULL ); + opts =qemu_opts_create (&socket_opts,NULL ,0 ,NULL );qemu_opt_set (opts,"path" , path); sock =unix_connect_opts (opts);qemu_opts_del (opts);
qemu_socket.h +2 -0
@@ -30,6 +30,8 @@ int inet_aton(const char *cp, struct in_addr *ia);#include "error.h" #include "qerror.h" +extern QemuOptsList socket_opts; +/* misc helpers */ int qemu_socket (int domain,int type,int protocol);int qemu_accept (int s,struct sockaddr *addr,socklen_t *addrlen);
PATCH v8 2/6 sockets: Make port specification optional in inet_parse
In reply to Bharata B Raosockets: Make port specification optional in inet_parse
From: Bharata B Rao <[email protected]>
Change inet_parse() to work without explicit port specification. Add a default_port argument to be used when port isn't specified.
---
qemu-sockets.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 files changed, 34 insertions(+), 9 deletions(-)
qemu-sockets.c +34 -9
@@ -406,26 +406,36 @@ err:return -1 ; } -/* compatibility wrapper */ -static int inet_parse (QemuOpts *opts,const char *str) +/* +* Converts inet address and port specification in @str to QemuOpts +* options. +* +* If port isn't specified in @str, @default_port will be set in the +* port option of @opts. If default_port is -1, then the parser will +* look for the port specification in @str mandatorily. +*/ +static int inet_parse (QemuOpts *opts,const char *str,int default_port) {const char *optstr, *h;char addr[64 ];char port[33 ]; -int pos; +int ret, pos, addr_pos =-1 , port_pos =-1 ;/* parse address */ if (str[0 ] ==':' ) {/* no host given */ addr[0 ] ='\0' ; -if (1 !=sscanf (str,":%32[^,]%n" ,port,&pos)) { + ret =sscanf (str,":%32[^,]%n" , port, &port_pos); +if (port_pos ==-1 || ret ==EOF ) {fprintf (stderr,"%s: portonly parse error (%s)\n" , __FUNCTION__, str);return -1 ; } }else if (str[0 ] =='[' ) {/* IPv6 addr */ -if (2 !=sscanf (str,"[%64[^]]]:%32[^,]%n" ,addr,port,&pos)) { + ret =sscanf (str,"[%64[^]]]%n:%32[^,]%n" , addr, &addr_pos, + port, &port_pos); +if (addr_pos ==-1 || ret ==EOF ) {fprintf (stderr,"%s: ipv6 parse error (%s)\n" , __FUNCTION__, str);return -1 ;
@@ -433,7 +443,9 @@ static int inet_parse(QemuOpts *opts, const char *str)qemu_opt_set (opts,"ipv6" ,"on" ); }else if (qemu_isdigit (str[0 ])) {/* IPv4 addr */ -if (2 !=sscanf (str,"%64[0-9.]:%32[^,]%n" ,addr,port,&pos)) { + ret =sscanf (str,"%64[0-9.]%n:%32[^,]%n" , addr, &addr_pos, + port, &port_pos); +if (addr_pos ==-1 || ret ==EOF ) {fprintf (stderr,"%s: ipv4 parse error (%s)\n" , __FUNCTION__, str);return -1 ;
@@ -441,12 +453,25 @@ static int inet_parse(QemuOpts *opts, const char *str)qemu_opt_set (opts,"ipv4" ,"on" ); }else {/* hostname */ -if (2 !=sscanf (str,"%64[^:]:%32[^,]%n" ,addr,port,&pos)) { + ret =sscanf (str,"%64[^:]%n:%32[^,]%n" , addr, &addr_pos, + port, &port_pos); +if (addr_pos ==-1 || ret ==EOF ) {fprintf (stderr,"%s: hostname parse error (%s)\n" , __FUNCTION__, str);return -1 ; } } + +if (port_pos !=-1 ) { + pos = port_pos; + }else { + pos = addr_pos; +if (default_port ==-1 ) { +return -1 ; + } +snprintf (port,33 ,"%d" , default_port); + } +qemu_opt_set (opts,"host" , addr);qemu_opt_set (opts,"port" , port);
@@ -470,7 +495,7 @@ int inet_listen(const char *str, char *ostr, int olen,int sock =-1 ; opts =qemu_opts_create (&socket_opts,NULL ,0 ,NULL ); -if (inet_parse (opts, str) ==0 ) { +if (inet_parse (opts, str,-1 ) ==0 ) { sock =inet_listen_opts (opts, port_offset, errp);if (sock !=-1 && ostr) { optstr =strchr (str,',' );
@@ -499,7 +524,7 @@ int inet_connect(const char *str, bool block, bool *in_progress, Error **errp)int sock =-1 ; opts =qemu_opts_create (&socket_opts,NULL ,0 ,NULL ); -if (inet_parse (opts, str) ==0 ) { +if (inet_parse (opts, str,-1 ) ==0 ) {if (block) {qemu_opt_set (opts,"block" ,"on" ); }
PATCH v8 3/6 sockets: Make inet_parse() non static.
In reply to Bharata B Raosockets: Make inet_parse() non static.
From: Bharata B Rao <[email protected]>
Make inet_parse() non-static so that other subsystems like gluster can use it to parse inet addresses.
---
qemu-sockets.c | 2 +- qemu_socket.h | 1 + 2 files changed, 2 insertions(+), 1 deletions(-)
qemu-sockets.c +1 -1
@@ -414,7 +414,7 @@ err:* port option of @opts. If default_port is -1, then the parser will * look for the port specification in @str mandatorily. */ -static int inet_parse (QemuOpts *opts,const char *str,int default_port) +int inet_parse (QemuOpts *opts,const char *str,int default_port) {const char *optstr, *h;char addr[64 ];
qemu_socket.h +1 -0
@@ -48,6 +48,7 @@ int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp);int inet_connect (const char *str,bool block,bool *in_progress,Error **errp);int inet_dgram_opts (QemuOpts *opts);const char *inet_strfamily (int family); +int inet_parse (QemuOpts *opts,const char *str,int default_port);int unix_listen_opts (QemuOpts *opts);int unix_listen (const char *path,char *ostr,int olen);
PATCH v8 4/6 aio: Fix qemu_aio_wait() to maintain correct walking_handlers count
In reply to Bharata B Raoaio: 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 v8 5/6 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 v8 6/6 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 | 675 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 676 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 +675 -0
675 lines not on this page · raw message