On Mon, Aug 20, 2012 at 11:47 AM, Benoît Canet <benoit.ca...@gmail.com> wrote: > Valid quorum resources look like: > quorum:threshold/total:path/to/image_1: ... :path/to/image_total > > '\' can escape the ':' character. > > Signed-off-by: Benoit Canet <ben...@irqsave.net> > --- > block/quorum.c | 110 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 110 insertions(+) > > diff --git a/block/quorum.c b/block/quorum.c > index 19a9a44..70e7216 100644 > --- a/block/quorum.c > +++ b/block/quorum.c > @@ -52,11 +52,121 @@ struct QuorumAIOCB { > int vote_ret; > }; > > +/* Valid quorum resources look like > + * quorum:threshold/total:path/to/image_1: ... :path/to/image_total > + */ > +static int quorum_open(BlockDriverState *bs, const char *filename, int flags) > +{ > + BDRVQuorumState *s = bs->opaque; > + int i, j, 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 n */
Here's still 'n' instead of threshold. > + errno = 0; > + s->threshold = strtoul(filename, &a, 10); > + if (*a != '/' || errno) { > + return -EINVAL; > + } > + a++; > + > + /* Get m */ Also 'm' here. > + 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 = 0, j = 1; i < len && j < s->total; i++) { > + if (!escape && names[i] == ':') { > + names[i] = '\0'; > + s->filenames[j] = names + i + 1; > + j++; > + } > + > + escape = !escape && names[i] == '\\'; > + } > + > + if (j != 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 >