2012-09-27 18:00:32 +04:00
|
|
|
/*
|
|
|
|
* GlusterFS backend for QEMU
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
|
|
|
|
*
|
2014-01-29 18:29:55 +04:00
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
2012-09-27 18:00:32 +04:00
|
|
|
*
|
|
|
|
*/
|
2016-01-18 21:01:42 +03:00
|
|
|
#include "qemu/osdep.h"
|
2012-09-27 18:00:32 +04:00
|
|
|
#include <glusterfs/api/glfs.h>
|
2012-12-17 21:19:44 +04:00
|
|
|
#include "block/block_int.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 11:01:28 +03:00
|
|
|
#include "qapi/error.h"
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/uri.h"
|
2016-07-19 19:57:31 +03:00
|
|
|
#include "qemu/error-report.h"
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2016-07-19 19:57:30 +03:00
|
|
|
#define GLUSTER_OPT_FILENAME "filename"
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
#define GLUSTER_OPT_VOLUME "volume"
|
|
|
|
#define GLUSTER_OPT_PATH "path"
|
|
|
|
#define GLUSTER_OPT_TYPE "type"
|
|
|
|
#define GLUSTER_OPT_SERVER_PATTERN "server."
|
|
|
|
#define GLUSTER_OPT_HOST "host"
|
|
|
|
#define GLUSTER_OPT_PORT "port"
|
|
|
|
#define GLUSTER_OPT_TO "to"
|
|
|
|
#define GLUSTER_OPT_IPV4 "ipv4"
|
|
|
|
#define GLUSTER_OPT_IPV6 "ipv6"
|
|
|
|
#define GLUSTER_OPT_SOCKET "socket"
|
2016-07-19 19:57:30 +03:00
|
|
|
#define GLUSTER_OPT_DEBUG "debug"
|
2016-07-19 19:57:32 +03:00
|
|
|
#define GLUSTER_DEFAULT_PORT 24007
|
2016-07-19 19:57:30 +03:00
|
|
|
#define GLUSTER_DEBUG_DEFAULT 4
|
|
|
|
#define GLUSTER_DEBUG_MAX 9
|
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
#define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n"
|
2016-07-19 19:57:30 +03:00
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
typedef struct GlusterAIOCB {
|
|
|
|
int64_t size;
|
|
|
|
int ret;
|
|
|
|
QEMUBH *bh;
|
2013-12-21 13:21:24 +04:00
|
|
|
Coroutine *coroutine;
|
2014-05-08 18:34:41 +04:00
|
|
|
AioContext *aio_context;
|
2012-09-27 18:00:32 +04:00
|
|
|
} GlusterAIOCB;
|
|
|
|
|
|
|
|
typedef struct BDRVGlusterState {
|
|
|
|
struct glfs *glfs;
|
|
|
|
struct glfs_fd *fd;
|
2016-03-10 21:38:00 +03:00
|
|
|
bool supports_seek_data;
|
2016-04-08 00:24:19 +03:00
|
|
|
int debug_level;
|
2012-09-27 18:00:32 +04:00
|
|
|
} BDRVGlusterState;
|
|
|
|
|
2016-07-19 19:57:30 +03:00
|
|
|
typedef struct BDRVGlusterReopenState {
|
|
|
|
struct glfs *glfs;
|
|
|
|
struct glfs_fd *fd;
|
|
|
|
} BDRVGlusterReopenState;
|
|
|
|
|
|
|
|
|
|
|
|
static QemuOptsList qemu_gluster_create_opts = {
|
|
|
|
.name = "qemu-gluster-create-opts",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = BLOCK_OPT_SIZE,
|
|
|
|
.type = QEMU_OPT_SIZE,
|
|
|
|
.help = "Virtual disk size"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = BLOCK_OPT_PREALLOC,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "Preallocation mode (allowed values: off, full)"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_DEBUG,
|
|
|
|
.type = QEMU_OPT_NUMBER,
|
|
|
|
.help = "Gluster log level, valid range is 0-9",
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static QemuOptsList runtime_opts = {
|
|
|
|
.name = "gluster",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_FILENAME,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "URL to the gluster image",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_DEBUG,
|
|
|
|
.type = QEMU_OPT_NUMBER,
|
|
|
|
.help = "Gluster log level, valid range is 0-9",
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
static QemuOptsList runtime_json_opts = {
|
|
|
|
.name = "gluster_json",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(runtime_json_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_VOLUME,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "name of gluster volume where VM image resides",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_PATH,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "absolute path to image file in gluster volume",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_DEBUG,
|
|
|
|
.type = QEMU_OPT_NUMBER,
|
|
|
|
.help = "Gluster log level, valid range is 0-9",
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static QemuOptsList runtime_type_opts = {
|
|
|
|
.name = "gluster_type",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(runtime_type_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_TYPE,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "tcp|unix",
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static QemuOptsList runtime_unix_opts = {
|
|
|
|
.name = "gluster_unix",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(runtime_unix_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_SOCKET,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "socket file path)",
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static QemuOptsList runtime_tcp_opts = {
|
|
|
|
.name = "gluster_tcp",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_TYPE,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "tcp|unix",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_HOST,
|
|
|
|
.type = QEMU_OPT_STRING,
|
|
|
|
.help = "host address (hostname/ipv4/ipv6 addresses)",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = GLUSTER_OPT_PORT,
|
|
|
|
.type = QEMU_OPT_NUMBER,
|
|
|
|
.help = "port number on which glusterd is listening (default 24007)",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "to",
|
|
|
|
.type = QEMU_OPT_NUMBER,
|
|
|
|
.help = "max port number, not supported by gluster",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "ipv4",
|
|
|
|
.type = QEMU_OPT_BOOL,
|
|
|
|
.help = "ipv4 bool value, not supported by gluster",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "ipv6",
|
|
|
|
.type = QEMU_OPT_BOOL,
|
|
|
|
.help = "ipv6 bool value, not supported by gluster",
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
2016-07-19 19:57:30 +03:00
|
|
|
|
2016-07-19 19:57:32 +03:00
|
|
|
static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
|
|
|
char *p, *q;
|
|
|
|
|
|
|
|
if (!path) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* volume */
|
|
|
|
p = q = path + strspn(path, "/");
|
|
|
|
p += strcspn(p, "/");
|
|
|
|
if (*p == '\0') {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2016-07-19 19:57:29 +03:00
|
|
|
gconf->volume = g_strndup(q, p - q);
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2016-07-19 19:57:29 +03:00
|
|
|
/* path */
|
2012-09-27 18:00:32 +04:00
|
|
|
p += strspn(p, "/");
|
|
|
|
if (*p == '\0') {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2016-07-19 19:57:29 +03:00
|
|
|
gconf->path = g_strdup(p);
|
2012-09-27 18:00:32 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2016-07-19 19:57:29 +03:00
|
|
|
* file=gluster[+transport]://[host[:port]]/volume/path[?socket=...]
|
2012-09-27 18:00:32 +04:00
|
|
|
*
|
|
|
|
* 'gluster' is the protocol.
|
|
|
|
*
|
|
|
|
* 'transport' specifies the transport type used to connect to gluster
|
|
|
|
* management daemon (glusterd). Valid transport types are
|
2016-07-19 19:57:31 +03:00
|
|
|
* tcp or unix. If a transport type isn't specified, then tcp type is assumed.
|
2012-09-27 18:00:32 +04:00
|
|
|
*
|
2016-07-19 19:57:29 +03:00
|
|
|
* 'host' specifies the host where the volume file specification for
|
2016-07-19 19:57:31 +03:00
|
|
|
* the given volume resides. This can be either hostname or ipv4 address.
|
2016-07-19 19:57:29 +03:00
|
|
|
* If transport type is 'unix', then 'host' field should not be specified.
|
2012-09-27 18:00:32 +04:00
|
|
|
* 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. If the transport type is unix, then 'port' should not be
|
|
|
|
* specified.
|
|
|
|
*
|
2016-07-19 19:57:29 +03:00
|
|
|
* 'volume' is the name of the gluster volume which contains the VM image.
|
2012-09-27 18:00:32 +04:00
|
|
|
*
|
2016-07-19 19:57:29 +03:00
|
|
|
* 'path' is the path to the actual VM image that resides on gluster volume.
|
2012-09-27 18:00:32 +04:00
|
|
|
*
|
|
|
|
* 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
|
2016-07-19 19:57:29 +03:00
|
|
|
* file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
|
2012-09-27 18:00:32 +04:00
|
|
|
* file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
|
|
|
|
*/
|
2016-07-19 19:57:32 +03:00
|
|
|
static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
|
|
|
|
const char *filename)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
2016-07-19 19:57:32 +03:00
|
|
|
GlusterServer *gsconf;
|
2012-09-27 18:00:32 +04:00
|
|
|
URI *uri;
|
|
|
|
QueryParams *qp = NULL;
|
|
|
|
bool is_unix = false;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
uri = uri_parse(filename);
|
|
|
|
if (!uri) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
gconf->server = g_new0(GlusterServerList, 1);
|
|
|
|
gconf->server->value = gsconf = g_new0(GlusterServer, 1);
|
2016-07-19 19:57:32 +03:00
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
/* transport */
|
2014-02-17 17:43:54 +04:00
|
|
|
if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
|
2016-07-19 19:57:32 +03:00
|
|
|
gsconf->type = GLUSTER_TRANSPORT_TCP;
|
2012-09-27 18:00:32 +04:00
|
|
|
} else if (!strcmp(uri->scheme, "gluster+tcp")) {
|
2016-07-19 19:57:32 +03:00
|
|
|
gsconf->type = GLUSTER_TRANSPORT_TCP;
|
2012-09-27 18:00:32 +04:00
|
|
|
} else if (!strcmp(uri->scheme, "gluster+unix")) {
|
2016-07-19 19:57:32 +03:00
|
|
|
gsconf->type = GLUSTER_TRANSPORT_UNIX;
|
2012-09-27 18:00:32 +04:00
|
|
|
is_unix = true;
|
|
|
|
} else if (!strcmp(uri->scheme, "gluster+rdma")) {
|
2016-07-19 19:57:32 +03:00
|
|
|
gsconf->type = GLUSTER_TRANSPORT_TCP;
|
2016-07-19 19:57:31 +03:00
|
|
|
error_report("Warning: rdma feature is not supported, falling "
|
|
|
|
"back to tcp");
|
2012-09-27 18:00:32 +04:00
|
|
|
} else {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = parse_volume_options(gconf, uri->path);
|
|
|
|
if (ret < 0) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
qp = query_params_parse(uri->query);
|
|
|
|
if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_unix) {
|
|
|
|
if (uri->server || uri->port) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (strcmp(qp->p[0].name, "socket")) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2016-07-19 19:57:32 +03:00
|
|
|
gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
|
2012-09-27 18:00:32 +04:00
|
|
|
} else {
|
2016-07-19 19:57:32 +03:00
|
|
|
gsconf->u.tcp.host = g_strdup(uri->server ? uri->server : "localhost");
|
|
|
|
if (uri->port) {
|
|
|
|
gsconf->u.tcp.port = g_strdup_printf("%d", uri->port);
|
|
|
|
} else {
|
|
|
|
gsconf->u.tcp.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
|
|
|
|
}
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (qp) {
|
|
|
|
query_params_free(qp);
|
|
|
|
}
|
|
|
|
uri_free(uri);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
|
|
|
|
Error **errp)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
struct glfs *glfs;
|
2012-09-27 18:00:32 +04:00
|
|
|
int ret;
|
|
|
|
int old_errno;
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
GlusterServerList *server;
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2016-07-19 19:57:29 +03:00
|
|
|
glfs = glfs_new(gconf->volume);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (!glfs) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
for (server = gconf->server; server; server = server->next) {
|
|
|
|
if (server->value->type == GLUSTER_TRANSPORT_UNIX) {
|
|
|
|
ret = glfs_set_volfile_server(glfs,
|
|
|
|
GlusterTransport_lookup[server->value->type],
|
|
|
|
server->value->u.q_unix.path, 0);
|
|
|
|
} else {
|
|
|
|
ret = glfs_set_volfile_server(glfs,
|
|
|
|
GlusterTransport_lookup[server->value->type],
|
|
|
|
server->value->u.tcp.host,
|
|
|
|
atoi(server->value->u.tcp.port));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
goto out;
|
|
|
|
}
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2016-04-08 00:24:19 +03:00
|
|
|
ret = glfs_set_logging(glfs, "-", gconf->debug_level);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (ret < 0) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = glfs_init(glfs);
|
|
|
|
if (ret) {
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
error_setg(errp, "Gluster connection for volume %s, path %s failed"
|
|
|
|
" to connect", gconf->volume, gconf->path);
|
|
|
|
for (server = gconf->server; server; server = server->next) {
|
|
|
|
if (server->value->type == GLUSTER_TRANSPORT_UNIX) {
|
|
|
|
error_append_hint(errp, "hint: failed on socket %s ",
|
|
|
|
server->value->u.q_unix.path);
|
|
|
|
} else {
|
|
|
|
error_append_hint(errp, "hint: failed on host %s and port %s ",
|
|
|
|
server->value->u.tcp.host,
|
|
|
|
server->value->u.tcp.port);
|
|
|
|
}
|
2016-07-19 19:57:32 +03:00
|
|
|
}
|
2014-05-09 14:08:10 +04:00
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
error_append_hint(errp, "Please refer to gluster logs for more info\n");
|
|
|
|
|
2014-05-09 14:08:10 +04:00
|
|
|
/* glfs_init sometimes doesn't set errno although docs suggest that */
|
2016-07-19 19:57:32 +03:00
|
|
|
if (errno == 0) {
|
2014-05-09 14:08:10 +04:00
|
|
|
errno = EINVAL;
|
2016-07-19 19:57:32 +03:00
|
|
|
}
|
2014-05-09 14:08:10 +04:00
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
return glfs;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (glfs) {
|
|
|
|
old_errno = errno;
|
|
|
|
glfs_fini(glfs);
|
|
|
|
errno = old_errno;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
static int qapi_enum_parse(const char *opt)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!opt) {
|
|
|
|
return GLUSTER_TRANSPORT__MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < GLUSTER_TRANSPORT__MAX; i++) {
|
|
|
|
if (!strcmp(opt, GlusterTransport_lookup[i])) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the json formatted command line into qapi.
|
|
|
|
*/
|
|
|
|
static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
|
|
|
QDict *options, Error **errp)
|
|
|
|
{
|
|
|
|
QemuOpts *opts;
|
|
|
|
GlusterServer *gsconf;
|
|
|
|
GlusterServerList *curr = NULL;
|
|
|
|
QDict *backing_options = NULL;
|
|
|
|
Error *local_err = NULL;
|
|
|
|
char *str = NULL;
|
|
|
|
const char *ptr;
|
|
|
|
size_t num_servers;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* create opts info from runtime_json_opts list */
|
|
|
|
opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort);
|
|
|
|
qemu_opts_absorb_qdict(opts, options, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_servers = qdict_array_entries(options, GLUSTER_OPT_SERVER_PATTERN);
|
|
|
|
if (num_servers < 1) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER, "server");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_VOLUME);
|
|
|
|
if (!ptr) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_VOLUME);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
gconf->volume = g_strdup(ptr);
|
|
|
|
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH);
|
|
|
|
if (!ptr) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_PATH);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
gconf->path = g_strdup(ptr);
|
|
|
|
qemu_opts_del(opts);
|
|
|
|
|
|
|
|
for (i = 0; i < num_servers; i++) {
|
|
|
|
str = g_strdup_printf(GLUSTER_OPT_SERVER_PATTERN"%d.", i);
|
|
|
|
qdict_extract_subqdict(options, &backing_options, str);
|
|
|
|
|
|
|
|
/* create opts info from runtime_type_opts list */
|
|
|
|
opts = qemu_opts_create(&runtime_type_opts, NULL, 0, &error_abort);
|
|
|
|
qemu_opts_absorb_qdict(opts, backing_options, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_TYPE);
|
|
|
|
gsconf = g_new0(GlusterServer, 1);
|
|
|
|
gsconf->type = qapi_enum_parse(ptr);
|
|
|
|
if (!ptr) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_TYPE);
|
|
|
|
error_append_hint(&local_err, GERR_INDEX_HINT, i);
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (gsconf->type == GLUSTER_TRANSPORT__MAX) {
|
|
|
|
error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE,
|
|
|
|
GLUSTER_OPT_TYPE, "tcp or unix");
|
|
|
|
error_append_hint(&local_err, GERR_INDEX_HINT, i);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
qemu_opts_del(opts);
|
|
|
|
|
|
|
|
if (gsconf->type == GLUSTER_TRANSPORT_TCP) {
|
|
|
|
/* create opts info from runtime_tcp_opts list */
|
|
|
|
opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort);
|
|
|
|
qemu_opts_absorb_qdict(opts, backing_options, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_HOST);
|
|
|
|
if (!ptr) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER,
|
|
|
|
GLUSTER_OPT_HOST);
|
|
|
|
error_append_hint(&local_err, GERR_INDEX_HINT, i);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
gsconf->u.tcp.host = g_strdup(ptr);
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_PORT);
|
|
|
|
if (!ptr) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER,
|
|
|
|
GLUSTER_OPT_PORT);
|
|
|
|
error_append_hint(&local_err, GERR_INDEX_HINT, i);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
gsconf->u.tcp.port = g_strdup(ptr);
|
|
|
|
|
|
|
|
/* defend for unsupported fields in InetSocketAddress,
|
|
|
|
* i.e. @ipv4, @ipv6 and @to
|
|
|
|
*/
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_TO);
|
|
|
|
if (ptr) {
|
|
|
|
gsconf->u.tcp.has_to = true;
|
|
|
|
}
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_IPV4);
|
|
|
|
if (ptr) {
|
|
|
|
gsconf->u.tcp.has_ipv4 = true;
|
|
|
|
}
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_IPV6);
|
|
|
|
if (ptr) {
|
|
|
|
gsconf->u.tcp.has_ipv6 = true;
|
|
|
|
}
|
|
|
|
if (gsconf->u.tcp.has_to) {
|
|
|
|
error_setg(&local_err, "Parameter 'to' not supported");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (gsconf->u.tcp.has_ipv4 || gsconf->u.tcp.has_ipv6) {
|
|
|
|
error_setg(&local_err, "Parameters 'ipv4/ipv6' not supported");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
qemu_opts_del(opts);
|
|
|
|
} else {
|
|
|
|
/* create opts info from runtime_unix_opts list */
|
|
|
|
opts = qemu_opts_create(&runtime_unix_opts, NULL, 0, &error_abort);
|
|
|
|
qemu_opts_absorb_qdict(opts, backing_options, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET);
|
|
|
|
if (!ptr) {
|
|
|
|
error_setg(&local_err, QERR_MISSING_PARAMETER,
|
|
|
|
GLUSTER_OPT_SOCKET);
|
|
|
|
error_append_hint(&local_err, GERR_INDEX_HINT, i);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
gsconf->u.q_unix.path = g_strdup(ptr);
|
|
|
|
qemu_opts_del(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gconf->server == NULL) {
|
|
|
|
gconf->server = g_new0(GlusterServerList, 1);
|
|
|
|
gconf->server->value = gsconf;
|
|
|
|
curr = gconf->server;
|
|
|
|
} else {
|
|
|
|
curr->next = g_new0(GlusterServerList, 1);
|
|
|
|
curr->next->value = gsconf;
|
|
|
|
curr = curr->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
qdict_del(backing_options, str);
|
|
|
|
g_free(str);
|
|
|
|
str = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
out:
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
qemu_opts_del(opts);
|
|
|
|
if (str) {
|
|
|
|
qdict_del(backing_options, str);
|
|
|
|
g_free(str);
|
|
|
|
}
|
|
|
|
errno = EINVAL;
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
|
|
|
|
const char *filename,
|
|
|
|
QDict *options, Error **errp)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
if (filename) {
|
|
|
|
ret = qemu_gluster_parse_uri(gconf, filename);
|
|
|
|
if (ret < 0) {
|
|
|
|
error_setg(errp, "invalid URI");
|
|
|
|
error_append_hint(errp, "Usage: file=gluster[+transport]://"
|
|
|
|
"[host[:port]]/volume/path[?socket=...]\n");
|
|
|
|
errno = -ret;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = qemu_gluster_parse_json(gconf, options, errp);
|
|
|
|
if (ret < 0) {
|
|
|
|
error_append_hint(errp, "Usage: "
|
|
|
|
"-drive driver=qcow2,file.driver=gluster,"
|
|
|
|
"file.volume=testvol,file.path=/path/a.qcow2"
|
|
|
|
"[,file.debug=9],file.server.0.type=tcp,"
|
|
|
|
"file.server.0.host=1.2.3.4,"
|
|
|
|
"file.server.0.port=24007,"
|
|
|
|
"file.server.1.transport=unix,"
|
|
|
|
"file.server.1.socket=/var/run/glusterd.socket ..."
|
|
|
|
"\n");
|
|
|
|
errno = -ret;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return qemu_gluster_glfs_init(gconf, errp);
|
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:24 +04:00
|
|
|
static void qemu_gluster_complete_aio(void *opaque)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
2013-12-21 13:21:24 +04:00
|
|
|
GlusterAIOCB *acb = (GlusterAIOCB *)opaque;
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2013-12-21 13:21:24 +04:00
|
|
|
qemu_bh_delete(acb->bh);
|
|
|
|
acb->bh = NULL;
|
coroutine: move entry argument to qemu_coroutine_create
In practice the entry argument is always known at creation time, and
it is confusing that sometimes qemu_coroutine_enter is used with a
non-NULL argument to re-enter a coroutine (this happens in
block/sheepdog.c and tests/test-coroutine.c). So pass the opaque value
at creation time, for consistency with e.g. aio_bh_new.
Mostly done with the following semantic patch:
@ entry1 @
expression entry, arg, co;
@@
- co = qemu_coroutine_create(entry);
+ co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry2 @
expression entry, arg;
identifier co;
@@
- Coroutine *co = qemu_coroutine_create(entry);
+ Coroutine *co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry3 @
expression entry, arg;
@@
- qemu_coroutine_enter(qemu_coroutine_create(entry), arg);
+ qemu_coroutine_enter(qemu_coroutine_create(entry, arg));
@ reentry @
expression co;
@@
- qemu_coroutine_enter(co, NULL);
+ qemu_coroutine_enter(co);
except for the aforementioned few places where the semantic patch
stumbled (as expected) and for test_co_queue, which would otherwise
produce an uninitialized variable warning.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2016-07-04 20:10:01 +03:00
|
|
|
qemu_coroutine_enter(acb->coroutine);
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:25 +04:00
|
|
|
/*
|
|
|
|
* AIO callback routine called from GlusterFS thread.
|
|
|
|
*/
|
|
|
|
static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
|
|
|
|
{
|
|
|
|
GlusterAIOCB *acb = (GlusterAIOCB *)arg;
|
|
|
|
|
|
|
|
if (!ret || ret == acb->size) {
|
|
|
|
acb->ret = 0; /* Success */
|
|
|
|
} else if (ret < 0) {
|
2016-04-06 06:11:34 +03:00
|
|
|
acb->ret = -errno; /* Read/Write failed */
|
2013-12-21 13:21:25 +04:00
|
|
|
} else {
|
|
|
|
acb->ret = -EIO; /* Partial read/write - fail it */
|
|
|
|
}
|
|
|
|
|
2014-05-08 18:34:41 +04:00
|
|
|
acb->bh = aio_bh_new(acb->aio_context, qemu_gluster_complete_aio, acb);
|
2013-12-21 13:21:25 +04:00
|
|
|
qemu_bh_schedule(acb->bh);
|
|
|
|
}
|
|
|
|
|
2014-02-17 20:11:11 +04:00
|
|
|
static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags)
|
|
|
|
{
|
|
|
|
assert(open_flags != NULL);
|
|
|
|
|
|
|
|
*open_flags |= O_BINARY;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-10 21:38:00 +03:00
|
|
|
/*
|
|
|
|
* Do SEEK_DATA/HOLE to detect if it is functional. Older broken versions of
|
|
|
|
* gfapi incorrectly return the current offset when SEEK_DATA/HOLE is used.
|
|
|
|
* - Corrected versions return -1 and set errno to EINVAL.
|
|
|
|
* - Versions that support SEEK_DATA/HOLE correctly, will return -1 and set
|
|
|
|
* errno to ENXIO when SEEK_DATA is called with a position of EOF.
|
|
|
|
*/
|
|
|
|
static bool qemu_gluster_test_seek(struct glfs_fd *fd)
|
|
|
|
{
|
|
|
|
off_t ret, eof;
|
|
|
|
|
|
|
|
eof = glfs_lseek(fd, 0, SEEK_END);
|
|
|
|
if (eof < 0) {
|
|
|
|
/* this should never occur */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this should always fail with ENXIO if SEEK_DATA is supported */
|
|
|
|
ret = glfs_lseek(fd, eof, SEEK_DATA);
|
|
|
|
return (ret < 0) && (errno == ENXIO);
|
|
|
|
}
|
|
|
|
|
2013-04-12 22:02:37 +04:00
|
|
|
static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
|
2013-09-05 16:22:29 +04:00
|
|
|
int bdrv_flags, Error **errp)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
2014-02-17 20:11:11 +04:00
|
|
|
int open_flags = 0;
|
2012-09-27 18:00:32 +04:00
|
|
|
int ret = 0;
|
2016-07-19 19:57:32 +03:00
|
|
|
BlockdevOptionsGluster *gconf = NULL;
|
2013-04-12 19:50:16 +04:00
|
|
|
QemuOpts *opts;
|
|
|
|
Error *local_err = NULL;
|
|
|
|
const char *filename;
|
|
|
|
|
2014-01-02 06:49:17 +04:00
|
|
|
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
2013-04-12 19:50:16 +04:00
|
|
|
qemu_opts_absorb_qdict(opts, options, &local_err);
|
2014-01-30 18:07:28 +04:00
|
|
|
if (local_err) {
|
2014-02-17 17:43:55 +04:00
|
|
|
error_propagate(errp, local_err);
|
2013-04-12 19:50:16 +04:00
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2016-04-08 00:24:19 +03:00
|
|
|
filename = qemu_opt_get(opts, GLUSTER_OPT_FILENAME);
|
|
|
|
|
|
|
|
s->debug_level = qemu_opt_get_number(opts, GLUSTER_OPT_DEBUG,
|
|
|
|
GLUSTER_DEBUG_DEFAULT);
|
|
|
|
if (s->debug_level < 0) {
|
|
|
|
s->debug_level = 0;
|
|
|
|
} else if (s->debug_level > GLUSTER_DEBUG_MAX) {
|
|
|
|
s->debug_level = GLUSTER_DEBUG_MAX;
|
|
|
|
}
|
2013-04-12 19:50:16 +04:00
|
|
|
|
2016-07-19 19:57:32 +03:00
|
|
|
gconf = g_new0(BlockdevOptionsGluster, 1);
|
2016-04-08 00:24:19 +03:00
|
|
|
gconf->debug_level = s->debug_level;
|
2016-07-19 19:57:32 +03:00
|
|
|
gconf->has_debug_level = true;
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
s->glfs = qemu_gluster_init(gconf, filename, options, errp);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (!s->glfs) {
|
|
|
|
ret = -errno;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:40:09 +03:00
|
|
|
#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
|
|
|
|
/* Without this, if fsync fails for a recoverable reason (for instance,
|
|
|
|
* ENOSPC), gluster will dump its cache, preventing retries. This means
|
|
|
|
* almost certain data loss. Not all gluster versions support the
|
|
|
|
* 'resync-failed-syncs-after-fsync' key value, but there is no way to
|
|
|
|
* discover during runtime if it is supported (this api returns success for
|
|
|
|
* unknown key/value pairs) */
|
|
|
|
ret = glfs_set_xlator_option(s->glfs, "*-write-behind",
|
|
|
|
"resync-failed-syncs-after-fsync",
|
|
|
|
"on");
|
|
|
|
if (ret < 0) {
|
|
|
|
error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
|
|
|
|
ret = -errno;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-02-17 20:11:11 +04:00
|
|
|
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2016-07-19 19:57:29 +03:00
|
|
|
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (!s->fd) {
|
|
|
|
ret = -errno;
|
|
|
|
}
|
|
|
|
|
2016-03-10 21:38:00 +03:00
|
|
|
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
|
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
out:
|
2013-04-12 19:50:16 +04:00
|
|
|
qemu_opts_del(opts);
|
2016-07-19 19:57:32 +03:00
|
|
|
qapi_free_BlockdevOptionsGluster(gconf);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (!ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (s->fd) {
|
|
|
|
glfs_close(s->fd);
|
|
|
|
}
|
|
|
|
if (s->glfs) {
|
|
|
|
glfs_fini(s->glfs);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-02-17 20:11:12 +04:00
|
|
|
static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
|
|
|
|
BlockReopenQueue *queue, Error **errp)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2016-04-08 00:24:19 +03:00
|
|
|
BDRVGlusterState *s;
|
2014-02-17 20:11:12 +04:00
|
|
|
BDRVGlusterReopenState *reop_s;
|
2016-07-19 19:57:32 +03:00
|
|
|
BlockdevOptionsGluster *gconf;
|
2014-02-17 20:11:12 +04:00
|
|
|
int open_flags = 0;
|
|
|
|
|
|
|
|
assert(state != NULL);
|
|
|
|
assert(state->bs != NULL);
|
|
|
|
|
2016-04-08 00:24:19 +03:00
|
|
|
s = state->bs->opaque;
|
|
|
|
|
block: Use g_new() & friends where that makes obvious sense
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer,
for two reasons. One, it catches multiplication overflowing size_t.
Two, it returns T * rather than void *, which lets the compiler catch
more type errors.
Patch created with Coccinelle, with two manual changes on top:
* Add const to bdrv_iterate_format() to keep the types straight
* Convert the allocation in bdrv_drop_intermediate(), which Coccinelle
inexplicably misses
Coccinelle semantic patch:
@@
type T;
@@
-g_malloc(sizeof(T))
+g_new(T, 1)
@@
type T;
@@
-g_try_malloc(sizeof(T))
+g_try_new(T, 1)
@@
type T;
@@
-g_malloc0(sizeof(T))
+g_new0(T, 1)
@@
type T;
@@
-g_try_malloc0(sizeof(T))
+g_try_new0(T, 1)
@@
type T;
expression n;
@@
-g_malloc(sizeof(T) * (n))
+g_new(T, n)
@@
type T;
expression n;
@@
-g_try_malloc(sizeof(T) * (n))
+g_try_new(T, n)
@@
type T;
expression n;
@@
-g_malloc0(sizeof(T) * (n))
+g_new0(T, n)
@@
type T;
expression n;
@@
-g_try_malloc0(sizeof(T) * (n))
+g_try_new0(T, n)
@@
type T;
expression p, n;
@@
-g_realloc(p, sizeof(T) * (n))
+g_renew(T, p, n)
@@
type T;
expression p, n;
@@
-g_try_realloc(p, sizeof(T) * (n))
+g_try_renew(T, p, n)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-08-19 12:31:08 +04:00
|
|
|
state->opaque = g_new0(BDRVGlusterReopenState, 1);
|
2014-02-17 20:11:12 +04:00
|
|
|
reop_s = state->opaque;
|
|
|
|
|
|
|
|
qemu_gluster_parse_flags(state->flags, &open_flags);
|
|
|
|
|
2016-07-19 19:57:32 +03:00
|
|
|
gconf = g_new0(BlockdevOptionsGluster, 1);
|
2016-04-08 00:24:19 +03:00
|
|
|
gconf->debug_level = s->debug_level;
|
2016-07-19 19:57:32 +03:00
|
|
|
gconf->has_debug_level = true;
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, NULL, errp);
|
2014-02-17 20:11:12 +04:00
|
|
|
if (reop_s->glfs == NULL) {
|
|
|
|
ret = -errno;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:40:09 +03:00
|
|
|
#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
|
|
|
|
ret = glfs_set_xlator_option(reop_s->glfs, "*-write-behind",
|
|
|
|
"resync-failed-syncs-after-fsync", "on");
|
|
|
|
if (ret < 0) {
|
|
|
|
error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
|
|
|
|
ret = -errno;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-07-19 19:57:29 +03:00
|
|
|
reop_s->fd = glfs_open(reop_s->glfs, gconf->path, open_flags);
|
2014-02-17 20:11:12 +04:00
|
|
|
if (reop_s->fd == NULL) {
|
|
|
|
/* reops->glfs will be cleaned up in _abort */
|
|
|
|
ret = -errno;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
/* state->opaque will be freed in either the _abort or _commit */
|
2016-07-19 19:57:32 +03:00
|
|
|
qapi_free_BlockdevOptionsGluster(gconf);
|
2014-02-17 20:11:12 +04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qemu_gluster_reopen_commit(BDRVReopenState *state)
|
|
|
|
{
|
|
|
|
BDRVGlusterReopenState *reop_s = state->opaque;
|
|
|
|
BDRVGlusterState *s = state->bs->opaque;
|
|
|
|
|
|
|
|
|
|
|
|
/* close the old */
|
|
|
|
if (s->fd) {
|
|
|
|
glfs_close(s->fd);
|
|
|
|
}
|
|
|
|
if (s->glfs) {
|
|
|
|
glfs_fini(s->glfs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* use the newly opened image / connection */
|
|
|
|
s->fd = reop_s->fd;
|
|
|
|
s->glfs = reop_s->glfs;
|
|
|
|
|
|
|
|
g_free(state->opaque);
|
|
|
|
state->opaque = NULL;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void qemu_gluster_reopen_abort(BDRVReopenState *state)
|
|
|
|
{
|
|
|
|
BDRVGlusterReopenState *reop_s = state->opaque;
|
|
|
|
|
|
|
|
if (reop_s == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reop_s->fd) {
|
|
|
|
glfs_close(reop_s->fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reop_s->glfs) {
|
|
|
|
glfs_fini(reop_s->glfs);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(state->opaque);
|
|
|
|
state->opaque = NULL;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:25 +04:00
|
|
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
2016-06-02 00:10:08 +03:00
|
|
|
static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
|
2016-07-19 19:57:30 +03:00
|
|
|
int64_t offset,
|
|
|
|
int size,
|
|
|
|
BdrvRequestFlags flags)
|
2013-12-21 13:21:25 +04:00
|
|
|
{
|
|
|
|
int ret;
|
2015-10-01 14:04:38 +03:00
|
|
|
GlusterAIOCB acb;
|
2013-12-21 13:21:25 +04:00
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
acb.size = size;
|
|
|
|
acb.ret = 0;
|
|
|
|
acb.coroutine = qemu_coroutine_self();
|
|
|
|
acb.aio_context = bdrv_get_aio_context(bs);
|
2013-12-21 13:21:25 +04:00
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
ret = glfs_zerofill_async(s->fd, offset, size, gluster_finish_aiocb, &acb);
|
2013-12-21 13:21:25 +04:00
|
|
|
if (ret < 0) {
|
2015-10-01 14:04:38 +03:00
|
|
|
return -errno;
|
2013-12-21 13:21:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
qemu_coroutine_yield();
|
2015-10-01 14:04:38 +03:00
|
|
|
return acb.ret;
|
2013-12-21 13:21:25 +04:00
|
|
|
}
|
2013-12-21 13:21:26 +04:00
|
|
|
|
|
|
|
static inline bool gluster_supports_zerofill(void)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
|
2016-07-19 19:57:30 +03:00
|
|
|
int64_t size)
|
2013-12-21 13:21:26 +04:00
|
|
|
{
|
|
|
|
return glfs_zerofill(fd, offset, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
static inline bool gluster_supports_zerofill(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
|
2016-07-19 19:57:30 +03:00
|
|
|
int64_t size)
|
2013-12-21 13:21:26 +04:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2013-12-21 13:21:25 +04:00
|
|
|
#endif
|
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
static int qemu_gluster_create(const char *filename,
|
2014-06-05 13:20:54 +04:00
|
|
|
QemuOpts *opts, Error **errp)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
2016-07-19 19:57:32 +03:00
|
|
|
BlockdevOptionsGluster *gconf;
|
2012-09-27 18:00:32 +04:00
|
|
|
struct glfs *glfs;
|
|
|
|
struct glfs_fd *fd;
|
|
|
|
int ret = 0;
|
2013-12-21 13:21:26 +04:00
|
|
|
int prealloc = 0;
|
2012-09-27 18:00:32 +04:00
|
|
|
int64_t total_size = 0;
|
2014-06-05 13:20:54 +04:00
|
|
|
char *tmp = NULL;
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2016-07-19 19:57:32 +03:00
|
|
|
gconf = g_new0(BlockdevOptionsGluster, 1);
|
2016-04-08 00:24:19 +03:00
|
|
|
gconf->debug_level = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
|
|
|
|
GLUSTER_DEBUG_DEFAULT);
|
|
|
|
if (gconf->debug_level < 0) {
|
|
|
|
gconf->debug_level = 0;
|
|
|
|
} else if (gconf->debug_level > GLUSTER_DEBUG_MAX) {
|
|
|
|
gconf->debug_level = GLUSTER_DEBUG_MAX;
|
|
|
|
}
|
2016-07-19 19:57:32 +03:00
|
|
|
gconf->has_debug_level = true;
|
2016-04-08 00:24:19 +03:00
|
|
|
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
glfs = qemu_gluster_init(gconf, filename, NULL, errp);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (!glfs) {
|
2014-05-09 14:08:10 +04:00
|
|
|
ret = -errno;
|
2012-09-27 18:00:32 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2014-09-10 13:05:46 +04:00
|
|
|
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
|
|
|
|
BDRV_SECTOR_SIZE);
|
2014-06-05 13:20:54 +04:00
|
|
|
|
|
|
|
tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
|
|
|
if (!tmp || !strcmp(tmp, "off")) {
|
|
|
|
prealloc = 0;
|
2016-07-19 19:57:30 +03:00
|
|
|
} else if (!strcmp(tmp, "full") && gluster_supports_zerofill()) {
|
2014-06-05 13:20:54 +04:00
|
|
|
prealloc = 1;
|
|
|
|
} else {
|
|
|
|
error_setg(errp, "Invalid preallocation mode: '%s'"
|
2016-07-19 19:57:30 +03:00
|
|
|
" or GlusterFS doesn't support zerofill API", tmp);
|
2014-06-05 13:20:54 +04:00
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2016-07-19 19:57:29 +03:00
|
|
|
fd = glfs_creat(glfs, gconf->path,
|
2016-07-19 19:57:30 +03:00
|
|
|
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (!fd) {
|
|
|
|
ret = -errno;
|
|
|
|
} else {
|
2014-09-10 13:05:46 +04:00
|
|
|
if (!glfs_ftruncate(fd, total_size)) {
|
|
|
|
if (prealloc && qemu_gluster_zerofill(fd, 0, total_size)) {
|
2013-12-21 13:21:26 +04:00
|
|
|
ret = -errno;
|
|
|
|
}
|
|
|
|
} else {
|
2012-09-27 18:00:32 +04:00
|
|
|
ret = -errno;
|
|
|
|
}
|
2013-12-21 13:21:26 +04:00
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
if (glfs_close(fd) != 0) {
|
|
|
|
ret = -errno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out:
|
2014-06-05 13:20:54 +04:00
|
|
|
g_free(tmp);
|
2016-07-19 19:57:32 +03:00
|
|
|
qapi_free_BlockdevOptionsGluster(gconf);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (glfs) {
|
|
|
|
glfs_fini(glfs);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:24 +04:00
|
|
|
static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
|
2016-07-19 19:57:30 +03:00
|
|
|
int64_t sector_num, int nb_sectors,
|
|
|
|
QEMUIOVector *qiov, int write)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
|
|
|
int ret;
|
2015-10-01 14:04:38 +03:00
|
|
|
GlusterAIOCB acb;
|
2012-09-27 18:00:32 +04:00
|
|
|
BDRVGlusterState *s = bs->opaque;
|
2013-12-21 13:21:24 +04:00
|
|
|
size_t size = nb_sectors * BDRV_SECTOR_SIZE;
|
|
|
|
off_t offset = sector_num * BDRV_SECTOR_SIZE;
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
acb.size = size;
|
|
|
|
acb.ret = 0;
|
|
|
|
acb.coroutine = qemu_coroutine_self();
|
|
|
|
acb.aio_context = bdrv_get_aio_context(bs);
|
2012-09-27 18:00:32 +04:00
|
|
|
|
|
|
|
if (write) {
|
|
|
|
ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
|
2016-07-19 19:57:30 +03:00
|
|
|
gluster_finish_aiocb, &acb);
|
2012-09-27 18:00:32 +04:00
|
|
|
} else {
|
|
|
|
ret = glfs_preadv_async(s->fd, qiov->iov, qiov->niov, offset, 0,
|
2016-07-19 19:57:30 +03:00
|
|
|
gluster_finish_aiocb, &acb);
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ret < 0) {
|
2015-10-01 14:04:38 +03:00
|
|
|
return -errno;
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
2013-12-21 13:21:24 +04:00
|
|
|
|
|
|
|
qemu_coroutine_yield();
|
2015-10-01 14:04:38 +03:00
|
|
|
return acb.ret;
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2013-07-19 18:21:33 +04:00
|
|
|
static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
|
|
|
|
ret = glfs_ftruncate(s->fd, offset);
|
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:24 +04:00
|
|
|
static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
|
2016-07-19 19:57:30 +03:00
|
|
|
int64_t sector_num,
|
|
|
|
int nb_sectors,
|
|
|
|
QEMUIOVector *qiov)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
2013-12-21 13:21:24 +04:00
|
|
|
return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 0);
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:24 +04:00
|
|
|
static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
|
2016-07-19 19:57:30 +03:00
|
|
|
int64_t sector_num,
|
|
|
|
int nb_sectors,
|
|
|
|
QEMUIOVector *qiov)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
2013-12-21 13:21:24 +04:00
|
|
|
return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2016-04-15 23:29:06 +03:00
|
|
|
static void qemu_gluster_close(BlockDriverState *bs)
|
|
|
|
{
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
|
|
|
|
if (s->fd) {
|
|
|
|
glfs_close(s->fd);
|
|
|
|
s->fd = NULL;
|
|
|
|
}
|
|
|
|
glfs_fini(s->glfs);
|
|
|
|
}
|
|
|
|
|
2013-12-21 13:21:24 +04:00
|
|
|
static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
|
2012-09-27 18:00:32 +04:00
|
|
|
{
|
|
|
|
int ret;
|
2015-10-01 14:04:38 +03:00
|
|
|
GlusterAIOCB acb;
|
2012-09-27 18:00:32 +04:00
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
acb.size = 0;
|
|
|
|
acb.ret = 0;
|
|
|
|
acb.coroutine = qemu_coroutine_self();
|
|
|
|
acb.aio_context = bdrv_get_aio_context(bs);
|
2012-09-27 18:00:32 +04:00
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
ret = glfs_fsync_async(s->fd, gluster_finish_aiocb, &acb);
|
2012-09-27 18:00:32 +04:00
|
|
|
if (ret < 0) {
|
2016-04-05 17:40:09 +03:00
|
|
|
ret = -errno;
|
|
|
|
goto error;
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
2013-12-21 13:21:24 +04:00
|
|
|
|
|
|
|
qemu_coroutine_yield();
|
2016-04-05 17:40:09 +03:00
|
|
|
if (acb.ret < 0) {
|
|
|
|
ret = acb.ret;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
return acb.ret;
|
2016-04-05 17:40:09 +03:00
|
|
|
|
|
|
|
error:
|
|
|
|
/* Some versions of Gluster (3.5.6 -> 3.5.8?) will not retain its cache
|
|
|
|
* after a fsync failure, so we have no way of allowing the guest to safely
|
|
|
|
* continue. Gluster versions prior to 3.5.6 don't retain the cache
|
|
|
|
* either, but will invalidate the fd on error, so this is again our only
|
|
|
|
* option.
|
|
|
|
*
|
|
|
|
* The 'resync-failed-syncs-after-fsync' xlator option for the
|
|
|
|
* write-behind cache will cause later gluster versions to retain its
|
|
|
|
* cache after error, so long as the fd remains open. However, we
|
|
|
|
* currently have no way of knowing if this option is supported.
|
|
|
|
*
|
|
|
|
* TODO: Once gluster provides a way for us to determine if the option
|
|
|
|
* is supported, bypass the closure and setting drv to NULL. */
|
|
|
|
qemu_gluster_close(bs);
|
|
|
|
bs->drv = NULL;
|
|
|
|
return ret;
|
2012-09-27 18:00:32 +04:00
|
|
|
}
|
|
|
|
|
2013-07-16 20:17:42 +04:00
|
|
|
#ifdef CONFIG_GLUSTERFS_DISCARD
|
2016-07-16 02:23:00 +03:00
|
|
|
static coroutine_fn int qemu_gluster_co_pdiscard(BlockDriverState *bs,
|
|
|
|
int64_t offset, int size)
|
2013-07-16 20:17:42 +04:00
|
|
|
{
|
|
|
|
int ret;
|
2015-10-01 14:04:38 +03:00
|
|
|
GlusterAIOCB acb;
|
2013-07-16 20:17:42 +04:00
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
acb.size = 0;
|
|
|
|
acb.ret = 0;
|
|
|
|
acb.coroutine = qemu_coroutine_self();
|
|
|
|
acb.aio_context = bdrv_get_aio_context(bs);
|
2013-07-16 20:17:42 +04:00
|
|
|
|
2015-10-01 14:04:38 +03:00
|
|
|
ret = glfs_discard_async(s->fd, offset, size, gluster_finish_aiocb, &acb);
|
2013-07-16 20:17:42 +04:00
|
|
|
if (ret < 0) {
|
2015-10-01 14:04:38 +03:00
|
|
|
return -errno;
|
2013-07-16 20:17:42 +04:00
|
|
|
}
|
2013-12-21 13:21:24 +04:00
|
|
|
|
|
|
|
qemu_coroutine_yield();
|
2015-10-01 14:04:38 +03:00
|
|
|
return acb.ret;
|
2013-07-16 20:17:42 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
static int64_t qemu_gluster_getlength(BlockDriverState *bs)
|
|
|
|
{
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
int64_t ret;
|
|
|
|
|
|
|
|
ret = glfs_lseek(s->fd, 0, SEEK_END);
|
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
} else {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs)
|
|
|
|
{
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
struct stat st;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = glfs_fstat(s->fd, &st);
|
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
} else {
|
|
|
|
return st.st_blocks * 512;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-26 11:41:57 +04:00
|
|
|
static int qemu_gluster_has_zero_init(BlockDriverState *bs)
|
|
|
|
{
|
|
|
|
/* GlusterFS volume could be backed by a block device */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-10 21:38:00 +03:00
|
|
|
/*
|
|
|
|
* Find allocation range in @bs around offset @start.
|
|
|
|
* May change underlying file descriptor's file offset.
|
|
|
|
* If @start is not in a hole, store @start in @data, and the
|
|
|
|
* beginning of the next hole in @hole, and return 0.
|
|
|
|
* If @start is in a non-trailing hole, store @start in @hole and the
|
|
|
|
* beginning of the next non-hole in @data, and return 0.
|
|
|
|
* If @start is in a trailing hole or beyond EOF, return -ENXIO.
|
|
|
|
* If we can't find out, return a negative errno other than -ENXIO.
|
|
|
|
*
|
|
|
|
* (Shamefully copied from raw-posix.c, only miniscule adaptions.)
|
|
|
|
*/
|
|
|
|
static int find_allocation(BlockDriverState *bs, off_t start,
|
|
|
|
off_t *data, off_t *hole)
|
|
|
|
{
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
off_t offs;
|
|
|
|
|
|
|
|
if (!s->supports_seek_data) {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SEEK_DATA cases:
|
|
|
|
* D1. offs == start: start is in data
|
|
|
|
* D2. offs > start: start is in a hole, next data at offs
|
|
|
|
* D3. offs < 0, errno = ENXIO: either start is in a trailing hole
|
|
|
|
* or start is beyond EOF
|
|
|
|
* If the latter happens, the file has been truncated behind
|
|
|
|
* our back since we opened it. All bets are off then.
|
|
|
|
* Treating like a trailing hole is simplest.
|
|
|
|
* D4. offs < 0, errno != ENXIO: we learned nothing
|
|
|
|
*/
|
|
|
|
offs = glfs_lseek(s->fd, start, SEEK_DATA);
|
|
|
|
if (offs < 0) {
|
|
|
|
return -errno; /* D3 or D4 */
|
|
|
|
}
|
|
|
|
assert(offs >= start);
|
|
|
|
|
|
|
|
if (offs > start) {
|
|
|
|
/* D2: in hole, next data at offs */
|
|
|
|
*hole = start;
|
|
|
|
*data = offs;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* D1: in data, end not yet known */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SEEK_HOLE cases:
|
|
|
|
* H1. offs == start: start is in a hole
|
|
|
|
* If this happens here, a hole has been dug behind our back
|
|
|
|
* since the previous lseek().
|
|
|
|
* H2. offs > start: either start is in data, next hole at offs,
|
|
|
|
* or start is in trailing hole, EOF at offs
|
|
|
|
* Linux treats trailing holes like any other hole: offs ==
|
|
|
|
* start. Solaris seeks to EOF instead: offs > start (blech).
|
|
|
|
* If that happens here, a hole has been dug behind our back
|
|
|
|
* since the previous lseek().
|
|
|
|
* H3. offs < 0, errno = ENXIO: start is beyond EOF
|
|
|
|
* If this happens, the file has been truncated behind our
|
|
|
|
* back since we opened it. Treat it like a trailing hole.
|
|
|
|
* H4. offs < 0, errno != ENXIO: we learned nothing
|
|
|
|
* Pretend we know nothing at all, i.e. "forget" about D1.
|
|
|
|
*/
|
|
|
|
offs = glfs_lseek(s->fd, start, SEEK_HOLE);
|
|
|
|
if (offs < 0) {
|
|
|
|
return -errno; /* D1 and (H3 or H4) */
|
|
|
|
}
|
|
|
|
assert(offs >= start);
|
|
|
|
|
|
|
|
if (offs > start) {
|
|
|
|
/*
|
|
|
|
* D1 and H2: either in data, next hole at offs, or it was in
|
|
|
|
* data but is now in a trailing hole. In the latter case,
|
|
|
|
* all bets are off. Treating it as if it there was data all
|
|
|
|
* the way to EOF is safe, so simply do that.
|
|
|
|
*/
|
|
|
|
*data = start;
|
|
|
|
*hole = offs;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* D1 and H1 */
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the allocation status of the specified sectors.
|
|
|
|
*
|
|
|
|
* If 'sector_num' is beyond the end of the disk image the return value is 0
|
|
|
|
* and 'pnum' is set to 0.
|
|
|
|
*
|
|
|
|
* 'pnum' is set to the number of sectors (including and immediately following
|
|
|
|
* the specified sector) that are known to be in the same
|
|
|
|
* allocated/unallocated state.
|
|
|
|
*
|
|
|
|
* 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
|
|
|
|
* beyond the end of the disk image it will be clamped.
|
|
|
|
*
|
|
|
|
* (Based on raw_co_get_block_status() from raw-posix.c.)
|
|
|
|
*/
|
|
|
|
static int64_t coroutine_fn qemu_gluster_co_get_block_status(
|
|
|
|
BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
|
|
|
|
BlockDriverState **file)
|
|
|
|
{
|
|
|
|
BDRVGlusterState *s = bs->opaque;
|
|
|
|
off_t start, data = 0, hole = 0;
|
|
|
|
int64_t total_size;
|
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
|
|
if (!s->fd) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = sector_num * BDRV_SECTOR_SIZE;
|
|
|
|
total_size = bdrv_getlength(bs);
|
|
|
|
if (total_size < 0) {
|
|
|
|
return total_size;
|
|
|
|
} else if (start >= total_size) {
|
|
|
|
*pnum = 0;
|
|
|
|
return 0;
|
|
|
|
} else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
|
|
|
|
nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = find_allocation(bs, start, &data, &hole);
|
|
|
|
if (ret == -ENXIO) {
|
|
|
|
/* Trailing hole */
|
|
|
|
*pnum = nb_sectors;
|
|
|
|
ret = BDRV_BLOCK_ZERO;
|
|
|
|
} else if (ret < 0) {
|
|
|
|
/* No info available, so pretend there are no holes */
|
|
|
|
*pnum = nb_sectors;
|
|
|
|
ret = BDRV_BLOCK_DATA;
|
|
|
|
} else if (data == start) {
|
|
|
|
/* On a data extent, compute sectors to the end of the extent,
|
|
|
|
* possibly including a partial sector at EOF. */
|
|
|
|
*pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
|
|
|
|
ret = BDRV_BLOCK_DATA;
|
|
|
|
} else {
|
|
|
|
/* On a hole, compute sectors to the beginning of the next extent. */
|
|
|
|
assert(hole == start);
|
|
|
|
*pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
|
|
|
|
ret = BDRV_BLOCK_ZERO;
|
|
|
|
}
|
|
|
|
|
|
|
|
*file = bs;
|
|
|
|
|
|
|
|
return ret | BDRV_BLOCK_OFFSET_VALID | start;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-27 18:00:32 +04:00
|
|
|
static BlockDriver bdrv_gluster = {
|
|
|
|
.format_name = "gluster",
|
|
|
|
.protocol_name = "gluster",
|
|
|
|
.instance_size = sizeof(BDRVGlusterState),
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
.bdrv_needs_filename = false,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_file_open = qemu_gluster_open,
|
2014-02-17 20:11:12 +04:00
|
|
|
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
|
|
|
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
|
|
|
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_close = qemu_gluster_close,
|
2014-06-05 13:21:11 +04:00
|
|
|
.bdrv_create = qemu_gluster_create,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_getlength = qemu_gluster_getlength,
|
|
|
|
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
2013-07-19 18:21:33 +04:00
|
|
|
.bdrv_truncate = qemu_gluster_truncate,
|
2013-12-21 13:21:24 +04:00
|
|
|
.bdrv_co_readv = qemu_gluster_co_readv,
|
|
|
|
.bdrv_co_writev = qemu_gluster_co_writev,
|
|
|
|
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
2013-06-26 11:41:57 +04:00
|
|
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
2013-07-16 20:17:42 +04:00
|
|
|
#ifdef CONFIG_GLUSTERFS_DISCARD
|
2016-07-16 02:23:00 +03:00
|
|
|
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
2013-12-21 13:21:25 +04:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
2016-06-02 00:10:08 +03:00
|
|
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
2013-07-16 20:17:42 +04:00
|
|
|
#endif
|
2016-03-10 21:38:00 +03:00
|
|
|
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
2014-06-05 13:20:54 +04:00
|
|
|
.create_opts = &qemu_gluster_create_opts,
|
2012-09-27 18:00:32 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static BlockDriver bdrv_gluster_tcp = {
|
|
|
|
.format_name = "gluster",
|
|
|
|
.protocol_name = "gluster+tcp",
|
|
|
|
.instance_size = sizeof(BDRVGlusterState),
|
block/gluster: add support for multiple gluster servers
This patch adds a way to specify multiple volfile servers to the gluster
block backend of QEMU with tcp|rdma transport types and their port numbers.
Problem:
Currently VM Image on gluster volume is specified like this:
file=gluster[+tcp]://host[:port]/testvol/a.img
Say we have three hosts in a trusted pool with replica 3 volume in action.
When the host mentioned in the command above goes down for some reason,
the other two hosts are still available. But there's currently no way
to tell QEMU about them.
Solution:
New way of specifying VM Image on gluster volume with volfile servers:
(We still support old syntax to maintain backward compatibility)
Basic command line syntax looks like:
Pattern I:
-drive driver=gluster,
volume=testvol,path=/path/a.raw,[debug=N,]
server.0.type=tcp,
server.0.host=1.2.3.4,
server.0.port=24007,
server.1.type=unix,
server.1.socket=/path/socketfile
Pattern II:
'json:{"driver":"qcow2","file":{"driver":"gluster",
"volume":"testvol","path":"/path/a.qcow2",["debug":N,]
"server":[{hostinfo_1}, ...{hostinfo_N}]}}'
driver => 'gluster' (protocol name)
volume => name of gluster volume where our VM image resides
path => absolute path of image in gluster volume
[debug] => libgfapi loglevel [(0 - 9) default 4 -> Error]
{hostinfo} => {{type:"tcp",host:"1.2.3.4"[,port=24007]},
{type:"unix",socket:"/path/sockfile"}}
type => transport type used to connect to gluster management daemon,
it can be tcp|unix
host => host address (hostname/ipv4/ipv6 addresses/socket path)
port => port number on which glusterd is listening.
socket => path to socket file
Examples:
1.
-drive driver=qcow2,file.driver=gluster,
file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
file.server.0.type=tcp,
file.server.0.host=1.2.3.4,
file.server.0.port=24007,
file.server.1.type=unix,
file.server.1.socket=/var/run/glusterd.socket
2.
'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
"path":"/path/a.qcow2","debug":9,"server":
[{"type":"tcp","host":"1.2.3.4","port":"24007"},
{"type":"unix","socket":"/var/run/glusterd.socket"}
]}}'
This patch gives a mechanism to provide all the server addresses, which are in
replica set, so in case host1 is down VM can still boot from any of the
active hosts.
This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)
credits: sincere thanks to all the supporters
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1468947453-5433-6-git-send-email-prasanna.kalever@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-07-19 19:57:33 +03:00
|
|
|
.bdrv_needs_filename = false,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_file_open = qemu_gluster_open,
|
2014-02-17 20:11:12 +04:00
|
|
|
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
|
|
|
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
|
|
|
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_close = qemu_gluster_close,
|
2014-06-05 13:21:11 +04:00
|
|
|
.bdrv_create = qemu_gluster_create,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_getlength = qemu_gluster_getlength,
|
|
|
|
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
2013-07-19 18:21:33 +04:00
|
|
|
.bdrv_truncate = qemu_gluster_truncate,
|
2013-12-21 13:21:24 +04:00
|
|
|
.bdrv_co_readv = qemu_gluster_co_readv,
|
|
|
|
.bdrv_co_writev = qemu_gluster_co_writev,
|
|
|
|
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
2013-06-26 11:41:57 +04:00
|
|
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
2013-07-16 20:17:42 +04:00
|
|
|
#ifdef CONFIG_GLUSTERFS_DISCARD
|
2016-07-16 02:23:00 +03:00
|
|
|
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
2013-12-21 13:21:25 +04:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
2016-06-02 00:10:08 +03:00
|
|
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
2013-07-16 20:17:42 +04:00
|
|
|
#endif
|
2016-03-10 21:38:00 +03:00
|
|
|
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
2014-06-05 13:20:54 +04:00
|
|
|
.create_opts = &qemu_gluster_create_opts,
|
2012-09-27 18:00:32 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static BlockDriver bdrv_gluster_unix = {
|
|
|
|
.format_name = "gluster",
|
|
|
|
.protocol_name = "gluster+unix",
|
|
|
|
.instance_size = sizeof(BDRVGlusterState),
|
2013-09-24 19:07:04 +04:00
|
|
|
.bdrv_needs_filename = true,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_file_open = qemu_gluster_open,
|
2014-02-17 20:11:12 +04:00
|
|
|
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
|
|
|
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
|
|
|
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_close = qemu_gluster_close,
|
2014-06-05 13:21:11 +04:00
|
|
|
.bdrv_create = qemu_gluster_create,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_getlength = qemu_gluster_getlength,
|
|
|
|
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
2013-07-19 18:21:33 +04:00
|
|
|
.bdrv_truncate = qemu_gluster_truncate,
|
2013-12-21 13:21:24 +04:00
|
|
|
.bdrv_co_readv = qemu_gluster_co_readv,
|
|
|
|
.bdrv_co_writev = qemu_gluster_co_writev,
|
|
|
|
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
2013-06-26 11:41:57 +04:00
|
|
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
2013-07-16 20:17:42 +04:00
|
|
|
#ifdef CONFIG_GLUSTERFS_DISCARD
|
2016-07-16 02:23:00 +03:00
|
|
|
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
2013-12-21 13:21:25 +04:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
2016-06-02 00:10:08 +03:00
|
|
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
2013-07-16 20:17:42 +04:00
|
|
|
#endif
|
2016-03-10 21:38:00 +03:00
|
|
|
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
2014-06-05 13:20:54 +04:00
|
|
|
.create_opts = &qemu_gluster_create_opts,
|
2012-09-27 18:00:32 +04:00
|
|
|
};
|
|
|
|
|
2016-07-19 19:57:31 +03:00
|
|
|
/* rdma is deprecated (actually never supported for volfile fetch).
|
|
|
|
* Let's maintain it for the protocol compatibility, to make sure things
|
|
|
|
* won't break immediately. For now, gluster+rdma will fall back to gluster+tcp
|
|
|
|
* protocol with a warning.
|
|
|
|
* TODO: remove gluster+rdma interface support
|
|
|
|
*/
|
2012-09-27 18:00:32 +04:00
|
|
|
static BlockDriver bdrv_gluster_rdma = {
|
|
|
|
.format_name = "gluster",
|
|
|
|
.protocol_name = "gluster+rdma",
|
|
|
|
.instance_size = sizeof(BDRVGlusterState),
|
2013-09-24 19:07:04 +04:00
|
|
|
.bdrv_needs_filename = true,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_file_open = qemu_gluster_open,
|
2014-02-17 20:11:12 +04:00
|
|
|
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
|
|
|
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
|
|
|
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_close = qemu_gluster_close,
|
2014-06-05 13:21:11 +04:00
|
|
|
.bdrv_create = qemu_gluster_create,
|
2012-09-27 18:00:32 +04:00
|
|
|
.bdrv_getlength = qemu_gluster_getlength,
|
|
|
|
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
2013-07-19 18:21:33 +04:00
|
|
|
.bdrv_truncate = qemu_gluster_truncate,
|
2013-12-21 13:21:24 +04:00
|
|
|
.bdrv_co_readv = qemu_gluster_co_readv,
|
|
|
|
.bdrv_co_writev = qemu_gluster_co_writev,
|
|
|
|
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
2013-06-26 11:41:57 +04:00
|
|
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
2013-07-16 20:17:42 +04:00
|
|
|
#ifdef CONFIG_GLUSTERFS_DISCARD
|
2016-07-16 02:23:00 +03:00
|
|
|
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
2013-12-21 13:21:25 +04:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
2016-06-02 00:10:08 +03:00
|
|
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
2013-07-16 20:17:42 +04:00
|
|
|
#endif
|
2016-03-10 21:38:00 +03:00
|
|
|
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
2014-06-05 13:20:54 +04:00
|
|
|
.create_opts = &qemu_gluster_create_opts,
|
2012-09-27 18:00:32 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static void bdrv_gluster_init(void)
|
|
|
|
{
|
|
|
|
bdrv_register(&bdrv_gluster_rdma);
|
|
|
|
bdrv_register(&bdrv_gluster_unix);
|
|
|
|
bdrv_register(&bdrv_gluster_tcp);
|
|
|
|
bdrv_register(&bdrv_gluster);
|
|
|
|
}
|
|
|
|
|
|
|
|
block_init(bdrv_gluster_init);
|