qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Benoît Canet" <benoit.canet@gmail.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, stefanha@linux.vnet.ibm.com,
	blauwirbel@gmail.com, pbonzini@redhat.com, eblake@redhat.com,
	"Benoît Canet" <benoit@irqsave.net>
Subject: [Qemu-devel] [RFC V5 03/11] quorum: Add quorum_open() and quorum_close().
Date: Mon, 27 Aug 2012 09:30:21 +0200	[thread overview]
Message-ID: <1346052629-15686-4-git-send-email-benoit@irqsave.net> (raw)
In-Reply-To: <1346052629-15686-1-git-send-email-benoit@irqsave.net>

Valid quorum resources look like
quorum:threshold/total:path/to/image_1, ... ,path/to/image_total

',' is used as a separator to allow to use networked path
'\' is the escaping character for filename containing ','
'\' escape itself

On the command line for quorum files "img,test.raw", "img2.raw"
and "img3.raw" invocation look like:

-drive file=quorum:2/3:img\\,,test.raw,,img2.raw,,img3.raw
(note the double ,, and \\)

Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 block/quorum.c |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/block/quorum.c b/block/quorum.c
index 19a9a44..b9fb2b9 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -52,11 +52,134 @@ struct QuorumAIOCB {
     int vote_ret;
 };
 
+/* Valid quorum resources look like
+ * quorum:threshold/total:path/to/image_1, ... ,path/to/image_total
+ *
+ * ',' is used as a separator to allow to use network path
+ * '\' is the escaping character for filename containing ','
+ */
+static int quorum_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVQuorumState *s = bs->opaque;
+    int i, j, k, len, ret = 0;
+    char *a, *b, *names;
+    bool escape;
+
+    /* Parse the quorum: prefix */
+    if (strncmp(filename, "quorum:", strlen("quorum:"))) {
+        return -EINVAL;
+    }
+
+    filename += strlen("quorum:");
+
+    /* Get threshold */
+    errno = 0;
+    s->threshold = strtoul(filename, &a, 10);
+    if (*a != '/' || errno) {
+        return -EINVAL;
+    }
+    a++;
+
+    /* Get total */
+    errno = 0;
+    s->total = strtoul(a, &b, 10);
+    if (*b != ':' || errno) {
+        return -EINVAL;
+    }
+    b++;
+
+    if (s->threshold < 1 || s->total < 2) {
+        return -EINVAL;
+    }
+
+    if (s->threshold > s->total) {
+        return -EINVAL;
+    }
+
+    s->bs = g_malloc0(sizeof(BlockDriverState *) * s->total);
+    /* Two allocations for all filenames: simpler to free */
+    s->filenames = g_malloc0(sizeof(char *) * s->total);
+    names = g_strdup(b);
+
+    /* Get the filenames pointers */
+    escape = false;
+    s->filenames[0] = names;
+    len = strlen(names);
+    for (i = j = k = 0; i < len && j < s->total; i++) {
+        /* separation between two files */
+        if (!escape && names[i] == ',') {
+            char *prev = s->filenames[j];
+            prev[k] = '\0';
+            s->filenames[++j] = prev + k + 1;
+            k = 0;
+            continue;
+        }
+
+        escape = !escape && names[i] == '\\';
+
+        /* if we are not escaping copy */
+        if (!escape) {
+            s->filenames[j][k++] = names[i];
+        }
+    }
+    /* terminate last string */
+    s->filenames[j][k] = '\0';
+
+    if ((j + 1) != s->total) {
+        ret = -EINVAL;
+        goto free_exit;
+    }
+
+    /* Open files */
+    for (i = 0; i < s->total; i++) {
+        s->bs[i] = bdrv_new("");
+        ret = bdrv_open(s->bs[i], s->filenames[i], flags, NULL);
+        if (ret < 0) {
+            goto error_exit;
+        }
+    }
+
+    goto exit;
+
+error_exit:
+    for (; i >= 0; i--) {
+        bdrv_delete(s->bs[i]);
+        s->bs[i] = NULL;
+    }
+free_exit:
+    g_free(s->filenames[0]);
+    g_free(s->filenames);
+    s->filenames = NULL;
+    g_free(s->bs);
+exit:
+    return ret;
+}
+
+static void quorum_close(BlockDriverState *bs)
+{
+    BDRVQuorumState *s = bs->opaque;
+    int i;
+
+    for (i = 0; i < s->total; i++) {
+        /* Ensure writes reach stable storage */
+        bdrv_flush(s->bs[i]);
+        bdrv_delete(s->bs[i]);
+    }
+
+    g_free(s->filenames[0]);
+    g_free(s->filenames);
+    s->filenames = NULL;
+    g_free(s->bs);
+}
+
 static BlockDriver bdrv_quorum = {
     .format_name        = "quorum",
     .protocol_name      = "quorum",
 
     .instance_size      = sizeof(BDRVQuorumState),
+
+    .bdrv_file_open     = quorum_open,
+    .bdrv_close         = quorum_close,
 };
 
 static void bdrv_quorum_init(void)
-- 
1.7.9.5

  parent reply	other threads:[~2012-08-27  7:30 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-27  7:30 [Qemu-devel] [RFC V5 00/11] Quorum disk image corruption resiliency Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 01/11] quorum: Create quorum.c, add QuorumSingleAIOCB and QuorumAIOCB Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 02/11] quorum: Create BDRVQuorumState and BlkDriver and do init Benoît Canet
2012-08-27  7:30 ` Benoît Canet [this message]
2012-08-27 17:59   ` [Qemu-devel] [RFC V5 03/11] quorum: Add quorum_open() and quorum_close() Eric Blake
2012-08-27 19:20     ` Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 04/11] quorum: Add quorum_aio_writev and its dependencies Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 05/11] blkverify: Extract qemu_iovec_clone() and qemu_iovec_compare() from blkverify Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 06/11] quorum: Add quorum_co_flush() Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 07/11] quorum: Add quorum_aio_readv Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 08/11] quorum: Add quorum mechanism Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 09/11] quorum: Add quorum_getlength() Benoît Canet
2012-08-27 18:03   ` Eric Blake
2012-08-27 19:23     ` Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 10/11] quorum: Add quorum_invalidate_cache() Benoît Canet
2012-08-27  7:30 ` [Qemu-devel] [RFC V5 11/11] quorum: Add quorum_co_is_allocated Benoît Canet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1346052629-15686-4-git-send-email-benoit@irqsave.net \
    --to=benoit.canet@gmail.com \
    --cc=benoit@irqsave.net \
    --cc=blauwirbel@gmail.com \
    --cc=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).