sheepdog: QAPIfy "redundancy" create option

The "redundancy" option for Sheepdog image creation is currently a
string that can encode one or two integers depending on its format,
which at the same time implicitly selects a mode.

This patch turns it into a QAPI union and converts the string into such
a QAPI object before interpreting the values.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Kevin Wolf 2018-02-01 17:26:27 +01:00
parent a1a42af422
commit a595e4bcca
2 changed files with 113 additions and 28 deletions

View file

@ -1882,48 +1882,28 @@ out_with_err_set:
return ret; return ret;
} }
/* static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
* Sheepdog support two kinds of redundancy, full replication and erasure
* coding.
*
* # create a fully replicated vdi with x copies
* -o redundancy=x (1 <= x <= SD_MAX_COPIES)
*
* # create a erasure coded vdi with x data strips and y parity strips
* -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
*/
static int parse_redundancy(BDRVSheepdogState *s, const char *opt)
{ {
struct SheepdogInode *inode = &s->inode; struct SheepdogInode *inode = &s->inode;
const char *n1, *n2;
long copy, parity;
char p[10];
pstrcpy(p, sizeof(p), opt); switch (opt->type) {
n1 = strtok(p, ":"); case SHEEPDOG_REDUNDANCY_TYPE_FULL:
n2 = strtok(NULL, ":"); if (opt->u.full.copies > SD_MAX_COPIES || opt->u.full.copies < 1) {
if (!n1) {
return -EINVAL; return -EINVAL;
} }
copy = strtol(n1, NULL, 10);
/* FIXME fix error checking by switching to qemu_strtol() */
if (copy > SD_MAX_COPIES || copy < 1) {
return -EINVAL;
}
if (!n2) {
inode->copy_policy = 0; inode->copy_policy = 0;
inode->nr_copies = copy; inode->nr_copies = opt->u.full.copies;
return 0; return 0;
}
case SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED:
{
int64_t copy = opt->u.erasure_coded.data_strips;
int64_t parity = opt->u.erasure_coded.parity_strips;
if (copy != 2 && copy != 4 && copy != 8 && copy != 16) { if (copy != 2 && copy != 4 && copy != 8 && copy != 16) {
return -EINVAL; return -EINVAL;
} }
parity = strtol(n2, NULL, 10);
/* FIXME fix error checking by switching to qemu_strtol() */
if (parity >= SD_EC_MAX_STRIP || parity < 1) { if (parity >= SD_EC_MAX_STRIP || parity < 1) {
return -EINVAL; return -EINVAL;
} }
@ -1934,10 +1914,70 @@ static int parse_redundancy(BDRVSheepdogState *s, const char *opt)
*/ */
inode->copy_policy = ((copy / 2) << 4) + parity; inode->copy_policy = ((copy / 2) << 4) + parity;
inode->nr_copies = copy + parity; inode->nr_copies = copy + parity;
return 0; return 0;
} }
default:
g_assert_not_reached();
}
return -EINVAL;
}
/*
* Sheepdog support two kinds of redundancy, full replication and erasure
* coding.
*
* # create a fully replicated vdi with x copies
* -o redundancy=x (1 <= x <= SD_MAX_COPIES)
*
* # create a erasure coded vdi with x data strips and y parity strips
* -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
*/
static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
{
struct SheepdogRedundancy redundancy;
const char *n1, *n2;
long copy, parity;
char p[10];
int ret;
pstrcpy(p, sizeof(p), opt);
n1 = strtok(p, ":");
n2 = strtok(NULL, ":");
if (!n1) {
return -EINVAL;
}
ret = qemu_strtol(n1, NULL, 10, &copy);
if (ret < 0) {
return ret;
}
if (!n2) {
redundancy = (SheepdogRedundancy) {
.type = SHEEPDOG_REDUNDANCY_TYPE_FULL,
.u.full.copies = copy,
};
} else {
ret = qemu_strtol(n2, NULL, 10, &parity);
if (ret < 0) {
return ret;
}
redundancy = (SheepdogRedundancy) {
.type = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED,
.u.erasure_coded = {
.data_strips = copy,
.parity_strips = parity,
},
};
}
return parse_redundancy(s, &redundancy);
}
static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt) static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
{ {
struct SheepdogInode *inode = &s->inode; struct SheepdogInode *inode = &s->inode;
@ -2007,7 +2047,7 @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
g_free(buf); g_free(buf);
buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY); buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
if (buf) { if (buf) {
ret = parse_redundancy(s, buf); ret = parse_redundancy_str(s, buf);
if (ret < 0) { if (ret < 0) {
error_setg(errp, "Invalid redundancy mode: '%s'", buf); error_setg(errp, "Invalid redundancy mode: '%s'", buf);
goto out; goto out;

View file

@ -3466,6 +3466,51 @@
'size': 'size', 'size': 'size',
'*cluster-size' : 'size' } } '*cluster-size' : 'size' } }
##
# @SheepdogRedundancyType:
#
# @full Create a fully replicated vdi with x copies
# @erasure-coded Create an erasure coded vdi with x data strips and
# y parity strips
#
# Since: 2.12
##
{ 'enum': 'SheepdogRedundancyType',
'data': [ 'full', 'erasure-coded' ] }
##
# @SheepdogRedundancyFull:
#
# @copies Number of copies to use (between 1 and 31)
#
# Since: 2.12
##
{ 'struct': 'SheepdogRedundancyFull',
'data': { 'copies': 'int' }}
##
# @SheepdogRedundancyErasureCoded:
#
# @data-strips Number of data strips to use (one of {2,4,8,16})
# @parity-strips Number of parity strips to use (between 1 and 15)
#
# Since: 2.12
##
{ 'struct': 'SheepdogRedundancyErasureCoded',
'data': { 'data-strips': 'int',
'parity-strips': 'int' }}
##
# @SheepdogRedundancy:
#
# Since: 2.12
##
{ 'union': 'SheepdogRedundancy',
'base': { 'type': 'SheepdogRedundancyType' },
'discriminator': 'type',
'data': { 'full': 'SheepdogRedundancyFull',
'erasure-coded': 'SheepdogRedundancyErasureCoded' } }
## ##
# @BlockdevCreateNotSupported: # @BlockdevCreateNotSupported:
# #