diff mbox

[v4,2/3] block/archipelago: Add support for creating images

Message ID 1403189328-18457-3-git-send-email-cnanakos@grnet.gr
State New
Headers show

Commit Message

Chrysostomos Nanakos June 19, 2014, 2:48 p.m. UTC
qemu-img archipelago:<volumename>[/mport=<mapperd_port>[:vport=<vlmcd_port>]]
[size]

Signed-off-by: Chrysostomos Nanakos <cnanakos@grnet.gr>
---
 block/archipelago.c |  137 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 137 insertions(+)

Comments

Stefan Hajnoczi June 20, 2014, 2:35 p.m. UTC | #1
On Thu, Jun 19, 2014 at 05:48:47PM +0300, Chrysostomos Nanakos wrote:
> +static int qemu_archipelago_create_volume(Error **errp, const char *volname,
> +                                          uint64_t size, xport mportno,
> +                                          xport vportno)
> +{
> +    int ret, targetlen;
> +    struct xseg *xseg = NULL;
> +    struct xseg_request *req;
> +    struct xseg_request_clone *xclone;
> +    struct xseg_port *port;
> +    xport srcport = NoPort, sport = NoPort;
> +    char *target;
> +
> +    /* Try default values if none has been set */
> +    if (mportno == (xport) -1) {
> +        mportno = 1001;
> +    }
> +
> +    if (vportno == (xport) -1) {
> +        vportno = 501;
> +    }
> +
> +    if (xseg_initialize()) {
> +        error_setg(errp, "Cannot initialize XSEG");
> +        return -1;
> +    }
> +
> +    xseg = xseg_join((char *)"posix", (char *)"archipelago",
> +                     (char *)"posixfd", NULL);
> +
> +    if (!xseg) {
> +        error_setg(errp, "Cannot join XSEG shared memory segment");
> +        return -1;
> +    }
> +
> +    port = xseg_bind_dynport(xseg);
> +    srcport = port->portno;
> +    init_local_signal(xseg, sport, srcport);
> +
> +    req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
> +    if (!req) {
> +        error_setg(errp, "Cannot get XSEG request");
> +        return -1;

xseg_leave() is missing.
diff mbox

Patch

diff --git a/block/archipelago.c b/block/archipelago.c
index 3da7a1c..4553b2d 100644
--- a/block/archipelago.c
+++ b/block/archipelago.c
@@ -32,6 +32,7 @@ 
  * or implied, of GRNET S.A.
  */
 
+#include "qemu-common.h"
 #include "block/block_int.h"
 #include "qemu/error-report.h"
 #include "qemu/thread.h"
@@ -573,6 +574,127 @@  err_exit:
     xseg_leave(s->xseg);
 }
 
+static int qemu_archipelago_create_volume(Error **errp, const char *volname,
+                                          uint64_t size, xport mportno,
+                                          xport vportno)
+{
+    int ret, targetlen;
+    struct xseg *xseg = NULL;
+    struct xseg_request *req;
+    struct xseg_request_clone *xclone;
+    struct xseg_port *port;
+    xport srcport = NoPort, sport = NoPort;
+    char *target;
+
+    /* Try default values if none has been set */
+    if (mportno == (xport) -1) {
+        mportno = 1001;
+    }
+
+    if (vportno == (xport) -1) {
+        vportno = 501;
+    }
+
+    if (xseg_initialize()) {
+        error_setg(errp, "Cannot initialize XSEG");
+        return -1;
+    }
+
+    xseg = xseg_join((char *)"posix", (char *)"archipelago",
+                     (char *)"posixfd", NULL);
+
+    if (!xseg) {
+        error_setg(errp, "Cannot join XSEG shared memory segment");
+        return -1;
+    }
+
+    port = xseg_bind_dynport(xseg);
+    srcport = port->portno;
+    init_local_signal(xseg, sport, srcport);
+
+    req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
+    if (!req) {
+        error_setg(errp, "Cannot get XSEG request");
+        return -1;
+    }
+
+    targetlen = strlen(volname);
+    ret = xseg_prep_request(xseg, req, targetlen,
+                            sizeof(struct xseg_request_clone));
+    if (ret < 0) {
+        error_setg(errp, "Cannot prepare XSEG request");
+        goto err_exit;
+    }
+
+    target = xseg_get_target(xseg, req);
+    if (!target) {
+        error_setg(errp, "Cannot get XSEG target.\n");
+        goto err_exit;
+    }
+    strncpy(target, volname, targetlen);
+    xclone = (struct xseg_request_clone *) xseg_get_data(xseg, req);
+    memset(xclone->target, 0 , XSEG_MAX_TARGETLEN);
+    xclone->targetlen = 0;
+    xclone->size = size * BDRV_SECTOR_SIZE;
+    req->offset = 0;
+    req->size = req->datalen;
+    req->op = X_CLONE;
+
+    xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
+    if (p == NoPort) {
+        error_setg(errp, "Could not submit XSEG request");
+        goto err_exit;
+    }
+    xseg_signal(xseg, p);
+
+    ret = wait_reply(xseg, srcport, port, req);
+    if (ret < 0) {
+        error_setg(errp, "wait_reply() error.");
+    }
+
+    xseg_put_request(xseg, req, srcport);
+    xseg_leave_dynport(xseg, port);
+    xseg_leave(xseg);
+    return ret;
+
+err_exit:
+    xseg_put_request(xseg, req, srcport);
+    xseg_leave_dynport(xseg, port);
+    xseg_leave(xseg);
+    return -1;
+}
+
+static int qemu_archipelago_create(const char *filename,
+                                   QemuOpts *options,
+                                   Error **errp)
+{
+    int ret = 0;
+    uint64_t total_size = 0;
+    char *volname = NULL;
+    const char *start;
+    xport mport = NoPort, vport = NoPort;
+
+    if (!strstart(filename, "archipelago:", &start)) {
+        error_setg(errp, "File name must start with 'archipelago:'");
+        return -1;
+    }
+
+    if (!strlen(start) || strstart(start, "/", NULL)) {
+        error_setg(errp, "volume name must be specified");
+        return -1;
+    }
+
+    parse_filename_opts(filename, errp, &volname, &mport, &vport);
+    total_size = qemu_opt_get_size_del(options, BLOCK_OPT_SIZE, 0) / \
+                 BDRV_SECTOR_SIZE;
+
+    /* Create an Archipelago volume */
+    ret = qemu_archipelago_create_volume(errp, volname, total_size, mport,
+                                         vport);
+    g_free(volname);
+    return ret;
+}
+
 static void qemu_archipelago_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) blockacb;
@@ -1017,6 +1139,19 @@  static int64_t qemu_archipelago_getlength(BlockDriverState *bs)
     return ret;
 }
 
+static QemuOptsList qemu_archipelago_create_opts = {
+    .name = "archipelago-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "Virtual disk size"
+        },
+        { /* end of list */ }
+    }
+};
+
 static BlockDriverAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
@@ -1031,11 +1166,13 @@  static BlockDriver bdrv_archipelago = {
     .bdrv_parse_filename = archipelago_parse_filename,
     .bdrv_file_open      = qemu_archipelago_open,
     .bdrv_close          = qemu_archipelago_close,
+    .bdrv_create         = qemu_archipelago_create,
     .bdrv_getlength      = qemu_archipelago_getlength,
     .bdrv_aio_readv      = qemu_archipelago_aio_readv,
     .bdrv_aio_writev     = qemu_archipelago_aio_writev,
     .bdrv_aio_flush      = qemu_archipelago_aio_flush,
     .bdrv_has_zero_init  = bdrv_has_zero_init_1,
+    .create_opts         = &qemu_archipelago_create_opts,
 };
 
 static void bdrv_archipelago_init(void)