Re: [Qemu-devel] [PATCH v3 2/2] block: Support GlusterFS as a QEMU block backend

2012-07-28 Thread Blue Swirl
On Sat, Jul 28, 2012 at 4:43 AM, Bharata B Rao
bhar...@linux.vnet.ibm.com wrote:
 On Fri, Jul 27, 2012 at 06:44:04PM +, Blue Swirl wrote:
  +struct GlusterOpts {

 static

 Sure.


  +bool optional;
  +char defval[10];

 const char *defval?

 Sure I could.


  +char *value;
  +} GlusterOpts[] = {
  +{false, , NULL },
  +{false, , NULL },
  +{true, 0, NULL },
  +{true, socket, NULL },
  +{false, , NULL },
  +{false, , NULL },
  +};
  +
  +if (i == GOPT_LAST-1  strlen(q)) {

 Spaces around '-'.

 checkpatch.pl doesn't enforce this, but I can change.

  +
  +port = strtoul(GlusterOpts[GOPT_PORT].value, NULL, 0);
  +if (port  0) {

 port  65535 could be bad too.

 Actually I am just checking if strtoul gave me a valid integer only
 and depending on gluster to flag an error for invalid port number.
 But I guess no harm in checking for valid port range here. Is there
 a #define equivalent for 65535 ?

I don't think there is. It may also be possible to omit the check if
the connection function checks it and fails. Accidental modular
arithmetic for the port numbers (65537 % 65536 == 1) would not be so
nice if there are no checks.



  +
  +fd = glfs_creat(glfs, GlusterOpts[GOPT_IMAGE].value,
  +O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR);

 Spaces around '|'.

 Again, checkpatch.pl doesn't enforce this, but I can change.

 Thanks for take time to review.

 Regards,
 Bharata.




Re: [Qemu-devel] [PATCH v3 2/2] block: Support GlusterFS as a QEMU block backend

2012-07-27 Thread Blue Swirl
On Wed, Jul 25, 2012 at 6:00 AM, Bharata B Rao
bhar...@linux.vnet.ibm.com wrote:
 block: Support GlusterFS as a QEMU block backend.

 From: Bharata B Rao bhar...@linux.vnet.ibm.com

 This patch adds gluster as the new block backend in QEMU. This gives
 QEMU the ability to boot VM images from gluster volumes. Its already
 possible to boot from VM images on gluster volumes, but this patchset
 provides the ability to boot VM images from gluster volumes by by-passing
 the FUSE layer in gluster. In case the image is present on the local
 system, it is possible to even bypass client and server translator and
 hence the RPC overhead.

 VM Image on gluster volume is specified like this:

 -drive file=gluster:server:[port]:[transport]:volname:image

 - Here 'gluster' is the protocol.
 - 'server' specifies the server where the volume file specification for
   the given volume resides.
 - 'port' is the port number on which gluster management daemon (glusterd) is
listening. This is optional and if not specified, QEMU will send 0 which
will make libgfapi to use the default port.
 - 'transport' specifies the transport used to connect to glusterd. This is
   optional and if not specified, socket transport is used.
 - 'volname' is the name of the gluster volume which contains the VM image.
 - 'image' is the path to the actual VM image in the gluster volume.

 Eg 1: -drive file=gluster:server1:0:socket:test:/image
 Eg 2: -drive file=gluster:server1:::test:/image

 Signed-off-by: Bharata B Rao bhar...@linux.vnet.ibm.com
 ---

  block/Makefile.objs |1
  block/gluster.c |  484 
 +++
  2 files changed, 485 insertions(+), 0 deletions(-)
  create mode 100644 block/gluster.c


 diff --git a/block/Makefile.objs b/block/Makefile.objs
 index b5754d3..a1ae67f 100644
 --- a/block/Makefile.objs
 +++ b/block/Makefile.objs
 @@ -9,3 +9,4 @@ block-obj-$(CONFIG_POSIX) += raw-posix.o
  block-obj-$(CONFIG_LIBISCSI) += iscsi.o
  block-obj-$(CONFIG_CURL) += curl.o
  block-obj-$(CONFIG_RBD) += rbd.o
 +block-obj-$(CONFIG_GLUSTERFS) += gluster.o
 diff --git a/block/gluster.c b/block/gluster.c
 new file mode 100644
 index 000..b27971b
 --- /dev/null
 +++ b/block/gluster.c
 @@ -0,0 +1,484 @@
 +/*
 + * GlusterFS backend for QEMU
 + *
 + * (AIO implementation is derived from block/rbd.c)
 + *
 + * Copyright (C) 2012 Bharata B Rao bhar...@linux.vnet.ibm.com
 + *
 + * This work is licensed under the terms of the GNU GPL, version 2 or
 + * (at your option) any later version. See the COPYING file in the top-level
 + * directory.
 + */
 +#include block_int.h
 +#include glusterfs/api/glfs.h
 +
 +typedef struct GlusterAIOCB {
 +BlockDriverAIOCB common;
 +bool canceled;
 +int64_t size;
 +int ret;
 +} GlusterAIOCB;
 +
 +typedef struct BDRVGlusterState {
 +struct glfs *glfs;
 +int fds[2];
 +struct glfs_fd *fd;
 +int qemu_aio_count;
 +} BDRVGlusterState;
 +
 +#define GLUSTER_FD_READ 0
 +#define GLUSTER_FD_WRITE 1
 +
 +typedef enum {
 +GOPT_PROTOCOL,
 +GOPT_SERVER,
 +GOPT_PORT,
 +GOPT_TRANSPORT,
 +GOPT_VOLNAME,
 +GOPT_IMAGE,
 +
 +GOPT_LAST,
 +} GlusterOptsEnum;
 +
 +struct GlusterOpts {

static

 +bool optional;
 +char defval[10];

const char *defval?

 +char *value;
 +} GlusterOpts[] = {
 +{false, , NULL },
 +{false, , NULL },
 +{true, 0, NULL },
 +{true, socket, NULL },
 +{false, , NULL },
 +{false, , NULL },
 +};
 +
 +static void qemu_gluster_opts_free(void)
 +{
 +int i;
 +
 +for (i = 0; i  GOPT_LAST; i++) {
 +g_free(GlusterOpts[i].value);
 +/* Prepare GlusterOpts to parse the next gluster drive (if any) */
 +GlusterOpts[i].value = NULL;
 +}
 +}
 +
 +/*
 + * file=protocol:server:[port]:[transport]:volname:image
 + */
 +static int qemu_gluster_parsename(const char *filename)
 +{
 +char *p, *q, *r;
 +int ret = -EINVAL;
 +int i;
 +
 +p = q = r = g_strdup(filename);
 +for (i = 0; i  GOPT_LAST; i++) {
 +q = p;
 +p = strchr(p, ':');
 +if (!p) {
 +goto out;
 +}
 +
 +if (p == q) {
 +if (GlusterOpts[i].optional) {
 +GlusterOpts[i].value = g_strdup(GlusterOpts[i].defval);
 +p++;
 +continue;
 +} else {
 +goto out;
 +}
 +}
 +*p++ = '\0';
 +GlusterOpts[i].value = g_strdup(q);
 +}
 +out:
 +if (i == GOPT_LAST-1  strlen(q)) {

Spaces around '-'.

 +GlusterOpts[i].value = g_strdup(q);
 +ret = 0;
 +}
 +g_free(r);
 +return ret;
 +}
 +
 +static struct glfs *qemu_gluster_init(const char *filename)
 +{
 +struct glfs *glfs = NULL;
 +int ret;
 +int port;
 +
 +ret = qemu_gluster_parsename(filename);
 +if (ret  0) {
 +errno = -ret;
 +goto out;
 +}
 +
 +port = strtoul(GlusterOpts[GOPT_PORT].value, NULL, 0);
 +if 

Re: [Qemu-devel] [PATCH v3 2/2] block: Support GlusterFS as a QEMU block backend

2012-07-27 Thread Bharata B Rao
On Fri, Jul 27, 2012 at 06:44:04PM +, Blue Swirl wrote:
  +struct GlusterOpts {
 
 static

Sure.

 
  +bool optional;
  +char defval[10];
 
 const char *defval?

Sure I could.

 
  +char *value;
  +} GlusterOpts[] = {
  +{false, , NULL },
  +{false, , NULL },
  +{true, 0, NULL },
  +{true, socket, NULL },
  +{false, , NULL },
  +{false, , NULL },
  +};
  +
  +if (i == GOPT_LAST-1  strlen(q)) {
 
 Spaces around '-'.

checkpatch.pl doesn't enforce this, but I can change.

  +
  +port = strtoul(GlusterOpts[GOPT_PORT].value, NULL, 0);
  +if (port  0) {
 
 port  65535 could be bad too.

Actually I am just checking if strtoul gave me a valid integer only
and depending on gluster to flag an error for invalid port number.
But I guess no harm in checking for valid port range here. Is there
a #define equivalent for 65535 ?

 
  +
  +fd = glfs_creat(glfs, GlusterOpts[GOPT_IMAGE].value,
  +O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR);
 
 Spaces around '|'.

Again, checkpatch.pl doesn't enforce this, but I can change.

Thanks for take time to review.

Regards,
Bharata.




[Qemu-devel] [PATCH v3 2/2] block: Support GlusterFS as a QEMU block backend

2012-07-24 Thread Bharata B Rao
block: Support GlusterFS as a QEMU block backend.

From: Bharata B Rao bhar...@linux.vnet.ibm.com

This patch adds gluster as the new block backend in QEMU. This gives
QEMU the ability to boot VM images from gluster volumes. Its already
possible to boot from VM images on gluster volumes, but this patchset
provides the ability to boot VM images from gluster volumes by by-passing
the FUSE layer in gluster. In case the image is present on the local
system, it is possible to even bypass client and server translator and
hence the RPC overhead.

VM Image on gluster volume is specified like this:

-drive file=gluster:server:[port]:[transport]:volname:image

- Here 'gluster' is the protocol.
- 'server' specifies the server where the volume file specification for
  the given volume resides.
- 'port' is the port number on which gluster management daemon (glusterd) is
   listening. This is optional and if not specified, QEMU will send 0 which
   will make libgfapi to use the default port.
- 'transport' specifies the transport used to connect to glusterd. This is
  optional and if not specified, socket transport is used.
- 'volname' is the name of the gluster volume which contains the VM image.
- 'image' is the path to the actual VM image in the gluster volume.

Eg 1: -drive file=gluster:server1:0:socket:test:/image
Eg 2: -drive file=gluster:server1:::test:/image

Signed-off-by: Bharata B Rao bhar...@linux.vnet.ibm.com
---

 block/Makefile.objs |1 
 block/gluster.c |  484 +++
 2 files changed, 485 insertions(+), 0 deletions(-)
 create mode 100644 block/gluster.c


diff --git a/block/Makefile.objs b/block/Makefile.objs
index b5754d3..a1ae67f 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -9,3 +9,4 @@ block-obj-$(CONFIG_POSIX) += raw-posix.o
 block-obj-$(CONFIG_LIBISCSI) += iscsi.o
 block-obj-$(CONFIG_CURL) += curl.o
 block-obj-$(CONFIG_RBD) += rbd.o
+block-obj-$(CONFIG_GLUSTERFS) += gluster.o
diff --git a/block/gluster.c b/block/gluster.c
new file mode 100644
index 000..b27971b
--- /dev/null
+++ b/block/gluster.c
@@ -0,0 +1,484 @@
+/*
+ * GlusterFS backend for QEMU
+ *
+ * (AIO implementation is derived from block/rbd.c)
+ *
+ * Copyright (C) 2012 Bharata B Rao bhar...@linux.vnet.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+#include block_int.h
+#include glusterfs/api/glfs.h
+
+typedef struct GlusterAIOCB {
+BlockDriverAIOCB common;
+bool canceled;
+int64_t size;
+int ret;
+} GlusterAIOCB;
+
+typedef struct BDRVGlusterState {
+struct glfs *glfs;
+int fds[2];
+struct glfs_fd *fd;
+int qemu_aio_count;
+} BDRVGlusterState;
+
+#define GLUSTER_FD_READ 0
+#define GLUSTER_FD_WRITE 1
+
+typedef enum {
+GOPT_PROTOCOL,
+GOPT_SERVER,
+GOPT_PORT,
+GOPT_TRANSPORT,
+GOPT_VOLNAME,
+GOPT_IMAGE,
+
+GOPT_LAST,
+} GlusterOptsEnum;
+
+struct GlusterOpts {
+bool optional;
+char defval[10];
+char *value;
+} GlusterOpts[] = {
+{false, , NULL },
+{false, , NULL },
+{true, 0, NULL },
+{true, socket, NULL },
+{false, , NULL },
+{false, , NULL },
+};
+
+static void qemu_gluster_opts_free(void)
+{
+int i;
+
+for (i = 0; i  GOPT_LAST; i++) {
+g_free(GlusterOpts[i].value);
+/* Prepare GlusterOpts to parse the next gluster drive (if any) */
+GlusterOpts[i].value = NULL;
+}
+}
+
+/*
+ * file=protocol:server:[port]:[transport]:volname:image
+ */
+static int qemu_gluster_parsename(const char *filename)
+{
+char *p, *q, *r;
+int ret = -EINVAL;
+int i;
+
+p = q = r = g_strdup(filename);
+for (i = 0; i  GOPT_LAST; i++) {
+q = p;
+p = strchr(p, ':');
+if (!p) {
+goto out;
+}
+
+if (p == q) {
+if (GlusterOpts[i].optional) {
+GlusterOpts[i].value = g_strdup(GlusterOpts[i].defval);
+p++;
+continue;
+} else {
+goto out;
+}
+}
+*p++ = '\0';
+GlusterOpts[i].value = g_strdup(q);
+}
+out:
+if (i == GOPT_LAST-1  strlen(q)) {
+GlusterOpts[i].value = g_strdup(q);
+ret = 0;
+}
+g_free(r);
+return ret;
+}
+
+static struct glfs *qemu_gluster_init(const char *filename)
+{
+struct glfs *glfs = NULL;
+int ret;
+int port;
+
+ret = qemu_gluster_parsename(filename);
+if (ret  0) {
+errno = -ret;
+goto out;
+}
+
+port = strtoul(GlusterOpts[GOPT_PORT].value, NULL, 0);
+if (port  0) {
+goto out;
+}
+
+glfs = glfs_new(GlusterOpts[GOPT_VOLNAME].value);
+if (!glfs) {
+goto out;
+}
+
+ret = glfs_set_volfile_server(glfs, GlusterOpts[GOPT_TRANSPORT].value,
+GlusterOpts[GOPT_SERVER].value, port);
+if (ret  0) {
+goto